Match first letter of each word on each line, multiple match scores

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
Rorqual
Posts: 10
Joined: 14 Jan 2017, 13:23

Match first letter of each word on each line, multiple match scores

17 Jan 2017, 19:25

I've created a working demo that uses a wordlist.txt, and allows the user to type and filter the wordlist based on what is typed

For example the wordlist is:

Code: Select all

New
Open
Save As
Page Setup
Print
Exit
Find
Find Next
Replace
Go To
View Help
About Notepad
Status Bar
Word Wrap
Font
Undo
Paste
Cut
Copy
Delete
Select All
Time/Date
The .ahk file I have which is working, allows you to filter the wordlist by left-to-right exact partial match, and also any other partial match as a secondary match (these secondary results are listed towards the bottom of the results). The script also alphabetically orders the word list prior to parsing to help make the results more orderly.

Code: Select all

SetBatchLines, -1
#SingleInstance Force
SetTitleMatchMode, 2
; Create a timer that checks if the popup is no longer the active window. If so, close the gui! (gosub esc to the gui)


; AUTO EXECUTE SECTION ----------------------------------------------------------------
FileRead, FileContents, wordlist.txt ; file read one time at script launch for best efficiency
Sort, FileContents ; sort alphabetically allows better autocomplete behavior
Gui +LastFound  ; Make the GUI window the last found window for use by the line below.
Gui, font, s12, Arial
Gui, Add, Edit, vneedle grefresh w400, ; whenever user types in this editbox, the grefresh g-label runs the refresh subroutine
Gui, Add, ListBox, vresults r6 w400 ; shows the contents of %results% in a listbox
listboxvisible := true
Gui, Show, x500 y500, Suggestions ;show the edit box for the user to type in
GuiControl, Focus, needle
Return

Refresh:
Gui, Submit, NoHide ; Save the user's input without hiding the window
choicelimit := 0 ; resets the listbox choices counter every time the user adds or removes a letter from the edit box
GuiControl,, results, | ; this empties the previous listbox entries
listbox:="" ; this empties variable that controls the listbox entries
if (needle != "") ; if the user's entry isn't empty (if something typed into editbox)
{
Guicontrol, show, results ; show the listbox
listboxvisible := true
Loop, parse, FileContents, `n, `r ; parse the wordlist.txt in memory to find matches
	{
		haystack:=A_LoopField ; cycles each line 1 by 1 matching 1 word at a time
		position := instr(haystack, needle) ; finds out where the user's entry matches the word at (left, middle, or end of word etc.) or if not at all
		if (position = 1) ;if it matches from the left
		{
			listbox.="|" . haystack ; add it to the listbox variable
			choicelimit := choicelimit + 1 ; increase the counter which counts how many results are going to be in the listbox
		}
	}
Loop, parse, FileContents, `n, `r ; parse the wordlist.txt in memory again for a different kind of matching (midstring match)
	{
		haystack:=A_LoopField ; cycles each line 1 by 1 matching 1 word at a time
		position := instr(haystack, needle) ; finds out where the user's entry matches the word at (left, middle, or end of word etc.) or if not at all
		if (position > 1) ; if it matches anywhere but from the left
		{
			listbox.="|" . haystack ; add it to the listbox variable, importantly AFTER the above matches
			choicelimit := choicelimit + 1 ; increase the counter which counts how many results are going to be in the listbox
		}
	}
if (listbox = "" || listbox = "|") {
listboxvisible := false
return
}
GuiControl,, results, %listbox% ; add the matched words to the listbox entries
GuiControl, choose, results, 1 ; choose the first one by default (highlight it)
resultchosen := 1 ; store which choice is highlighted in a variable
}
return

; HOTKEYS ----------------------------------------------------------------
1::
2::
3::
4::
5::
6::
7::
8::
9::
0::
a::
b::
c::
d::
e::
f::
g::
h::
i::
j::
k::
l::
m::
n::
o::
p::
q::
r::
s::
t::
u::
v::
w::
x::
y::
z::
controlsend, Edit1, %A_ThisHotkey%, Suggestions ahk_class AutoHotkeyGUI
Return


^Esc::
Reload
Return
However what I'm trying to get it to do now, is match first-character of each word sequences. For example, "sa" would match Save As, "an" would match About Notepad, "f" would match "Find", "fn" would match "Find Next", etc. I want these matches to take top priority and show at the top of the list

A good test case is typing the letter 'p', right now it will match "Page Setup" as the first result (screenshot below). I would like to make the script prioritize the exact first-letter of the word match for Paste to be at the top, with Print coming in second (because the second letter is alphabetically ordered), and page setup coming in third. But this 'first letter of each word' functionality eludes me

A good second proof the functionality is working would be to type "ps" and have the only result be "Page Setup", as it is now nothing appears.

Image

Do I need a match-scoring system to incorporate this new first letter of each word search functionality as well or can I do without it?
list
Posts: 222
Joined: 26 Mar 2014, 14:03
Contact:

Re: Match first letter of each word on each line, multiple match scores

25 Jan 2017, 15:01

Try something like this, you would need to prepare a Special Sort function to order the words before you start searching in your preferred order (see the Sort docs for details) - this searches twice, first it does a "magic" search which translates the letters you to look for the beginning of words so fn is find next, if it can't find a match it will do a normal instr search so typing fi would show "find next" and "find" and fi is both words.

Code: Select all

SetBatchLines, -1
#SingleInstance Force
SetTitleMatchMode, 2
; Create a timer that checks if the popup is no longer the active window. If so, close the gui! (gosub esc to the gui)


