Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

[WIP] Method: IntelliEdit (v0.2)


  • Please log in to reply
13 replies to this topic
sumon
  • Moderators
  • 1317 posts
  • Last active: Dec 05 2016 10:14 PM
  • Joined: 18 May 2010
This is a work in progress.

About

Intellisense takes input and suggests output.

IntelliEdit is an intellisense-like Gui Control inspired by all autocomplete input fields around, such as the Chrome Omnibar or smart autocomplete-function on modern phones. It's a method to turn an edit field into an intelligent edit field, that suggests outputs.

Posted Image

Changelog

0.1. Original release, proves method is viable
0.2. Made it continue after one word, added min-length, improved hotkeys, added FileRead example (zzzooo10 & Elesar)
0.3. Control := A_GuiControl (possible to use several controls)


Fun "facts" about IntelliEdit

- It is more reliable and less memory consuming than other solutions such as Input or timers
- I plan to use this in Go for the next update
- It has the potential to save keypresses & time in many scripts, making them more user friendly
- I intend to improve it over time to successfully return an appropiate suggestion for any situation*
- This will be a function includable by anyone in their scripts, and library

Without further ado:

#SingleInstance, Force
IfExist, word_list.txt
   FileRead, List, word_list.txt ; Read input from external file?
else
   List := "Autohotkey,Barrack Obama,Caesar,Delta Quadrant,Elephant,Antonius" ; Any commadelimitered list of the potential "matches"

Sort, List, D`, ; Important that the list is alphabetical
Gui, Add, Edit, gIntelliEdit hwndIntelliControl vControl, ; Note the gRoutine, hwndID and vVar: All are used later
Gui, Show,, GuiWin
return

#If (WinActive("GuiWin")) ; Optional/configurable part: Hotkey to "verify" the suggestion
Tab::
If IntelliHotkey
    Send {Right}{Space}
return
#If

IntelliEdit:
Control := A_GuiControl ; Added in v0.3
If (GetKeyState("Backspace","P") OR GetKeyState("Delete", "P") ; Added by zzzooo10 (+sumon v0.3)
    Return
Gui, Submit, Nohide
Suggestion := IntelliEdit(Control, List) ; See the function
If (Suggestion)
{
   StringSplit, Words, Control, %A_Space% ; Checks to see if there is more then one word
   Words := Words%Words0%
   Suggestion := Words0 > 1 ? SubStr(Control, 1, StrLen(Control) - StrLen(Words))  . Suggestion : Suggestion ; If there is append the Suggestion to Control, else replace the whole edit box.
   GuiControl,, Control, %Suggestion%
   PostMessage, 0xB1, % StrLen(Control), % StrLen(Suggestion),, ahk_id %IntelliControl% ; EM_SETSEL
   IntelliHotkey := "True"
}
else
   IntelliHotkey := "False"
return

IntelliEdit(Control, List="", Length=1) ; Input the content to check for, and the matches (edit-control & list)
{
   If (StrLen(Control) < 1) ; If input string is empty
      return 0
   StringSplit, Word, Control, %A_Space% ; Gets the current word.
   Word := Word%Word0%
   Loop, Parse, List, `, ; Look for consecutive alphabetical match
   {
      If ((( Word < A_LoopField) AND ( Word > Previous) AND InStr(A_LoopField, Word )) AND StrLen(Word) >= Length)
         Return A_LoopField ; Return the closest alphabetical match
      else
         Previous := A_Loopfield
   }
   return
}

Requirements

- A commadelimitered list of matches (f.ex. from ini_getAllSectionNames() or similar)
- The Edit control must have a subroutine that calls the function, a handle to operate upon and a variable holding its' contents
- Get the value, compare it with matches, return eventual match, set the selector appropiately in the Edit Control
- (Optional) A hotkey to verify the choice

*Wish list

Let me first say that general improvements will be edited into the method/function and credited to their author, so I hope you can contribute if you have any ideas. Anyway, in Launchy, a great keystroke app launcher, the intellisense is pretty powerful. Let's say the potential matches are "Alpha,Autohotkey,Hot sauce"

