1

Тема: AHK: Автозавершение вводимого текста

Доброе время суток.
Есть такая тема:
Если в AHK-скрипте создать такую строчку:

:*:.ui:: UINT64

,
то каждый раз при вводе .ui будем получать UINT64.
А вот реально ли на ОДНУ И ТУЖЕ последовательность символов повесить несколько вариантов автозавершения?
например хотя бы так:


:*:for:: for(int i=0; i<   ; i++) {   }
:*:for:: for i:= 0 to 10 do begin    end;
:*:for:: for(i=0; i<1000; ++i) {    }

и получить список-подсказку для трех for.

Чтобы, например, на экране при вводе последовательности символов появлялся бы список возможных вариантов автозамены, в котором можно было бы выбрать нужный. Такое, возможно, если сделать небольшую программку на AHK. Такие программки уже есть готовые, например, TypeAid (если не ошибаюсь) или FastKeys. Обе они написаны на AHK. Но мне не нужна целая программа, поэтому и спрашиваю: может как-то можно в несколько строчек такое реализовать в AHK стандартно, ничего нового не изобретая?
Заранее спасибо!

2

Re: AHK: Автозавершение вводимого текста

Пожалуй, наверно тему можно закрыть, так как я нашел ответ на свой вопрос на GitHub. Uberi/Autocomplete предлагает некий скрипт, который скорее всего можно посмотреть и разобраться что и как.

3

Re: AHK: Автозавершение вводимого текста

#NoEnv
#Warn All
#Warn LocalSameAsGlobal, Off
#MaxThreadsBuffer On
#SingleInstance force
SetBatchLines -1

WordListFile := A_ScriptDir . "\WordList.txt" ;path of the wordlist file
SettingsFile := A_ScriptDir . "\Settings.ini" ;path of the settings file

MaxResults := 10 ;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
CorrectCase := True ;whether or not to fix uppercase or lowercase to match the suggestion

ResetKeyList := "RButton`nMButton"  ;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

IniRead, MaxResults, %SettingsFile%, Settings, MaxResults, %MaxResults%
IniRead, ShowLength, %SettingsFile%, Settings, ShowLength, %ShowLength%
IniRead, CorrectCase, %SettingsFile%, Settings, CorrectCase, %CorrectCase%
IniRead, ResetKeyList, %SettingsFile%, Keys, ResetKeyList, %ResetKeyList%
ResetKeyList := URLDecode(ResetKeyList)
IniRead, TriggerKeyList, %SettingsFile%, Keys, TriggerKeyList, %TriggerKeyList%
TriggerKeyList := URLDecode(TriggerKeyList)
IniRead WinTitle, %SettingsFile%, Keys, WinTitle, % " "
IniRead TitleMatchMode, %SettingsFile%, Keys, TitleMatchMode, 1
SetTitleMatchMode, % TitleMatchMode

TrayTip, Settings, Click the tray icon to modify settings, 5, 1

CoordMode, Caret
SetKeyDelay, 0
SendMode, Input

;obtain desktop size across all monitors
SysGet, ScreenWidth, 78
SysGet, ScreenHeight, 79

; FileRead, WordList, %WordListFile%
WordList =
(
for(int i=0; i<   ; i++) {   }
for i:= 0 to 10 do begin    end;
for(i=0; i<1000; ++i) {    }
)
PrepareWordList(WordList)

;set up tray menu
Menu, Tray, NoStandard
Menu, Tray, Click, 1
Menu, Tray, Add, Settings, ShowSettings
Menu, Tray, Add
Menu, Tray, Add, Exit, ExitSub
Menu, Tray, Default, Settings

;set up suggestions window
Gui, Suggestions:Default
Gui, Font, s10, Courier New
Gui, Add, ListBox, x0 y0 h%BoxHeight% 0x100 vMatched gCompleteWord AltSubmit
Gui, -Caption +ToolWindow +AlwaysOnTop +LastFound
hWindow := WinExist()
Gui, Show, h%BoxHeight% Hide, AutoComplete

Gosub, ResetWord

