Advertisement
Guest User

Autocomplete

a guest
Jul 30th, 2013
138
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #NoEnv
  2.  
  3. #Warn All
  4. #Warn LocalSameAsGlobal, Off
  5.  
  6. SetBatchLines, -1
  7.  
  8. GroupAdd, excludedWins, ahk_class CabinetWClass ; windows explorer
  9. GroupAdd, excludedWins, ahk_class DV2ControlHost ; start menu search bar
  10. GroupAdd, excludedWins, ahk_class ConsoleWindowClass ; console
  11.  
  12. WordListFile := A_ScriptDir . "\WordList.txt" ;path of the wordlist file
  13. SettingsFile := A_ScriptDir . "\Settings.ini" ;path of the settings file
  14.  
  15. MaxResults := 20 ;maximum number of results to display
  16. OffsetX := 0 ;offset in caret position in X axis
  17. OffsetY := 20 ;offset from caret position in Y axis
  18. BoxHeight := 165 ;height of the suggestions box in pixels
  19. ShowLength := 4 ;minimum length of word before showing suggestions
  20. CorrectCase := True ;whether or not to fix uppercase or lowercase to match the suggestion
  21.  
  22. NormKeyList := "a`nb`nc`nd`ne`nf`ng`nh`ni`nj`nk`nl`nm`nn`no`np`nq`nr`ns`nt`nu`nv`nw`nx`ny`nz" ;list of key names separated by `n that make up words in upper and lower case variants
  23. NumberKeyList := "1`n2`n3`n4`n5`n6`n7`n8`n9`n0" ;list of key names separated by `n that make up words as well as their numpad equivalents
  24. OtherKeyList := "'`n-" ;list of key names separated by `n that make up words
  25. ResetKeyList := "Esc`nSpace`nHome`nPGUP`nPGDN`nEnd`nLeft`nRight`nRButton`nMButton`n,`n.`n/`n[`n]`n;`n\`n=`n```n"""  ;list of key names separated by `n that cause suggestions to reset
  26. TriggerKeyList := "Tab`nEnter" ;list of key names separated by `n that trigger completion
  27.  
  28. IniRead, MaxResults, %SettingsFile%, Settings, MaxResults, %MaxResults%
  29. IniRead, ShowLength, %SettingsFile%, Settings, ShowLength, %ShowLength%
  30. IniRead, CorrectCase, %SettingsFile%, Settings, CorrectCase, %CorrectCase%
  31.  
  32. TrayTip, Settings, Click the tray icon to modify settings, 5, 1
  33.  
  34. SetTitleMatchMode, RegEx
  35. CoordMode, Caret
  36. SetKeyDelay, 0
  37. SendMode, Input
  38.  
  39. ;obtain desktop size across all monitors
  40. SysGet, ScreenWidth, 78
  41. SysGet, ScreenHeight, 79
  42.  
  43. FileRead, WordList, %WordListFile%
  44. PrepareWordList(WordList)
  45.  
  46. ;set up tray menu
  47. Menu, Tray, NoStandard
  48. Menu, Tray, Click, 1
  49. Menu, Tray, Add, Settings, ShowSettings
  50. Menu, Tray, Add
  51. Menu, Tray, Add, Exit, ExitScript
  52. Menu, Tray, Default, Settings
  53.  
  54. ;set up suggestions window
  55. Gui, Suggestions:Default
  56. Gui, Font, s10, Courier New
  57. Gui, Add, ListBox, x0 y0 h%BoxHeight% 0x100 vMatched gCompleteWord AltSubmit
  58. Gui, -Caption +ToolWindow +AlwaysOnTop +LastFound
  59. hWindow := WinExist()
  60. Gui, Show, h%BoxHeight% Hide, AutoComplete
  61.  
  62. Gosub, ResetWord
  63.  
  64. SetHotkeys(NormKeyList,NumberKeyList,OtherKeyList,ResetKeyList,TriggerKeyList)
  65.  
  66. OnExit, ExitSub
  67. Return
  68.  
  69. ExitSub:
  70. Gui, Settings:Submit
  71.  
  72. ;write settings
  73. IniWrite, %MaxResults%, %SettingsFile%, Settings, MaxResults
  74. IniWrite, %ShowLength%, %SettingsFile%, Settings, ShowLength
  75. IniWrite, %CorrectCase%, %SettingsFile%, Settings, CorrectCase
  76.  
  77. ;write wordlist file
  78. File := FileOpen(WordListFile,"w")
  79. File.Seek(0)
  80. Length := File.Write(WordList)
  81. File.Length := Length
  82. ExitApp
  83.  
  84. ExitScript:
  85. ExitApp
  86.  
  87. ShowSettings:
  88. ;do not show settings window if already shown
  89. Gui, Settings:+LastFoundExist
  90. If WinExist()
  91.     Return
  92.  
  93. Gui, Settings:Default
  94. Gui, Font,, Arial
  95. Gui, Font,, Century Gothic
  96. Gui, Color, White, FFF8F8
  97.  
  98. Gui, Font, s24 cFFAAAA
  99. Gui, Add, Text, x10 y10 w540 h45 Center, a u t o c o m p l e t e
  100. Gui, Add, Progress, x10 y55 w540 h1 BackgroundEEDDDD, 0
  101.  
  102. Gui, Font, s14 c885555
  103. Gui, Add, Text, x10 y73 w180 h30, RESULT LIMIT
  104. Gui, Add, Edit, x190 y70 w80 h30 Right Number
  105. Gui, Add, UpDown, Range1-100 vMaxResults, %MaxResults%
  106. Gui, Add, Text, x10 y113 w180 h30, TRIGGER LENGTH
  107. Gui, Add, Edit, x190 y110 w80 h30 Right Number
  108. Gui, Add, UpDown, Range1-10, %ShowLength%
  109.  
  110. Gui, Add, Checkbox, x10 y150 w260 h30 Checked%CorrectCase% vCorrectCase, CASE CORRECTION
  111.  
  112. Gui, Add, Edit, x10 y210 w230 h30 vNewWord
  113. Gui, Add, Button, x240 y210 w30 h30 Disabled vAddWord gAddWord, +
  114. Gui, Add, Button, x10 y250 w260 h40 Disabled vRemoveWord gRemoveWord, REMOVE SELECTED
  115. Gui, Font, s8, Courier New
  116. Gui, Add, ListView, x290 y70 w260 h220 -Hdr vWords, Words
  117.  
  118. Gui, Color, White
  119. Gui, +ToolWindow +AlwaysOnTop
  120. Gui, Show, w560 h300, Autocomplete by Uberi
  121.  
  122. LV_Add("", "Reading wordlist...")
  123. Sleep, 0
  124.  
  125. ;populate list with entries from wordlist
  126. GuiControl, -Redraw, Words
  127. Loop, Parse, WordList, `n
  128.     LV_Add("", A_LoopField)
  129. LV_Delete(1)
  130. GuiControl, +Redraw, Words
  131.  
  132. GuiControl, Enable, AddWord
  133. GuiControl, Enable, RemoveWord
  134. Return
  135.  
  136. SettingsGuiEscape:
  137. SettingsGuiClose:
  138. Gui, Settings:Default
  139. Gui, Submit
  140. Gui, Destroy
  141. Return
  142.  
  143. AddWord:
  144. Gui, Settings:Default
  145. GuiControlGet, NewWord,, NewWord
  146. Index := LV_Add("Select Focus", NewWord)
  147. LV_Modify(Index, "Vis")
  148. WordList .= "`n" . NewWord
  149. Return
  150.  
  151. RemoveWord:
  152. Gui, Settings:Default
  153. TempList := "`n" . WordList . "`n"
  154. GuiControl, -Redraw, Words
  155. While, CurrentRow := LV_GetNext()
  156. {
  157.     LV_Delete(CurrentRow)
  158.     Position := InStr(TempList,"`n",True,1,CurrentRow)
  159.     TempList := SubStr(TempList,1,Position) . SubStr(TempList,InStr(TempList,"`n",True,Position + 1) + 1)
  160. }
  161. GuiControl, +Redraw, Words
  162. WordList := SubStr(TempList,2,-1)
  163. Return
  164.  
  165. #IfWinExist AutoComplete ahk_class AutoHotkeyGUI
  166.  
  167. ~LButton::
  168. MouseGetPos,,, Temp1
  169. If (Temp1 != hWindow)
  170.     Gosub, ResetWord
  171. Return
  172.  
  173. Up::
  174. Gui, Suggestions:Default
  175. GuiControlGet, Temp1,, Matched
  176. If Temp1 > 1 ;ensure value is in range
  177.     GuiControl, Choose, Matched, % Temp1 - 1
  178. Return
  179.  
  180. Down::
  181. Gui, Suggestions:Default
  182. GuiControlGet, Temp1,, Matched
  183. GuiControl, Choose, Matched, % Temp1 + 1
  184. Return
  185.  
  186. #IfWinExist
  187.  
  188. ~BackSpace::
  189. CurrentWord := SubStr(CurrentWord,1,-1)
  190. Gosub, Suggest
  191. Return
  192.  
  193. Key:
  194. CurrentWord .= SubStr(A_ThisHotkey,2)
  195. Gosub, Suggest
  196. Return
  197.  
  198. ShiftedKey:
  199. Char := SubStr(A_ThisHotkey,3)
  200. StringUpper, Char, Char
  201. CurrentWord .= Char
  202. Gosub, Suggest
  203. Return
  204.  
  205. NumpadKey:
  206. CurrentWord .= SubStr(A_ThisHotkey,8)
  207. Gosub, Suggest
  208. Return
  209.  
  210. ResetWord:
  211. CurrentWord := ""
  212. Gui, Suggestions:Hide
  213. Return
  214.  
  215. Suggest:
  216. IfWinActive, ahk_group excludedWins
  217. {
  218.     return
  219. }
  220. Gui, Suggestions:Default
  221.  
  222. ;check word length against minimum length
  223. If StrLen(CurrentWord) < ShowLength
  224. {
  225.     Gui, Hide
  226.     Return
  227. }
  228.  
  229. MatchList := Suggest(CurrentWord,WordList)
  230.  
  231. ;check for a lack of matches
  232. If (MatchList = "")
  233. {
  234.     Gui, Hide
  235.     Return
  236. }
  237.  
  238. ;limit the number of results
  239. Position := InStr(MatchList,"|",True,1,MaxResults)
  240. If Position
  241.     MatchList := SubStr(MatchList,1,Position - 1)
  242.  
  243. ;find the longest text width
  244. MaxWidth := 0
  245. Loop, Parse, MatchList, |
  246. {
  247.     Width := TextWidth(A_LoopField)
  248.     If (Width > MaxWidth)
  249.         MaxWidth := Width
  250. }
  251. MaxWidth += 30 ;add room for the scrollbar
  252.  
  253. ;update the interface
  254. GuiControl,, Matched, |%MatchList%
  255. GuiControl, Choose, Matched, 1
  256. GuiControl, Move, Matched, w%MaxWidth%
  257. PosX := A_CaretX + OffsetX
  258. If PosX + MaxWidth > ScreenWidth ;past right side of the screen
  259.     PosX := ScreenWidth - MaxWidth
  260. PosY := A_CaretY + OffsetY
  261. If PosY + BoxHeight > ScreenHeight ;past bottom of the screen
  262.     PosY := ScreenHeight - BoxHeight
  263. Gui, Show, x%PosX% y%PosY% w%MaxWidth% NoActivate
  264. Return
  265.  
  266. CompleteWord:
  267. Critical
  268.  
  269. ;only trigger word completion on non-interface event or double click on matched list
  270. If (A_GuiEvent != "" && A_GuiEvent != "DoubleClick")
  271.     Return
  272.  
  273. Gui, Suggestions:Default
  274. Gui, Hide
  275.  
  276. ;retrieve the word that was selected
  277. GuiControlGet, Index,, Matched
  278. TempList := "|" . MatchList . "|"
  279. Position := InStr(TempList,"|",0,1,Index) + 1
  280. NewWord := SubStr(TempList,Position,InStr(TempList,"|",0,Position) - Position)
  281.  
  282. SendWord(CurrentWord,NewWord,CorrectCase)
  283.  
  284. Gosub, ResetWord
  285. Return
  286.  
  287. PrepareWordList(ByRef WordList)
  288. {
  289.     If InStr(WordList,"`r")
  290.         StringReplace, WordList, WordList, `r,, All
  291.     While, InStr(WordList,"`n`n")
  292.         StringReplace, WordList, WordList, `n`n, `n, All
  293. }
  294.  
  295. SetHotkeys(NormKeyList,NumberKeyList,OtherKeyList,ResetKeyList,TriggerKeyList)
  296. {
  297.     Loop, Parse, NormKeyList, `n
  298.     {
  299.         Hotkey, ~%A_LoopField%, Key, UseErrorLevel
  300.         Hotkey, ~+%A_LoopField%, ShiftedKey, UseErrorLevel
  301.     }
  302.  
  303.     Loop, Parse, NumberKeyList, `n
  304.     {
  305.         Hotkey, ~%A_LoopField%, Key, UseErrorLevel
  306.         Hotkey, ~Numpad%A_LoopField%, NumpadKey, UseErrorLevel
  307.     }
  308.  
  309.     Loop, Parse, OtherKeyList, `n
  310.         Hotkey, ~%A_LoopField%, Key, UseErrorLevel
  311.  
  312.     Loop, Parse, ResetKeyList, `n
  313.         Hotkey, ~*%A_LoopField%, ResetWord, UseErrorLevel
  314.  
  315.     Hotkey, IfWinExist, AutoComplete ahk_class AutoHotkeyGUI
  316.     Loop, Parse, TriggerKeyList, `n
  317.         Hotkey, %A_LoopField%, CompleteWord, UseErrorLevel
  318. }
  319.  
  320. Suggest(Word,ByRef WordList)
  321. {
  322.     Pattern := RegExReplace(Word,"S).","$0.*") ;subsequence matching pattern
  323.  
  324.     ;treat accented characters as equivalent to their unaccented counterparts
  325.     Pattern := RegExReplace(Pattern,"S)[a" . Chr(224) . Chr(226) . "]","[a" . Chr(224) . Chr(226) . "]")
  326.     Pattern := RegExReplace(Pattern,"S)[c" . Chr(231) . "]","[c" . Chr(231) . "]")
  327.     Pattern := RegExReplace(Pattern,"S)[e" . Chr(233) . Chr(232) . Chr(234) . Chr(235) . "]","[e" . Chr(233) . Chr(232) . Chr(234) . Chr(235) . "]")
  328.     Pattern := RegExReplace(Pattern,"S)[i" . Chr(238) . Chr(239) . "]","[i" . Chr(238) . Chr(239) . "]")
  329.     Pattern := RegExReplace(Pattern,"S)[o" . Chr(244) . "]","[o" . Chr(244) . "]")
  330.     Pattern := RegExReplace(Pattern,"S)[u" . Chr(251) . Chr(249) . "]","[u" . Chr(251) . Chr(249) . "]")
  331.  
  332.     Pattern := "`nimS)^" . Pattern ;match options
  333.  
  334.     ;search for words matching the pattern
  335.     MatchList := ""
  336.     Position := 1
  337.     While, Position := RegExMatch(WordList,Pattern,Word,Position)
  338.     {
  339.         Position += StrLen(Word)
  340.         StringReplace, Word, Word, %A_Tab%, %A_Space%%A_Space%%A_Space%%A_Space%, All
  341.         MatchList .= Word . "|"
  342.     }
  343.  
  344.     Sort, MatchList, FRankResults D| ;rank results by score
  345.  
  346.     Return, MatchList
  347. }
  348.  
  349. RankResults(Entry1,Entry2,Offset)
  350. {
  351.     Return, Score(Entry2,0) - Score(Entry1,Offset)
  352. }
  353.  
  354. Score(Entry,Offset)
  355. {
  356.     global CurrentWord
  357.     Score := 100
  358.  
  359.     Length := StrLen(CurrentWord)
  360.  
  361.     ;determine prefixing
  362.     Position := 1
  363.     While, Position <= Length && SubStr(CurrentWord,Position,1) = SubStr(Entry,Position,1)
  364.         Position ++
  365.     Score *= Position ** 3
  366.  
  367.     ;determine number of superfluous characters
  368.     RegExMatch(Entry,"`nmS)^" . SubStr(RegExReplace(CurrentWord,"S).","$0.*"),1,-2),Word)
  369.     Score *= (1 + StrLen(Word) - Length) ** -1.5
  370.  
  371.     ;determine the offset (for wordlists sorted by frequency)
  372.     If Offset > 0
  373.         Score *= 10 ** 0.4
  374.     Else If Offset < 0
  375.         Score *= 10 ** -0.4
  376.  
  377.     Return, Score
  378. }
  379.  
  380. SendWord(CurrentWord,NewWord,CorrectCase = False)
  381. {
  382.     If CorrectCase
  383.     {
  384.         Position := 1
  385.         CaseSense := A_StringCaseSense
  386.         StringCaseSense, Locale
  387.         Loop, Parse, CurrentWord
  388.         {
  389.             Position := InStr(NewWord,A_LoopField,False,Position) ;find next character in the current word if only subsequence matched
  390.             If A_LoopField Is Upper
  391.             {
  392.                 Char := SubStr(NewWord,Position,1)
  393.                 StringUpper, Char, Char
  394.                 NewWord := SubStr(NewWord,1,Position - 1) . Char . SubStr(NewWord,Position + 1)
  395.             }
  396.         }
  397.         StringCaseSense, %CaseSense%
  398.     }
  399.  
  400.     ;send the word
  401.     Send, % "{BS " . StrLen(CurrentWord) . "}" ;clear the typed word
  402.     SendRaw, %NewWord%
  403. }
  404.  
  405. TextWidth(String)
  406. {
  407.     static Typeface := "Courier New"
  408.     static Size := 10
  409.     static hDC, hFont := 0, Extent
  410.     If !hFont
  411.     {
  412.         hDC := DllCall("GetDC","UPtr",0,"UPtr")
  413.         Height := -DllCall("MulDiv","Int",Size,"Int",DllCall("GetDeviceCaps","UPtr",hDC,"Int",90),"Int",72)
  414.         hFont := DllCall("CreateFont","Int",Height,"Int",0,"Int",0,"Int",0,"Int",400,"UInt",False,"UInt",False,"UInt",False,"UInt",0,"UInt",0,"UInt",0,"UInt",0,"UInt",0,"Str",Typeface)
  415.         hOriginalFont := DllCall("SelectObject","UPtr",hDC,"UPtr",hFont,"UPtr")
  416.         VarSetCapacity(Extent,8)
  417.     }
  418.     DllCall("GetTextExtentPoint32","UPtr",hDC,"Str",String,"Int",StrLen(String),"UPtr",&Extent)
  419.     Return, NumGet(Extent,0,"UInt")
  420. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement