Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Settings.ini
149 changes: 120 additions & 29 deletions Autocomplete.ahk
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
#NoEnv

#Hotstring NoMouse
#KeyHistory 0
#MaxMem 1
#MaxThreadsBuffer On
#SingleInstance force

#Warn All
#Warn LocalSameAsGlobal, Off

#MaxThreadsBuffer On

SetBatchLines, -1

WordListFile := A_ScriptDir . "\WordList.txt" ;path of the wordlist file
Expand All @@ -14,14 +18,14 @@ MaxResults := 20 ;maximum number of results to display
OffsetX := 0 ;offset in caret position in X axis
OffsetY := 20 ;offset from caret position in Y axis
BoxHeight := 165 ;height of the suggestions box in pixels
ShowLength := 4 ;minimum length of word before showing suggestions
ShowLength := 2 ;minimum length of word before showing suggestions
CorrectCase := True ;whether or not to fix uppercase or lowercase to match the suggestion

NormalKeyList := "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
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
OtherKeyList := "'`n-" ;list of key names separated by `n that make up words
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
TriggerKeyList := "Tab`nEnter" ;list of key names separated by `n that trigger completion
OtherKeyList := "<`n(`n{`n'`n-" ;list of key names separated by `n that make up words
ResetKeyList := "Esc`nSpace`nHome`nNumpadHome`nEnd`nNumpadEnd`nLeft`nNumpadLeft`nRight`nNumpadRight`nRButton`nMButton`n,`n.`n/`n[`n]`n;`n\`n=`n```n""" ;list of key names separated by `n that cause suggestions to reset
TriggerKeyList := "Tab`nEnter`nNumpadEnter" ;list of key names separated by `n that trigger completion

IniRead, MaxResults, %SettingsFile%, Settings, MaxResults, %MaxResults%
IniRead, ShowLength, %SettingsFile%, Settings, ShowLength, %ShowLength%
Expand All @@ -47,6 +51,8 @@ SendMode, Input
;obtain desktop size across all monitors
SysGet, ScreenWidth, 78
SysGet, ScreenHeight, 79
;obtain vertical scrollbar width (SM_CXVSCROLL)
SysGet, VSBW, 2

FileRead, WordList, %WordListFile%
PrepareWordList(WordList)
Expand All @@ -62,6 +68,7 @@ Menu, Tray, Default, Settings
;set up suggestions window
Gui, Suggestions:Default
Gui, Font, s10, Courier New
Gui, Font, s10, Consolas
Gui, +Delimiter`n
Gui, Add, ListBox, x0 y0 h%BoxHeight% 0x100 vMatched gCompleteWord AltSubmit
Gui, -Caption +ToolWindow +AlwaysOnTop +LastFound
Expand Down Expand Up @@ -107,6 +114,7 @@ If WinExist()

Gui, Settings:Default
Gui, Font,, Arial
Gui, Font,, Calibri
Gui, Font,, Century Gothic
Gui, Color, White, FFF8F8

Expand All @@ -125,23 +133,27 @@ Gui, Add, UpDown, Range1-10, %ShowLength%
Gui, Add, Checkbox, x10 y150 w260 h30 Checked%CorrectCase% vCorrectCase, CASE CORRECTION

Gui, Add, Edit, x10 y210 w230 h30 vNewWord
Gui, Add, Button, x240 y210 w30 h30 Disabled vAddWord gAddWord, +
Gui, Add, Button, x240 y210 w30 h30 Disabled Default vAddWord gAddWord, +
Gui, Add, Button, x10 y250 w260 h40 Disabled vRemoveWord gRemoveWord, REMOVE SELECTED
Gui, Font, s8, Courier New
Gui, Font, s8, Consolas
Gui, Add, ListView, x290 y70 w260 h220 -Hdr vWords, Words

Gui, Color, White
Gui, +ToolWindow +AlwaysOnTop
Gui, Show, w560 h300, Autocomplete by Uberi

LV_Add("", "Reading wordlist...")
LV_Add("", "Loading wordlist...")
Sleep, 0

;populate list with entries from wordlist
GuiControl, -Redraw, Words
Loop, Parse, WordList, `n
LV_Add("", A_LoopField)
LV_Delete(1)
If LV_GetCount() >= 13
LV_ModifyCol(1,256-VSBW) ;suppress horizontal scrollbar
GuiControl, +Sort, Words
GuiControl, +Redraw, Words

GuiControl, Enable, AddWord
Expand All @@ -158,9 +170,13 @@ Return
AddWord:
Gui, Settings:Default
GuiControlGet, NewWord,, NewWord
GuiControl,, NewWord

Index := LV_Add("Select Focus", NewWord)
LV_Modify(Index, "Vis")
WordList .= "`n" . NewWord
If LV_GetCount() >= 13
LV_ModifyCol(1,256-VSBW) ;suppress horizontal scrollbar
Return

RemoveWord:
Expand All @@ -173,6 +189,8 @@ While, CurrentRow := LV_GetNext()
Position := InStr(TempList,"`n",True,1,CurrentRow)
TempList := SubStr(TempList,1,Position) . SubStr(TempList,InStr(TempList,"`n",True,Position + 1) + 1)
}
If LV_GetCount() < 13
LV_ModifyCol(1,256) ;reset column width
GuiControl, +Redraw, Words
WordList := SubStr(TempList,2,-1)
Return
Expand All @@ -186,35 +204,60 @@ If (Temp1 != hWindow)
Return