SetHotkeys(ResetKeyList,TriggerKeyList,WinTitle)
Run notepad
Loop {
	WinWaitActive % WinTitle
	Input key, L1VE, .`,`;:\/{Left}{Right}{Up}{Down}{Home}{End}{PgUp}{PgDn}{Enter}{Space}{LControl}{RControl}{LAlt}{RAlt}{LWin}{RWin}{AppsKey}{BackSpace}`;`"|''
	CurrentWord := (ErrorLevel = "Max")
	 ? CurrentWord key
	 : ErrorLevel = "EndKey:Backspace"
		 ? SubStr(CurrentWord, 1, StrLen(CurrentWord)-1)
		 : ""
	If (StrLen(CurrentWord) > ShowLength)
		Gosub Suggest
	Else
		Gui Suggestions:Hide
}

OnExit, ExitSub
Return

ExitSub:
Gui, Settings:Submit

;write settings
IniWrite, % MaxResults, %SettingsFile%, Settings, MaxResults
IniWrite, % ShowLength, %SettingsFile%, Settings, ShowLength
IniWrite, % CorrectCase, %SettingsFile%, Settings, CorrectCase

IniWrite, % URLEncode(ResetKeyList), %SettingsFile%, Keys, ResetKeyList
IniWrite, % URLEncode(TriggerKeyList), %SettingsFile%, Keys, TriggerKeyList
IniWrite, % WinTitle, %SettingsFile%, Keys, WinTitle
IniWrite, % TitleMatchMode, %SettingsFile%, Keys, TitleMatchMode

;write wordlist file
File := FileOpen(WordListFile,"w")
File.Seek(0)
Length := File.Write(WordList)
File.Length := Length
ExitApp

ShowSettings:
;do not show settings window if already shown
Gui, Settings:+LastFoundExist
If WinExist()
	Return

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

Gui, Font, s24 cFFAAAA
Gui, Add, Text, x10 y10 w540 h45 Center, a u t o c o m p l e t e
Gui, Add, Progress, x10 y55 w540 h1 BackgroundEEDDDD, 0

Gui, Font, s14 c885555
Gui, Add, Text, x10 y73 w180 h30, RESULT LIMIT
Gui, Add, Edit, x190 y70 w80 h30 Right Number vMaxResults, % MaxResults
Gui, Add, UpDown, Range1-100, % MaxResults
Gui, Add, Text, x10 y113 w180 h30, TRIGGER LENGTH
Gui, Add, Edit, x190 y110 w80 h30 Right Number vShowLength, % ShowLength
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, x10 y250 w260 h40 Disabled vRemoveWord gRemoveWord, REMOVE SELECTED
Gui, Font, s8, Courier New
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...")
Sleep, 0

;populate list with entries from wordlist
GuiControl, -Redraw, Words
Loop, Parse, WordList, `n
	LV_Add("", A_LoopField)
LV_Delete(1)
GuiControl, +Redraw, Words

GuiControl, Enable, AddWord
GuiControl, Enable, RemoveWord
Return

SettingsGuiEscape:
SettingsGuiClose:
Gui, Settings:Default
Gui, Submit
Gui, Destroy
Return

AddWord:
Gui, Settings:Default
GuiControlGet, NewWord,, NewWord
Index := LV_Add("Select Focus", NewWord)
LV_Modify(Index, "Vis")
WordList .= "`n" . NewWord
Return

RemoveWord:
Gui, Settings:Default
TempList := "`n" . WordList . "`n"
GuiControl, -Redraw, Words
While, CurrentRow := LV_GetNext()
{
	LV_Delete(CurrentRow)
	Position := InStr(TempList,"`n",True,1,CurrentRow)
	TempList := SubStr(TempList,1,Position) . SubStr(TempList,InStr(TempList,"`n",True,Position + 1) + 1)
}
GuiControl, +Redraw, Words
WordList := SubStr(TempList,2,-1)
Return

#IfWinExist AutoComplete ahk_class AutoHotkeyGUI

~LButton::
MouseGetPos,,, Temp1
If (Temp1 != hWindow)
	Gosub, ResetWord
Return

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

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

#IfWinExist

; ~BackSpace::
; CurrentWord := SubStr(CurrentWord,1,-1)
; Gosub, Suggest
; Return

Key:
CurrentWord .= SubStr(A_ThisHotkey,2)
Gosub, Suggest
Return

ShiftedKey:
Char := SubStr(A_ThisHotkey,3)
StringUpper, Char, Char
CurrentWord .= Char
Gosub, Suggest
Return

NumpadKey:
CurrentWord .= SubStr(A_ThisHotkey,8)
Gosub, Suggest
Return

ResetWord:
CurrentWord := ""
Input
Gui, Suggestions:Hide
Return