a -> Alpha
au -> Autohotkey
auc -> Hot sauce (because "auc" is a part of "sauce")
hot -> Hot sauce (prio'd over Autohotkey because hot's in the beginning of "Hot sauce")

So, I would like the function to work like this, ideally, but I couldn't wrap my head around how to solve it. Basically, consecutive letters are necessary for a match. The more consecutive letters the better, and the first letter is the most important to match (potentially, it could also give extra value to the first letter of any "second word", such as the s in "Hot sauce").

Other suggestions for improvement are welcome.

The greatest thing about this, of course, is that it can be used in any edit control, giving you free hands to make it look basically however you wish - Jon's "Jump" launcher comes to mind.

nimda
  • Members
  • 4368 posts
  • Last active: Aug 09 2015 02:36 AM
  • Joined: 26 Dec 2010
Two things:
1) Just because we have #If doesn't mean we should use it all the time. #If WinActive() doesn't perform as well as #IfWinActive
2.) typing auc and getting hot sauce would really piss me off if I wanted "auction", but "auction" wasn't yet in the list. Even Chrome's bar doesn't pull that crap on you.

sumon
  • Moderators
  • 1317 posts
  • Last active: Dec 05 2016 10:14 PM
  • Joined: 18 May 2010

Two things:
1) Just because we have #If doesn't mean we should use it all the time. #If WinActive() doesn't perform as well as #IfWinActive
2.) typing auc and getting hot sauce would really piss me off if I wanted "auction", but "auction" wasn't yet in the list. Even Chrome's bar doesn't pull that crap on you.


Ok, two answers:
1) True, I was intending to add another requirement (#If (WinActive() AND Suggestion)), but that failed. Why?
2) Depends on what the list is of course, if it's a static list of things that you to some level expect (such as in "Go" or "Launchy" - I usually write "zilla" when I need to open FileZilla) it might be useful, but in other places, like you say, it's crap. Maybe make that one optional.

In general, the rating of the matches could be very indepth if need-be, depending on how often items were chosen, when they were last chosen, etc. But my "wishes" should go a pretty long way. Another idea would be to include an optional "lasthand" list, for example the keys of an ini file (if prio A was the sections). The practical use for this would be that I could have an ini with:

[Simon Strålberg]
Location=Sweden
Nickname=sumon

[Anon Ymous]
Location=USA
Nickname=guest

Then make a search for either Si(mon) or su(mon). If I wrote "mon" I would get "Simon" since it was higher prio. I would use this all the time to make reverse-lookups on people in different adress books I have stored as inis.

nimda
  • Members
  • 4368 posts
  • Last active: Aug 09 2015 02:36 AM
  • Joined: 26 Dec 2010
lol
My phone does crazy things on this website
I fixed that before I saw your reply
Edit: and you fixed it before I was done with this reply
1) Probably failed because Suggestion wasn't set correctly
2) How 'bout being able to specify the delimiter?

zzzooo10
  • Members
  • 237 posts
  • Last active: Apr 14 2015 01:57 AM
  • Joined: 19 Dec 2010
