Default/Portable installation StdLib

Propose new features and changes
Coco
Posts: 771
Joined: 29 Sep 2013, 20:37
GitHub: cocobelgica

Default/Portable installation StdLib

14 Nov 2015, 23:58

Not really sure if this should be a poll or not, I(or a mod/admin) can change it later on if necessary. I would like to make a suggestion on including some core lib scripts w/ the basic AHK installation and ZIP download. By "core", particularly a function version of all AHK commands(only those retained in v2) and of course naming(and syntax) should follow that of v2(e.g.: FileSelectFile becomes FileSelect and so on..). Some pros and cons:
PROS:
  • Addresses some limitations/quirks. Like passing/forcing expressions etc. (e.g.: SetTimer(Func("foo").Bind(args*), -1))
  • Scripts written onwards should be easier to port to v2
  • Easier transition to v2
  • I know there are still others
CONS:
  • Bloat, Installation size - they're just text files so this shouldn't be that big of an issue
  • Portability - compiler addresses this or if compiling is not an option, it's easy to write a "release" script or a script consolidator
  • Who'll perform the command-to-function port? - I'm willing to do this
What do you think?
Coco
Posts: 771
Joined: 29 Sep 2013, 20:37
GitHub: cocobelgica

Re: Default/Portable installation StdLib

06 Mar 2016, 12:13

I decided to work on this - Github repo