Suggest:
; ToolTip % CurrentWord
Gui, Suggestions:Default

;check word length against minimum length
If (StrLen(CurrentWord) < ShowLength)
{
	Gui, Hide
	Return
}

MatchList := Suggest(CurrentWord,WordList)

;check for a lack of matches
If (MatchList = "")
{
	Gui, Hide
	Return
}

;limit the number of results
Position := InStr(MatchList,"|",True,1,MaxResults)
If Position
	MatchList := SubStr(MatchList,1,Position - 1)

;find the longest text width
MaxWidth := 0
Loop, Parse, MatchList, |
{
	Width := TextWidth(A_LoopField)
	If (Width > MaxWidth)
		MaxWidth := Width
}
MaxWidth += 30 ;add room for the scrollbar

;update the interface
GuiControl,, Matched, |%MatchList%
GuiControl, Choose, Matched, 1
GuiControl, Move, Matched, w%MaxWidth% ;set the control width
CoordMode Mouse, Screen
MouseGetPos mX, mY
CaretOrMouseX := (A_CaretX = "") ? mX : A_CaretX
CaretOrMouseY := (A_CaretY = "") ? mY : A_CaretY
PosX := CaretOrMouseX + OffsetX
If PosX + MaxWidth > ScreenWidth ;past right side of the screen
	PosX := ScreenWidth - MaxWidth
PosY := CaretOrMouseY + OffsetY
If PosY + BoxHeight > ScreenHeight ;past bottom of the screen
	PosY := ScreenHeight - BoxHeight
Gui, Show, x%PosX% y%PosY% w%MaxWidth% NoActivate ;show window
Return

CompleteWord:
Critical

;only trigger word completion on non-interface event or double click on matched list
If (A_GuiEvent != "" && A_GuiEvent != "DoubleClick")
	Return

Gui, Suggestions:Default
Gui, Hide

;retrieve the word that was selected
GuiControlGet, Index,, Matched
TempList := "|" . MatchList . "|"
Position := InStr(TempList,"|",0,1,Index) + 1
NewWord := SubStr(TempList,Position,InStr(TempList,"|",0,Position) - Position)

SendWord(CurrentWord,NewWord,CorrectCase)

Gosub, ResetWord
Return

PrepareWordList(ByRef WordList)
{
	If InStr(WordList,"`r")
		StringReplace, WordList, WordList, `r,, All
	While, InStr(WordList,"`n`n") ;remove blank lines within the list
		StringReplace, WordList, WordList, `n`n, `n, All
	WordList := Trim(WordList,"`n") ;remove blank lines at the beginning and end
}

SetHotkeys(ResetKeyList,TriggerKeyList,WinTitle)
{
	Hotkey, IfWinActive, %WinTitle%

	Loop, Parse, ResetKeyList, `n
		Hotkey, ~*%A_LoopField%, ResetWord, UseErrorLevel

	Hotkey, IfWinExist, AutoComplete ahk_class AutoHotkeyGUI
	Loop, Parse, TriggerKeyList, `n
		Hotkey, %A_LoopField%, CompleteWord, UseErrorLevel
}

Suggest(CurrentWord,ByRef WordList)
{
	Pattern := RegExReplace(CurrentWord,"S)(*UCP).","$0.*") ;subsequence matching pattern

	Pattern := "`nimS)(*UCP)^" . Pattern ;match options

	;search for words matching the pattern
	MatchList := ""
	Position := 1
	While, Position := RegExMatch(WordList,Pattern,Word,Position)
	{
		Position += StrLen(Word)
		StringReplace, Word, Word, %A_Tab%, %A_Space%%A_Space%%A_Space%%A_Space%, All ;convert tabs to spaces
		MatchList .= Word . "`n"
		; MsgBox % Word
	}
	MatchList := SubStr(MatchList,1,-1) ;remove trailing delimiter

	;sort by score
	SortedMatches := ""
	Loop, Parse, MatchList, `n
		SortedMatches .= Score(CurrentWord,A_LoopField) . "`t" . A_LoopField . "`n"
	SortedMatches := SubStr(SortedMatches,1,-1)
	Sort, SortedMatches, N R ;rank results numerically descending by score

	;remove scores
	MatchList := ""
	Loop, Parse, SortedMatches, `n
		MatchList .= SubStr(A_LoopField,InStr(A_LoopField,"`t",True,-1) + 1) . "|"

	Return, MatchList
}