Nice script. One thing that bugged me was when you backspace when intelliedit was suggesting a word nothing would happen.
So I added these two lines so you can actually backspace.
#SingleInstance, Force
List := "Autohotkey,Barrack Obama,Caesar,Delta Quadrant,Elephant,Antonius" ; Any commadelimitered list of the potential "matches"
Sort, List, D`, ; Important that the list is alphabetical
Gui, Add, Edit, gIntelliEdit hwndIntelliControl vControl, ; Note the gRoutine, hwndID and vVar: All are used later
Gui, Show,, GuiWin
return

#If (WinActive("GuiWin")) ; Optional/configurable part: Hotkey to "verify" the suggestion
Enter::
Send {Right}{Space}
return
#If

IntelliEdit:
[color=red]If GetKeyState("BackSpace","P")
    Return[/color]
Gui, Submit, Nohide
Suggestion := IntelliEdit(Control, List) ; See the function
If (Suggestion)
{
   GuiControl,, Control, %Suggestion%
   PostMessage, 0xB1, % StrLen(Control), % StrLen(Suggestion),, ahk_id %IntelliControl% ; EM_SETSEL
   IntelliHotkey := "True"
}
else
   IntelliHotkey := "False"
return

IntelliEdit(Control, List="") ; Input the content to check for, and the matches (edit-control & list)
{
   If (StrLen(Control) < 1) ; If input string is empty
      return 0
   Loop, Parse, List, `, ; Look for consecutive alphabetical match
   {
      If (((Control < A_LoopField) AND (Control > Previous) AND InStr(A_LoopField, Control)))
         return A_LoopField ; Return the closest alphabetical match
      else
         Previous := A_Loopfield
   }
   return
}


sumon
  • Moderators
  • 1317 posts
  • Last active: Dec 05 2016 10:14 PM
  • Joined: 18 May 2010

Nice script. One thing that bugged me was when you backspace when intelliedit was suggesting a word nothing would happen.
So I added these two lines so you can actually backspace. [... code ...]


Thanks, and thanks :) Yeah, that's why I added the [WIP], I don't consider it finished, so I'm thankful for all the help! Added your suggestion, good one.

Of course depending on the application you might wanna add more hotkeys or name the variables etc. differently, for example if you're making a program launcher such as Launchy or Jump, you might wanna do like Launchy so you can also pass commandline arguments (or copy the path of the app you selected) to the application by pressing tab. If you do, it adds a "►" and waits for the commandline argument.

zzzooo10
  • Members
  • 237 posts
  • Last active: Apr 14 2015 01:57 AM
  • Joined: 19 Dec 2010
I made another improvement to this helpful script.
After the first word was completed it would stop giving suggestions. I fixed that, now it continues to give you suggestions after the first word.
There was also a small problem with the word "Quote". If you typed in "o" it would suggest Quote.
So I decided to add a minimum length before it suggests any words. After IntelliEdit(Control, List) List specify the number of letters before it starts to suggests any words. It defaults to 0.
I also made the hotkey for auto complete only activate if there was a match.

Before:
Posted Image
After:
Posted Image
Changes in RED
#SingleInstance, Force
List := "Autohotkey,Barrack Obama,Caesar,Delta Quadrant,Elephant,Antonius" ; Any commadelimitered list of the potential "matches"
[color=red]Length := 0 ; Change this to the number of letters before it starts to suggests words.[/color]
Sort, List, D`, ; Important that the list is alphabetical
Gui, Add, Edit, gIntelliEdit hwndIntelliControl vControl, ; Note the gRoutine, hwndID and vVar: All are used later
Gui, Show,, GuiWin
return

#If (WinActive("GuiWin")) ; Optional/configurable part: Hotkey to "verify" the suggestion
Tab::
[color=red]If IntelliHotkey
    Send {Right}{Space}
return[/color]
#If

IntelliEdit:
If GetKeyState("Backspace","P") ; Added by zzzooo10
    Return
Gui, Submit, Nohide
Suggestion := IntelliEdit(Control, List[color=red], Length[/color]) ; See the function
If (Suggestion)
{
   [color=red]StringSplit, Words, Control, %A_Space% ; Checks to see if there is more then one word
   Words := Words%Words0%
   Suggestion := Words0 > 1 ? SubStr(Control, 1, StrLen(Control) - StrLen(Words))  . Suggestion : Suggestion ; If there is append the Suggestion to Control, else replace the whole edit box.[/color]
   GuiControl,, Control, %Suggestion%
   PostMessage, 0xB1, % StrLen(Control), % StrLen(Suggestion),, ahk_id %IntelliControl% ; EM_SETSEL
   IntelliHotkey := "True"
}
else
   IntelliHotkey := "False"
return

IntelliEdit(Control, List="", [color=red]Length=0[/color]) ; Input the content to check for, and the matches (edit-control & list)
{
   If (StrLen(Control) < 1) ; If input string is empty
      return 0
   [color=red]StringSplit, Word, Control, %A_Space% ; Gets the current word.
   Word := Word%Word0%[/color]
   Loop, Parse, List, `, ; Look for consecutive alphabetical match
   {
      If ((( [color=red] Word [/color] < A_LoopField) AND ( [color=red] Word [/color] > Previous) AND InStr(A_LoopField, [color=red] Word [/color] )) [color=red]AND StrLen(Word) >= Length)[/color]
         Return A_LoopField ; Return the closest alphabetical match
      else
         Previous := A_Loopfield
   }
   return
}