Up::
NumpadUp::
Gui, Suggestions:Default
GuiControlGet, Temp1,, Matched
If Temp1 > 1 ;ensure value is in range
GuiControl, Choose, Matched, % Temp1 - 1
Return

PgUp::
NumpadPgUp::
Gui, Suggestions:Default
GuiControlGet, Temp1,, Matched
If Temp1 > 10 ;ensure value is in range
GuiControl, Choose, Matched, % Temp1 - 10
Else If Temp1 > 1
GuiControl, Choose, Matched, 1
Return

Down::
NumpadDown::
Gui, Suggestions:Default
GuiControlGet, Temp1,, Matched
GuiControl, Choose, Matched, % Temp1 + 1
Return

!1::
!2::
!3::
!4::
!5::
!6::
!7::
!8::
!9::
!0::
PgDn::
NumpadPgDn::
Gui, Suggestions:Default
GuiControlGet, Temp1,, Matched
If % Temp1 + 10 <= MaxResults ;ensure value is in range
GuiControl, Choose, Matched, % Temp1 + 10
Else If % Temp1 < MaxResults
GuiControl, Choose, Matched, % MaxResults
Return

1::
2::
3::
4::
5::
6::
7::
8::
9::
0::
Gui, Suggestions:Default
KeyWait, Alt
Key := SubStr(A_ThisHotkey, 2, 1)
Key := SubStr(A_ThisHotkey,1,1)
GuiControl, Choose, Matched, % Key = 0 ? 10 : Key
Gosub, CompleteWord
Return

Esc::
Gosub, ResetWord
Return

#IfWinExist

~BackSpace::
Expand Down Expand Up @@ -273,7 +316,7 @@ MaxWidth := 0
DisplayList := ""
Loop, Parse, MatchList, `n
{
Entry := (A_Index < 10 ? A_Index . ". " : " ") . A_LoopField
Entry := (A_Index < 10 ? A_Index . ": " : (A_Index = 10 ? "0: " : " ")) . A_LoopField
Width := TextWidth(Entry)
If (Width > MaxWidth)
MaxWidth := Width
Expand All @@ -286,10 +329,16 @@ DisplayList := SubStr(DisplayList,1,-1)
GuiControl,, Matched, `n%DisplayList%
GuiControl, Choose, Matched, 1
GuiControl, Move, Matched, w%MaxWidth% ;set the control width
PosX := A_CaretX + OffsetX
If A_CaretX
PosX := A_CaretX + OffsetX
Else
PosX := OffsetX
If PosX + MaxWidth > ScreenWidth ;past right side of the screen
PosX := ScreenWidth - MaxWidth
PosY := A_CaretY + OffsetY
If A_CaretY
PosY := A_CaretY + OffsetY
Else
PosY := OffsetY
If PosY + BoxHeight > ScreenHeight ;past bottom of the screen
PosY := ScreenHeight - BoxHeight
Gui, Show, x%PosX% y%PosY% w%MaxWidth% NoActivate ;show window
Expand Down Expand Up @@ -352,7 +401,11 @@ SetHotkeys(NormalKeyList,NumberKeyList,OtherKeyList,ResetKeyList,TriggerKeyList)

Suggest(CurrentWord,ByRef WordList)
{
Pattern := RegExReplace(CurrentWord,"S).","$0.*") ;subsequence matching pattern
;escape Regular Expressions reserved characters
Pattern := RegExReplace(CurrentWord,"[.?*+(){}\[\]|\\^$]","\$0")
Pattern := RegExReplace(Pattern,".+","$0.*")
;TODO: use below instead if Fuzzy Matching is enabled
;Pattern := RegExReplace(Pattern,"S).","$0.*") ;subsequence matching pattern

;treat accented characters as equivalent to their unaccented counterparts
Pattern := RegExReplace(Pattern,"S)[a" . Chr(224) . Chr(226) . "]","[a" . Chr(224) . Chr(226) . "]")
Expand Down Expand Up @@ -398,10 +451,15 @@ Score(Word,Entry)
Position ++
Score *= Position ** 8

;escape Regular Expressions reserved characters
Pattern := RegExReplace(Word,"[.?*+(){}\[\]|\\^$]","\$0")
Pattern := "`nimS)^" . SubStr(RegExReplace(Pattern,".+","$0.*"),1,-2)
;TODO: use below instead if Fuzzy Matching is enabled
;Pattern := "`nimS)^" . SubStr(RegExReplace(Pattern,"S).","$0.*"),1,-2)

;determine number of superfluous characters
RegExMatch(Entry,"`nimS)^" . SubStr(RegExReplace(Word,"S).","$0.*"),1,-2),Remaining)
RegExMatch(Entry,Pattern,Remaining)
Score *= (1 + StrLen(Remaining) - Length) ** -1.5

Score *= StrLen(Word) ** 0.4

Return, Score
Expand All @@ -427,9 +485,42 @@ SendWord(CurrentWord,NewWord,CorrectCase = False)
StringCaseSense, %CaseSense%
}