Score(Word,Entry)
{
	Score := 100

	Length := StrLen(Word)

	;determine prefixing
	Position := 1
	While, Position <= Length && SubStr(Word,Position,1) = SubStr(Entry,Position,1)
		Position ++
	Score *= Position ** 8

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

	Return, Score
}

SendWord(CurrentWord, NewWord, CorrectCase:=False)
{
	If CorrectCase
	{
		Position := 1
		CaseSense := A_StringCaseSense
		StringCaseSense, Locale
		Loop, Parse, CurrentWord
		{
			Position := InStr(NewWord,A_LoopField,False,Position) ;find next character in the current word if only subsequence matched
			If A_LoopField Is Upper
			{
				Char := SubStr(NewWord,Position,1)
				StringUpper, Char, Char
				NewWord := SubStr(NewWord,1,Position - 1) . Char . SubStr(NewWord,Position + 1)
			}
		}
		StringCaseSense, %CaseSense%
	}

	;send the word
	Send, % "{BS " . StrLen(CurrentWord) . "}" ;clear the typed word
	SendRaw, %NewWord%
}

TextWidth(String) ; return length*10
{
	static Typeface := "Courier New"
	static Size := 10
	static hDC, hFont := 0, Extent
	If !hFont
	{
		hDC := DllCall("GetDC","UPtr",0,"UPtr")
		Height := -DllCall("MulDiv","Int",Size,"Int",DllCall("GetDeviceCaps","UPtr",hDC,"Int",90),"Int",72)
		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)
		hOriginalFont := DllCall("SelectObject","UPtr",hDC,"UPtr",hFont,"UPtr")
		VarSetCapacity(Extent,8)
	}
	DllCall("GetTextExtentPoint32","UPtr",hDC,"Str",String,"Int",StrLen(String),"UPtr",&Extent)
	Return, NumGet(Extent,0,"UInt")
}

URLEncode(Text) {
	StringReplace, Text, Text, `%, `%25, All
	FormatInteger := A_FormatInteger, FoundPos := 0
	SetFormat IntegerFast, Hex
	While FoundPos := RegExMatch(Text,"S)(*UCP)[^\w-\.~%]",Char,FoundPos + 1)
		StringReplace Text, Text, %Char%, % "%" . SubStr("0" . SubStr(Asc(Char),3),-1), All
	SetFormat IntegerFast, %FormatInteger%
	Return Text
}