Elesar
  • Members
  • 696 posts
  • Last active: May 08 2015 09:51 PM
  • Joined: 28 Jun 2007
Adding to zzzooo10's last change, I altered the script to read the list of inputs from a text file. This can be a list of words either each on a new line, or comma separated. Not a huge change, and really only shows that it is possible to have an external listing so that compiled scripts could alter their suggestion list without the need to recompile.

#SingleInstance, Force
[color=red]IfExist, word_list.txt
	FileRead, List, word_list.txt
else
{
    MsgBox, Word list not found!
    ExitApp
}
StringReplace, List, List, `n, `,, All[/color]
Length := 0 ; Change this to the number of letters before it starts to suggests words.
Sort, List, D`, ; Important that the list is alphabetical
Gui, Add, Edit, gIntelliEdit hwndIntelliControl vControl, ; Note the gRoutine, hwndID and vVar: All are used later
Gui, Show,, GuiWin
return

#If (WinActive("GuiWin")) ; Optional/configurable part: Hotkey to "verify" the suggestion
Tab::
If IntelliHotkey
    Send {Right}{Space}
return
#If

IntelliEdit:
If GetKeyState("Backspace","P") ; Added by zzzooo10
    Return
Gui, Submit, Nohide
Suggestion := IntelliEdit(Control, List, Length) ; See the function
If (Suggestion)
{
   StringSplit, Words, Control, %A_Space% ; Checks to see if there is more then one word
   Words := Words%Words0%
   Suggestion := Words0 > 1 ? SubStr(Control, 1, StrLen(Control) - StrLen(Words))  . Suggestion : Suggestion ; If there is append the Suggestion to Control, else replace the whole edit box.
   GuiControl,, Control, %Suggestion%
   PostMessage, 0xB1, % StrLen(Control), % StrLen(Suggestion),, ahk_id %IntelliControl% ; EM_SETSEL
   IntelliHotkey := "True"
}
else
   IntelliHotkey := "False"
return

IntelliEdit(Control, List="", Length=0, ByRef Word= "") ; Input the content to check for, and the matches (edit-control & list)
{
   If (StrLen(Control) < 1) ; If input string is empty
      return 0
   StringSplit, Word, Control, %A_Space% ; Gets the current word.
   Word := Word%Word0%
   Loop, Parse, List, `, ; Look for consecutive alphabetical match
   {
      If ((( Word < A_LoopField) AND ( Word > Previous) AND InStr(A_LoopField, Word )) AND StrLen(Word) >= Length)
         Return A_LoopField ; Return the closest alphabetical match
      else
         Previous := A_Loopfield
   }
   return
}


sumon
  • Moderators
  • 1317 posts
  • Last active: Dec 05 2016 10:14 PM
  • Joined: 18 May 2010
Modified your edits and put them in.

shajul
  • Members
  • 571 posts
  • Last active: Aug 01 2015 03:45 PM
  • Joined: 15 Sep 2006
Now we have some collaboration on the forums 8)
I like the way this is progressing.. Keep it up..
If i've seen further it is by standing on the shoulders of giants

my site | ~shajul | WYSIWYG BBCode Editor

zzzooo10
  • Members
  • 237 posts
  • Last active: Apr 14 2015 01:57 AM
  • Joined: 19 Dec 2010