Edit: (I'm including the Notes, limitations and todos here for reference)
Notes, limitations, todo:
  • ListVars() can only list global variables.
  • FileInstall() will only perform a FileCopy.
  • Gui("Add", ...) - the control's associated variable must be global. Declaring as static is currently impossible.
  • GuiControl() and GuiControlGet() can only operate on global variables(control's associated variable). Use ControlHwnd or ClassNN instead if needed.
  • Fix WinSetXXX() return values. In v2.0-a, ErrorLevel is returned. However, most of WinSet sub-commands in v1.1 do not use ErrorLevel. Perhaps ErrorLevel can be determined using A_LastError.
  • In v2, Func("MenuSelect").MinParams returns 0. However when called using command syntax, an error is thrown when a required parameter is omitted. There are probably other commands/functions that behave like this. Best to check using Func object properties.
  • Random() limitation -> how to mimic Random,, NewSeed?
Last edited by Coco on 07 Mar 2016, 12:11, edited 1 time in total.
lexikos
Posts: 6207
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

Re: Default/Portable installation StdLib

06 Mar 2016, 20:34

Where would you prefer to discuss your script/the limitations/todos listed at GitHub? In GitHub Issues, here or in another topic?
Coco
Posts: 771
Joined: 29 Sep 2013, 20:37
GitHub: cocobelgica

Re: Default/Portable installation StdLib

07 Mar 2016, 12:00

lexikos wrote:Where would you prefer to discuss your script/the limitations/todos listed at GitHub? In GitHub Issues, here or in another topic?
For visibility, so that others(including non-GitHub users) can chime in, I guess the forum is the best place. I'm not so sure if we should continue it here on this topic or split it up though... I've included the limitations/todos in my previous post, we can split it up from there if we decide to split this into a new topic.
lexikos
Posts: 6207
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

Re: Default/Portable installation StdLib

07 Mar 2016, 19:10

Fix WinSetXXX() return values. In v2.0-a, ErrorLevel is returned. However, most of WinSet sub-commands in v1.1 do not use ErrorLevel. Perhaps ErrorLevel can be determined using A_LastError.
WinSet doesn't update A_LastError. For the sub-commands which don't set ErrorLevel, I think it would be sufficient to consider it a success if the window exists. For efficiency, you could use WinExist() first and pass ahk_id to WinSet.
FileInstall() will only perform a FileCopy.
Whether for v2 or for this script, Ahk2Exe will need to be extended to parse expressions like FileInstall("Some\Path.ext", ...) if that syntax will be supported. If that was done, this script could use the Win32 resource API to extract the file data.

An alternative would be to have a more general function for extracting resources, and require the script to use the "upcoming" resource directives, but I suppose then you'd need to repeat the resource name/path.
lexikos
Posts: 6207
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

Re: Default/Portable installation StdLib

07 Mar 2016, 20:59

In v2, Func("MenuSelect").MinParams returns 0. However when called using command syntax, an error is thrown when a required parameter is omitted.
MinParams is 0 because WinTitle and WinText can be omitted, as in MenuSelect(,, "File", "Open"), which operates on the Last Found Window. That you can't omit the third parameter is only one of many requirements that are enforced at load time for specific commands, but not for the corresponding function (including MenuSelect()). Some checks are only done at load time, and only for args which are not variables/expressions.

For commands, only optional parameters can be completely blank; to pass an empty value to a mandatory parameter, you have to use a variable or expression.
Random() limitation -> how to mimic Random,, NewSeed?
Similarly, Input OutputVar starts collecting input with default options, while Input just cancels a previous call to the Input command (or does nothing).
lexikos
Posts: 6207
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

Re: Default/Portable installation StdLib

08 Mar 2016, 01:48

InputBox in v2 validates its options. There's probably not much need to duplicate the behaviour to that extent, but in this case we can simplify (or at least shorten ;)) your code and gain validation at the same time. Instead of a parsing loop, we can use a single regex:

Code: Select all

Options := "x0 y0 w100 h100 T10.0 Password*"
Valid := RegExMatch(Options, "i)^\s*(?:(?:X(?<X>\S*)|Y(?<Y>\S*)|W(?<W>\S*)|H(?<H>\S*)|T(?<T>\S*)|(?<P>Password\S?))\s*)*$", _)
ListVars
Pause
I think this is consistent with what v2-alpha accepts. Of course, InputBox in v1 still doesn't support Password* and you would need to use % _P ? "HIDE" : "" for the HIDE parameter.
Coco
Posts: 771
Joined: 29 Sep 2013, 20:37
GitHub: cocobelgica

Re: Default/Portable installation StdLib

09 Mar 2016, 12:09

lexikos wrote:WinSet doesn't update A_LastError. For the sub-commands which don't set ErrorLevel, I think it would be sufficient to consider it a success if the window exists. For efficiency, you could use WinExist() first and pass ahk_id to WinSet.
I see. Regarding WinExist(), I guess I would need to store the current "LastFound window" first then restore it back before returning. Otherwise the function might interfere with the user's script functionality, in rare cases. Another thing, which is more efficient, passing ahk_id %Hwnd% or omitting all the window parameters to take advantage of the "LastFound window" feature? The docs says that the script performs better with the latter..
lexikos wrote:Whether for v2 or for this script, Ahk2Exe will need to be extended to parse expressions like FileInstall("Some\Path.ext", ...) if that syntax will be supported. If that was done, this script could use the Win32 resource API to extract the file data.

An alternative would be to have a more general function for extracting resources, and require the script to use the "upcoming" resource directives, but I suppose then you'd need to repeat the resource name/path.
I see. For now I'll just retain the FileCopy behavior and wait for Ahk2Exe's progress.
lexikos wrote:MinParams is 0 because WinTitle and WinText can be omitted, as in MenuSelect(,, "File", "Open"), which operates on the Last Found Window. That you can't omit the third parameter is only one of many requirements that are enforced at load time for specific commands, but not for the corresponding function (including MenuSelect()). Some checks are only done at load time, and only for args which are not variables/expressions.
Thanks for the confirmation. I'd have to review some of the functions. I think I might have overlooked some aside from MenuSelect().
lexikos wrote:InputBox in v2 validates its options. There's probably not much need to duplicate the behaviour to that extent, but in this case we can simplify (or at least shorten ;)) your code and gain validation at the same time. Instead of a parsing loop, we can use a single regex:

Code: Select all

Options := "x0 y0 w100 h100 T10.0 Password*"
Valid := RegExMatch(Options, "i)^\s*(?:(?:X(?<X>\S*)|Y(?<Y>\S*)|W(?<W>\S*)|H(?<H>\S*)|T(?<T>\S*)|(?<P>Password\S?))\s*)*$", _)
ListVars
Pause
I think this is consistent with what v2-alpha accepts. Of course, InputBox in v1 still doesn't support Password* and you would need to use % _P ? "HIDE" : "" for the HIDE parameter.
Thanks, applied your suggestion in this commit. I modified your pattern a little bit to clone v2's strict validation. Added error handling as well for invalid options.
lexikos
Posts: 6207
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

Re: Default/Portable installation StdLib

09 Mar 2016, 16:22

I hadn't considered the Last Found Window. Yes, using it is marginally faster. Either way should be somewhat faster than using the title, which requires enumerating windows, retrieving and comparing the title of each window. But saving and restoring it might make it slower overall. You can avoid that by using WinGet ID.

If you want to know which commands have MinParams = 0, just look in g_act in globaldata.cpp. There are some comments explaining it for some commands.

If you add the pattern (?<Err>\S+)(*ACCEPT) into the regex, it can capture the first invalid option (by causing matching to immediately succeed without further processing).

Code: Select all

Options := "x0 y0 w100 first h100 T10.0 Password* second"
RegExMatch(Options, "i)^\s*(?:(?:X(?<X>-?\d+)|Y(?<Y>-?\d+)|W(?<W>\d+)"
    . "|H(?<H>\d+)|T(?<T>\d+(?:\.\d+)?)|(?<P>Password\S?)"
    . "|(?<Err>\S+)(*ACCEPT)"
    . ")\s*)*$", _)
ListVars
Pause
It would probably be more correct to use [ `t]* in place of \s.
Coco
Posts: 771
Joined: 29 Sep 2013, 20:37
GitHub: cocobelgica

Re: Default/Portable installation StdLib

10 Mar 2016, 10:48

lexikos wrote:I hadn't considered the Last Found Window. Yes, using it is marginally faster. Either way should be somewhat faster than using the title, which requires enumerating windows, retrieving and comparing the title of each window. But saving and restoring it might make it slower overall. You can avoid that by using WinGet ID.
Thanks. I'll go with WinGet ID, saving/restoring the Last Found Window would require several calls to WinExist(). Offtopic, reminds me of a previous wish I had about context managers -> something like using Hwnd := WinExist(...) { } would be a handy feature in similar cases, allowing AHK to restore the original Last Found Window automatically after the block.
lexikos wrote:If you want to know which commands have MinParams = 0, just look in g_act in globaldata.cpp. There are some comments explaining it for some commands.
Nice, thanks, makes it easier :)
lexikos wrote:If you add the pattern (?<Err>\S+)(*ACCEPT) into the regex, it can capture the first invalid option (by causing matching to immediately succeed without further processing).

Code: Select all

Options := "x0 y0 w100 first h100 T10.0 Password* second"
RegExMatch(Options, "i)^\s*(?:(?:X(?<X>-?\d+)|Y(?<Y>-?\d+)|W(?<W>\d+)"
    . "|H(?<H>\d+)|T(?<T>\d+(?:\.\d+)?)|(?<P>Password\S?)"
    . "|(?<Err>\S+)(*ACCEPT)"
    . ")\s*)*$", _)
ListVars
Pause
It would probably be more correct to use [ `t]* in place of \s.
Thanks again, I modified the pattern to to ensure that option(s) are either followed by space(s)/tab(s) or end-of-string($). The \s*/[ \t]*(being 0 or more) in the subpattern allows something like "x0y0w400t2.0" which should be invalid:

Code: Select all

RegExMatch(Options, "i)^[ \t]*(?:(?:X(?<X>-?\d+)|Y(?<Y>-?\d+)|W(?<W>\d+)"
    . "|H(?<H>\d+)|T(?<T>\d+(?:\.\d+)?)|(?<P>Password\S?)"
    . "|(?<Err>\S+)(*ACCEPT)"
    . ")(?=[ \t]|$)[ \t]*)*$", _) ; look-ahead ensures that each option is either followed by space(s)/tab(s) or end-of-string
lexikos
Posts: 6207
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

Re: Default/Portable installation StdLib

11 Mar 2016, 00:56

Re FileInstall: HotKeyIt has updated his Ahk2Exe for v2 to support the function syntax.
Coco
Posts: 771
Joined: 29 Sep 2013, 20:37
GitHub: cocobelgica

Re: Default/Portable installation StdLib

13 Mar 2016, 03:42

lexikos wrote:I think it would be sufficient to consider it a success if the window exists
I've applied the updates for WinSetXXX().
lexikos wrote:Re FileInstall: HotKeyIt has updated his Ahk2Exe for v2 to support the function syntax.
Thanks, I'll look into FileInstall().

Btw, in v2, how to do a Random,, NewSeed when using function syntax? Random("", NewSeed)? Random(NewSeed, "")? Or is it only supported when using command syntax?
lexikos
Posts: 6207
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

Re: Default/Portable installation StdLib

13 Mar 2016, 04:27

There is no way to "omit" the OutputVar when using the function syntax, so it is not supported. It is the same for Input.

My thought is that the syntax of these commands needs to be changed, but I don't know how exactly.
Coco
Posts: 771
Joined: 29 Sep 2013, 20:37
GitHub: cocobelgica

Re: Default/Portable installation StdLib

13 Mar 2016, 07:13

lexikos wrote:There is no way to "omit" the OutputVar when using the function syntax, so it is not supported. It is the same for Input.
I see, I need to fix Input()
lexikos wrote:My thought is that the syntax of these commands needs to be changed, but I don't know how exactly.
How about:
Input:
InputWait, OutputVar [, Options, EndKeys, MatchList ] / OutputVar := InputWait( [, Options, EndKeys, MatchList ] )
InputCancel / InputCancel() OR InputStop / InputStop()

Random:
Based on C# Random Class
Random, Seed / Random( Seed )
RandomNext, OutputVar [, Min, Max ] / OutputVar := RandomNext( [, Min, Max ] )
OR
RandomNum, OutputVar [, Min, Max ] / OutputVar := RandomNum( [, Min, Max ] )

I kinda like InputWait as it really tells what the command does...

Return to “Wish List”

Who is online

Users browsing this forum: No registered users and 7 guests