URLDecode(Encoded) {
	FoundPos := 0
	While FoundPos := InStr(Encoded,"%",False,FoundPos + 1)
	{
		Value := SubStr(Encoded,FoundPos + 1,2)
		If (Value != "25")
			StringReplace, Encoded, Encoded, `%%Value%, % Chr("0x" . Value), All
	}
	StringReplace Encoded, Encoded, `%25, `%, All
	Return Encoded
}

4

Re: AHK: Автозавершение вводимого текста

stealzy пишет:
#NoEnv
#Warn All
#Warn LocalSameAsGlobal, Off
#MaxThreadsBuffer On
#SingleInstance force
SetBatchLines -1

WordListFile := A_ScriptDir . "\WordList.txt" ;path of the wordlist file
SettingsFile := A_ScriptDir . "\Settings.ini" ;path of the settings file

MaxResults := 10 ;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
CorrectCase := True ;whether or not to fix uppercase or lowercase to match the suggestion

ResetKeyList := "RButton`nMButton"  ;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

IniRead, MaxResults, %SettingsFile%, Settings, MaxResults, %MaxResults%
IniRead, ShowLength, %SettingsFile%, Settings, ShowLength, %ShowLength%
IniRead, CorrectCase, %SettingsFile%, Settings, CorrectCase, %CorrectCase%
IniRead, ResetKeyList, %SettingsFile%, Keys, ResetKeyList, %ResetKeyList%
ResetKeyList := URLDecode(ResetKeyList)
IniRead, TriggerKeyList, %SettingsFile%, Keys, TriggerKeyList, %TriggerKeyList%
TriggerKeyList := URLDecode(TriggerKeyList)
IniRead WinTitle, %SettingsFile%, Keys, WinTitle, % " "
IniRead TitleMatchMode, %SettingsFile%, Keys, TitleMatchMode, 1
SetTitleMatchMode, % TitleMatchMode

TrayTip, Settings, Click the tray icon to modify settings, 5, 1

CoordMode, Caret
SetKeyDelay, 0
SendMode, Input

;obtain desktop size across all monitors
SysGet, ScreenWidth, 78
SysGet, ScreenHeight, 79

; FileRead, WordList, %WordListFile%
WordList =
(
for(int i=0; i<   ; i++) {   }
for i:= 0 to 10 do begin    end;
for(i=0; i<1000; ++i) {    }
)
PrepareWordList(WordList)

;set up tray menu
Menu, Tray, NoStandard
Menu, Tray, Click, 1
Menu, Tray, Add, Settings, ShowSettings
Menu, Tray, Add
Menu, Tray, Add, Exit, ExitSub
Menu, Tray, Default, Settings

;set up suggestions window
Gui, Suggestions:Default
Gui, Font, s10, Courier New
Gui, Add, ListBox, x0 y0 h%BoxHeight% 0x100 vMatched gCompleteWord AltSubmit
Gui, -Caption +ToolWindow +AlwaysOnTop +LastFound
hWindow := WinExist()
Gui, Show, h%BoxHeight% Hide, AutoComplete

Gosub, ResetWord

SetHotkeys(ResetKeyList,TriggerKeyList,WinTitle)
Run notepad
Loop {
	WinWaitActive % WinTitle
	Input key, L1VE, .`,`;:\/{Left}{Right}{Up}{Down}{Home}{End}{PgUp}{PgDn}{Enter}{Space}{LControl}{RControl}{LAlt}{RAlt}{LWin}{RWin}{AppsKey}{BackSpace}`;`"|''
	CurrentWord := (ErrorLevel = "Max")
	 ? CurrentWord key
	 : ErrorLevel = "EndKey:Backspace"
		 ? SubStr(CurrentWord, 1, StrLen(CurrentWord)-1)
		 : ""
	If (StrLen(CurrentWord) > ShowLength)
		Gosub Suggest
	Else
		Gui Suggestions:Hide
}

OnExit, ExitSub
Return

ExitSub:
Gui, Settings:Submit

;write settings
IniWrite, % MaxResults, %SettingsFile%, Settings, MaxResults
IniWrite, % ShowLength, %SettingsFile%, Settings, ShowLength
IniWrite, % CorrectCase, %SettingsFile%, Settings, CorrectCase

IniWrite, % URLEncode(ResetKeyList), %SettingsFile%, Keys, ResetKeyList
IniWrite, % URLEncode(TriggerKeyList), %SettingsFile%, Keys, TriggerKeyList
IniWrite, % WinTitle, %SettingsFile%, Keys, WinTitle
IniWrite, % TitleMatchMode, %SettingsFile%, Keys, TitleMatchMode

;write wordlist file
File := FileOpen(WordListFile,"w")
File.Seek(0)
Length := File.Write(WordList)
File.Length := Length
ExitApp

ShowSettings:
;do not show settings window if already shown
Gui, Settings:+LastFoundExist
If WinExist()
	Return

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

Gui, Font, s24 cFFAAAA
Gui, Add, Text, x10 y10 w540 h45 Center, a u t o c o m p l e t e
Gui, Add, Progress, x10 y55 w540 h1 BackgroundEEDDDD, 0

Gui, Font, s14 c885555
Gui, Add, Text, x10 y73 w180 h30, RESULT LIMIT
Gui, Add, Edit, x190 y70 w80 h30 Right Number vMaxResults, % MaxResults
Gui, Add, UpDown, Range1-100, % MaxResults
Gui, Add, Text, x10 y113 w180 h30, TRIGGER LENGTH
Gui, Add, Edit, x190 y110 w80 h30 Right Number vShowLength, % ShowLength
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, x10 y250 w260 h40 Disabled vRemoveWord gRemoveWord, REMOVE SELECTED
Gui, Font, s8, Courier New
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...")
Sleep, 0

;populate list with entries from wordlist
GuiControl, -Redraw, Words
Loop, Parse, WordList, `n
	LV_Add("", A_LoopField)
LV_Delete(1)
GuiControl, +Redraw, Words

GuiControl, Enable, AddWord
GuiControl, Enable, RemoveWord
Return

SettingsGuiEscape:
SettingsGuiClose:
Gui, Settings:Default
Gui, Submit
Gui, Destroy
Return

AddWord:
Gui, Settings:Default
GuiControlGet, NewWord,, NewWord
Index := LV_Add("Select Focus", NewWord)
LV_Modify(Index, "Vis")
WordList .= "`n" . NewWord
Return

RemoveWord:
Gui, Settings:Default
TempList := "`n" . WordList . "`n"
GuiControl, -Redraw, Words
While, CurrentRow := LV_GetNext()
{
	LV_Delete(CurrentRow)
	Position := InStr(TempList,"`n",True,1,CurrentRow)
	TempList := SubStr(TempList,1,Position) . SubStr(TempList,InStr(TempList,"`n",True,Position + 1) + 1)
}
GuiControl, +Redraw, Words
WordList := SubStr(TempList,2,-1)
Return

#IfWinExist AutoComplete ahk_class AutoHotkeyGUI

~LButton::
MouseGetPos,,, Temp1
If (Temp1 != hWindow)
	Gosub, ResetWord
Return

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

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

#IfWinExist

; ~BackSpace::
; CurrentWord := SubStr(CurrentWord,1,-1)
; Gosub, Suggest
; Return

Key:
CurrentWord .= SubStr(A_ThisHotkey,2)
Gosub, Suggest
Return

ShiftedKey:
Char := SubStr(A_ThisHotkey,3)
StringUpper, Char, Char
CurrentWord .= Char
Gosub, Suggest
Return

NumpadKey:
CurrentWord .= SubStr(A_ThisHotkey,8)
Gosub, Suggest
Return

ResetWord:
CurrentWord := ""
Input
Gui, Suggestions:Hide
Return

Suggest:
; ToolTip % CurrentWord
Gui, Suggestions:Default

;check word length against minimum length
If (StrLen(CurrentWord) < ShowLength)
{
	Gui, Hide
	Return
}

MatchList := Suggest(CurrentWord,WordList)

;check for a lack of matches
If (MatchList = "")
{
	Gui, Hide
	Return
}

;limit the number of results
Position := InStr(MatchList,"|",True,1,MaxResults)
If Position
	MatchList := SubStr(MatchList,1,Position - 1)

;find the longest text width
MaxWidth := 0
Loop, Parse, MatchList, |
{
	Width := TextWidth(A_LoopField)
	If (Width > MaxWidth)
		MaxWidth := Width
}
MaxWidth += 30 ;add room for the scrollbar

;update the interface
GuiControl,, Matched, |%MatchList%
GuiControl, Choose, Matched, 1
GuiControl, Move, Matched, w%MaxWidth% ;set the control width
CoordMode Mouse, Screen
MouseGetPos mX, mY
CaretOrMouseX := (A_CaretX = "") ? mX : A_CaretX
CaretOrMouseY := (A_CaretY = "") ? mY : A_CaretY
PosX := CaretOrMouseX + OffsetX
If PosX + MaxWidth > ScreenWidth ;past right side of the screen
	PosX := ScreenWidth - MaxWidth
PosY := CaretOrMouseY + OffsetY
If PosY + BoxHeight > ScreenHeight ;past bottom of the screen
	PosY := ScreenHeight - BoxHeight
Gui, Show, x%PosX% y%PosY% w%MaxWidth% NoActivate ;show window
Return

CompleteWord:
Critical

;only trigger word completion on non-interface event or double click on matched list
If (A_GuiEvent != "" && A_GuiEvent != "DoubleClick")
	Return

Gui, Suggestions:Default
Gui, Hide

;retrieve the word that was selected
GuiControlGet, Index,, Matched
TempList := "|" . MatchList . "|"
Position := InStr(TempList,"|",0,1,Index) + 1
NewWord := SubStr(TempList,Position,InStr(TempList,"|",0,Position) - Position)

SendWord(CurrentWord,NewWord,CorrectCase)

Gosub, ResetWord
Return

PrepareWordList(ByRef WordList)
{
	If InStr(WordList,"`r")
		StringReplace, WordList, WordList, `r,, All
	While, InStr(WordList,"`n`n") ;remove blank lines within the list
		StringReplace, WordList, WordList, `n`n, `n, All
	WordList := Trim(WordList,"`n") ;remove blank lines at the beginning and end
}

SetHotkeys(ResetKeyList,TriggerKeyList,WinTitle)
{
	Hotkey, IfWinActive, %WinTitle%

	Loop, Parse, ResetKeyList, `n
		Hotkey, ~*%A_LoopField%, ResetWord, UseErrorLevel

	Hotkey, IfWinExist, AutoComplete ahk_class AutoHotkeyGUI
	Loop, Parse, TriggerKeyList, `n
		Hotkey, %A_LoopField%, CompleteWord, UseErrorLevel
}

Suggest(CurrentWord,ByRef WordList)
{
	Pattern := RegExReplace(CurrentWord,"S)(*UCP).","$0.*") ;subsequence matching pattern

	Pattern := "`nimS)(*UCP)^" . Pattern ;match options

	;search for words matching the pattern
	MatchList := ""
	Position := 1
	While, Position := RegExMatch(WordList,Pattern,Word,Position)
	{
		Position += StrLen(Word)
		StringReplace, Word, Word, %A_Tab%, %A_Space%%A_Space%%A_Space%%A_Space%, All ;convert tabs to spaces
		MatchList .= Word . "`n"
		; MsgBox % Word
	}
	MatchList := SubStr(MatchList,1,-1) ;remove trailing delimiter

	;sort by score
	SortedMatches := ""
	Loop, Parse, MatchList, `n
		SortedMatches .= Score(CurrentWord,A_LoopField) . "`t" . A_LoopField . "`n"
	SortedMatches := SubStr(SortedMatches,1,-1)
	Sort, SortedMatches, N R ;rank results numerically descending by score

	;remove scores
	MatchList := ""
	Loop, Parse, SortedMatches, `n
		MatchList .= SubStr(A_LoopField,InStr(A_LoopField,"`t",True,-1) + 1) . "|"

	Return, MatchList
}

Score(Word,Entry)
{
	Score := 100

	Length := StrLen(Word)

	;determine prefixing
	Position := 1
	While, Position <= Length && SubStr(Word,Position,1) = SubStr(Entry,Position,1)
		Position ++
	Score *= Position ** 8

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

	Return, Score
}

SendWord(CurrentWord, NewWord, CorrectCase:=False)
{
	If CorrectCase
	{
		Position := 1
		CaseSense := A_StringCaseSense
		StringCaseSense, Locale
		Loop, Parse, CurrentWord
		{
			Position := InStr(NewWord,A_LoopField,False,Position) ;find next character in the current word if only subsequence matched
			If A_LoopField Is Upper
			{
				Char := SubStr(NewWord,Position,1)
				StringUpper, Char, Char
				NewWord := SubStr(NewWord,1,Position - 1) . Char . SubStr(NewWord,Position + 1)
			}
		}
		StringCaseSense, %CaseSense%
	}

	;send the word
	Send, % "{BS " . StrLen(CurrentWord) . "}" ;clear the typed word
	SendRaw, %NewWord%
}

TextWidth(String) ; return length*10
{
	static Typeface := "Courier New"
	static Size := 10
	static hDC, hFont := 0, Extent
	If !hFont
	{
		hDC := DllCall("GetDC","UPtr",0,"UPtr")
		Height := -DllCall("MulDiv","Int",Size,"Int",DllCall("GetDeviceCaps","UPtr",hDC,"Int",90),"Int",72)
		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)
		hOriginalFont := DllCall("SelectObject","UPtr",hDC,"UPtr",hFont,"UPtr")
		VarSetCapacity(Extent,8)
	}
	DllCall("GetTextExtentPoint32","UPtr",hDC,"Str",String,"Int",StrLen(String),"UPtr",&Extent)
	Return, NumGet(Extent,0,"UInt")
}

URLEncode(Text) {
	StringReplace, Text, Text, `%, `%25, All
	FormatInteger := A_FormatInteger, FoundPos := 0
	SetFormat IntegerFast, Hex
	While FoundPos := RegExMatch(Text,"S)(*UCP)[^\w-\.~%]",Char,FoundPos + 1)
		StringReplace Text, Text, %Char%, % "%" . SubStr("0" . SubStr(Asc(Char),3),-1), All
	SetFormat IntegerFast, %FormatInteger%
	Return Text
}

URLDecode(Encoded) {
	FoundPos := 0
	While FoundPos := InStr(Encoded,"%",False,FoundPos + 1)
	{
		Value := SubStr(Encoded,FoundPos + 1,2)
		If (Value != "25")
			StringReplace, Encoded, Encoded, `%%Value%, % Chr("0x" . Value), All
	}
	StringReplace Encoded, Encoded, `%25, `%, All
	Return Encoded
}

Спасибо большое! Буду пробовать!

5

Re: AHK: Автозавершение вводимого текста

stealzy, Ваш вариант не работает.
=====================================
P.S. есть аналогичные программы работающие с русским?