Here is an improvement to the hotkey.
#SingleInstance, Force

IfExist, word_list.txt

   FileRead, List, word_list.txt ; Read input from external file?

else

   List := "Autohotkey,Barrack Obama,Caesar,Delta Quadrant,Elephant,Antonius" ; Any commadelimitered list of the potential "matches"



Sort, List, D`, ; Important that the list is alphabetical

Gui, Add, Edit, gIntelliEdit hwndIntelliControl vControl, ; Note the gRoutine, hwndID and vVar: All are used later

Gui, Show,, GuiWin

return



#If (WinActive("GuiWin")) ; Optional/configurable part: Hotkey to "verify" the suggestion

Tab::

If IntelliHotkey

    Send {Right}{Space}

[color=red]IntelliHotkey := False[/color]

return

#If



IntelliEdit:

If GetKeyState("Backspace","P") ; Added by zzzooo10

    Return

Gui, Submit, Nohide

Suggestion := IntelliEdit(Control, List) ; See the function

If (Suggestion)

{

   StringSplit, Words, Control, %A_Space% ; Checks to see if there is more then one word

   Words := Words%Words0%

   Suggestion := Words0 > 1 ? SubStr(Control, 1, StrLen(Control) - StrLen(Words))  . Suggestion : Suggestion ; If there is append the Suggestion to Control, else replace the whole edit box.

   GuiControl,, Control, %Suggestion%

   PostMessage, 0xB1, % StrLen(Control), % StrLen(Suggestion),, ahk_id %IntelliControl% ; EM_SETSEL

   [color=red]IntelliHotkey := True[/color]

}

else [color=red]if (!RegExMatch(List, Words))[/color] ; If the word is not in the list.

   [color=red]IntelliHotkey := False[/color]

return



IntelliEdit(Control, List="", static Length=1) ; Input the content to check for, and the matches (edit-control & list)

{

   If (StrLen(Control) < 1) ; If input string is empty

      return 0

   StringSplit, Word, Control, %A_Space% ; Gets the current word.

   Word := Word%Word0%

   Loop, Parse, List, `, ; Look for consecutive alphabetical match

   {

      If ((( Word < A_LoopField) AND ( Word > Previous) AND InStr(A_LoopField, Word )) AND StrLen(Word) >= Length)

         Return A_LoopField ; Return the closest alphabetical match

      else

         Previous := A_Loopfield

   }

   return

}


Elesar
  • Members
  • 696 posts
  • Last active: May 08 2015 09:51 PM
  • Joined: 28 Jun 2007
Has any thought been put into making this a combo-box rather than an edit?
It may be nice to have a list of possible matches display while typing. Ill look into it when I get a chance later on today.

EDIT:
In the latest version, this line gives me trouble:
IntelliEdit(Control, List="", static Length=1)

SciTE4AutoHotkey gives the following output:
Parameter default required. Specifically: static


SoLong&Thx4AllTheFish
  • Members
  • 4999 posts
  • Last active:
  • Joined: 27 May 2007
@elesar: yes that would be my preference, there is a nice gui framework in TypingAid (the gui resizes auto the less results you have) <!-- m -->http://www.autohotke...pic.php?t=53630<!-- m -->

sumon
  • Moderators
  • 1317 posts
  • Last active: Dec 05 2016 10:14 PM
  • Joined: 18 May 2010

Has any thought been put into making this a combo-box rather than an edit?
It may be nice to have a list of possible matches display while typing. Ill look into it when I get a chance later on today.

EDIT:
In the latest version, this line gives me trouble:

IntelliEdit(Control, List="", static Length=1)

SciTE4AutoHotkey gives the following output:
Parameter default required. Specifically: static


I will fix that, I was screwing it up by adding static.

Anyway, we will probably be having alot of "options" and preferences (delimiter, length, number of returns, optional "second list" of items), any ideas of how to structure it up better? I was just providing a concept, so feel free to try to make subfunctions or whatever.