; AUTO EXECUTE SECTION ----------------------------------------------------------------
FileRead, FileContents, wordlist.txt ; file read one time at script launch for best efficiency
Sort, FileContents ; sort alphabetically allows better autocomplete behavior
Gui +LastFound  ; Make the GUI window the last found window for use by the line below.
Gui, font, s12, Arial
Gui, Add, Edit, vneedle grefresh w400, ; whenever user types in this editbox, the grefresh g-label runs the refresh subroutine
Gui, Add, ListBox, vresults r6 w400 ; shows the contents of %results% in a listbox
listboxvisible := true
Gui, Show, x500 y500, Suggestions ;show the edit box for the user to type in
GuiControl, Focus, needle
Return

Refresh:
Gui, Submit, NoHide ; Save the user's input without hiding the window
choicelimit := 0 ; resets the listbox choices counter every time the user adds or removes a letter from the edit box
GuiControl,, results, | ; this empties the previous listbox entries
listbox:="" ; this empties variable that controls the listbox entries
if (needle != "") ; if the user's entry isn't empty (if something typed into editbox)
{
Guicontrol, show, results ; show the listbox
listboxvisible := true

Loop, parse, FileContents, `n, `r ; parse the wordlist.txt in memory to find matches
	{
		SearchRe:=""
		haystack:=A_LoopField ; cycles each line 1 by 1 matching 1 word at a time
 		Loop, parse, needle
			SearchRe .= "\b" Upper(A_LoopField) ".*" ; similar to magic search in lintalist only added \b
		SearchRe:=RTrim(SearchRe,".*")
		If (RegExMatch(haystack, SearchRe) > 0)
			{
				listbox.= "|" . haystack ; add it to the listbox variable
				continue
			}

		If InStr(haystack, needle)
			listbox.= "|" . haystack ; add it to the listbox variable
			
	}

;Loop, parse, FileContents, `n, `r ; parse the wordlist.txt in memory to find matches
;	{
;		haystack:=A_LoopField ; cycles each line 1 by 1 matching 1 word at a time
;		position := instr(haystack, needle) ; finds out where the user's entry matches the word at (left, middle, or end of word etc.) or if not at all
;		if (position = 1) ;if it matches from the left
;		{
;			listbox.= "|" . haystack ; add it to the listbox variable
;			choicelimit := choicelimit + 1 ; increase the counter which counts how many results are going to be in the listbox
;		}
;	}
;Loop, parse, FileContents, `n, `r ; parse the wordlist.txt in memory again for a different kind of matching (midstring match)
;	{
;		haystack:=A_LoopField ; cycles each line 1 by 1 matching 1 word at a time
;		position := instr(haystack, needle) ; finds out where the user's entry matches the word at (left, middle, or end of word etc.) or if not at all
;		if (position > 1) ; if it matches anywhere but from the left
;		{
;			listbox.="|" . haystack ; add it to the listbox variable, importantly AFTER the above matches
;			choicelimit := choicelimit + 1 ; increase the counter which counts how many results are going to be in the listbox
;		}
;	}
if (listbox = "" || listbox = "|") {
listboxvisible := false
return
}
GuiControl,, results, %listbox% ; add the matched words to the listbox entries
GuiControl, choose, results, 1 ; choose the first one by default (highlight it)
resultchosen := 1 ; store which choice is highlighted in a variable
}
return

Upper(in)
	{
	 StringUpper, in, in
	 Return in
	}

; HOTKEYS ----------------------------------------------------------------
1::
2::
3::
4::
5::
6::
7::
8::
9::
0::
a::
b::
c::
d::
e::
f::
g::
h::
i::
j::
k::
l::
m::
n::
o::
p::
q::
r::
s::
t::
u::
v::
w::
x::
y::
z::
controlsend, Edit1, %A_ThisHotkey%, Suggestions ahk_class AutoHotkeyGUI
Return


^Esc::
Reload
Return

Esc::
GuiClose:
ExitApp
Return
User avatar
FanaticGuru
Posts: 1906
Joined: 30 Sep 2013, 22:25

Re: Match first letter of each word on each line, multiple match scores

25 Jan 2017, 19:23

Below is an example of using a constructed Needle for RegExMatch to find words that start with certain letters or several words that each start with the letters looked for.

For Example: "sa" will find both "Save" and "Select All".

Code: Select all

List =
(Join`n
New
Open
Save
Save As
Page Setup
Print
Exit
Find
Find Next
Replace
Go To
View Help
About Notepad
Status Bar
Word Wrap
Font
Undo
Paste
Cut
Copy
Delete
Select All
Time/Date
Select As New File
)
MsgBox % List

SearchString := "sa"	
Loop, Parse, SearchString
{
	Word .= A_LoopField
	Words .= A_LoopField "\w* "
}
Words := SubStr(Words, 1, -4)
Needle := "mi`a)(^" Word ".*$|^" Words ".*$)"

X := 0
while (X := RegExMatch(List, Needle, Match, X+1))
	Display .= Match1 "`n"

MsgBox % Display

Esc::ExitApp
Below is a link to a Sift functions and a fairly complex GUI that demonstrates its use that you might also find helpful.

FG
Hotkey Help - Help Dialog for Currently Running AHK Scripts
AHK Startup - Consolidate Multiply AHK Scripts with one Tray Icon
Hotstring Manager - Create and Manage Hotstrings
[Class] WinHook - Create Window Shell Hooks and Window Event Hooks

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Google [Bot], mebelantikjaya, Rohwedder and 335 guests