;send the word
Send, % "{BS " . StrLen(CurrentWord) . "}" ;clear the typed word
SendRaw, %NewWord%
;parse newlines (\n) and tabs (\t)
StringReplace, NewWord, NewWord, \n, `r`n, UseErrorLevel
StringReplace, NewWord, NewWord, \t, `t, UseErrorLevel

;parse caret indicator (|)?
MoveLeft := ""
CaretPosition := InStr(NewWord,"|")
If CaretPosition
{
If InStr(NewWord,"\|")
{
;handle escaped pipe
StringReplace, NewWord, NewWord, \|, |, UseErrorLevel
}
Else
{
;find caret position
MoveLeft := "{Left " . StrLen(NewWord) - CaretPosition . "}"
StringReplace, NewWord, NewWord, |,, UseErrorLevel
}
}

ClipSaved := Clipboard ;back up clipboard
Clipboard = ;empty the clipboard
Clipboard := NewWord ;put selected word into clipboard
ClipWait ;wait for the clipboard to contain text

;delete the current word and paste, moving to caret indicator if applicable
Send, % "{BS " . StrLen(CurrentWord) . "}^v" . MoveLeft
;pasting instead of SendRaw to play nicely with auto-indent editors
;SendRaw, %NewWord%
Sleep, 50 ;wait for paste action to complete
Clipboard := ClipSaved ;restore previous clipboard
;clear to free up memory
ClipSaved =
MoveLeft =
}

TextWidth(String)
Expand Down
32 changes: 26 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ Autocomplete by Uberi
=====================
Suggests and completes words as you type! Write faster and more efficiently.

# [Get it now](https://github.com/Uberi/Autocomplete/releases/)

![Screenshot](Screenshot.png)

Using
Expand All @@ -13,9 +11,10 @@ Using
2. If you downloaded the binaries, open `Autocomplete.exe`.
3. If you downloaded the source, make sure you have a recent version of [AutoHotkey](http://www.autohotkey.com/) installed, and run `Autocomplete.ahk`.
4. Start typing somewhere. After the first few characters, a suggestion box will appear.
5. Use the `Up` and `Down` arrow keys to select an entry if the currently selected one is not the desired word.
5. Use the `Up`/`Down` and `PgUp`/`PgDn` keys to select an entry if the currently selected one is not the desired word.
6. Press `Enter` or `Tab` to trigger the completion with the currently selected word.
7. Alternatively, press one of `Alt + 1`, `Alt + 2`, ..., `Alt + 9`, `Alt + 0` to trigger completion with the 1st, 2nd, ..., 9th, and 10th word, repectively.
7. Alternatively, press one of `1`, `2`, ... `9`, `0` to trigger completion with the 1st, 2nd, ... 9th, and 10th word, repectively.
8. Press `Esc` to cancel and close the suggestions list.

Advanced
--------
Expand All @@ -30,16 +29,37 @@ Settings are stored in `Settings.ini` in the program directory. This contains a

Key settings are URL encoded lists of key names such as `Space` and `d` where each entry is separated by a newline (the URL encoded version of a newline is `%0A`). They can be edited to change the keys accepted by the program.

Modifications by thdoan
-----------------------

- Added support for characters `< ( {` by default (to autocomplete `<tag>`, etc.)
- Added support for NumPad navigation in suggestions list
- Added ability to navigate suggestions list with `PgUp`/`PgDn`
- Added ability to autocomplete code snippets with newlines (\n) and tabs (\t)
- Added ability to move caret to indicator (`|`) after autocompleting (escape with `\|` if you want to insert a literal pipe)
- Added ability to close suggestions list by pressing `Esc`
- Added ability to add new word in Preferences by pressing `Enter`
- Changed monospace font to Consolas
- Changed default minimum trigger length to 2
- Changed suggestions list hotkeys from `Alt + <Num>` to `<Num>`
- Changed to clear "new word" edit box after adding to wordlist
- Changed Preferences wordlist to alphabetical order (sorted)
- Replaced English word list with a few code samples
- Fixed "0." not displayed in suggestions list
- Fixed incompatibility bug with v1.1.20.00 and higher
- Fixed horizontal scrollbar in Preferences wordlist
- Fixed Regular Expressions reserved characters not escaped in wordlist

Licence
-------

This program is provided under the 3-clause BSD license. In short, this gives you the right to modify and distribute the program as you please, as long as you make sure the notice below is accessible to the user.

Copyright (c) 2013, Anthony Zhang
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
Expand Down
Binary file modified Screenshot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading