Jump to content

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

Small Extension to #Include


  • Please log in to reply
43 replies to this topic
corrupt
  • Members
  • 2558 posts
  • Last active: Nov 01 2014 03:23 PM
  • Joined: 29 Dec 2004
Instead of adding options to #Include I had pictured adding a standard include library a bit differently. I haven't put a lot of thought into it but here's the basic idea that I had:

- Create an Include directory in the AHK installation folder
- Create an ini file in this directory called index.ini
- The ini file would contain a function section with a list of commands as keys with the corresponding values being the name of the file containing the associated function in the Include directory.

Then, when a new script is loaded and parsed and finds a reference to a function that doesn't exist, it then checks the .ini file. If the function is found in the .ini file, the associted file containing the function is included at the end of the script.

This way the include directory becomes a standard include library and only scripts that use the included functions are affected. This also allows others the ability to add additional files and update the index to add additional functionality.

An ini file may not end up being an ideal candidate but I've suggested an ini file to make searching for existing/possibly duplicate functions easy, a means to quickly generate a list of functions currently included, a method of adding descriptions for functions in a different section, date function was last updated, function version, etc... all from within one file.

I'm not certain about how easy it would be for the AutoHotkey installer to update the Include directory using this method but it could be as easy as adding an option to run a script at the end of the install process.

This script could then search the .ini file for standard functions and update as necessary. To simplify things a key could be added for each function in a different section with a non-standard include flag to indicate functions that shouldn't be overwritten by the install process. This section (maybe named update) could be checked when updating. If a function name exists as a key with a value of "False" in the update section for example, that function would not be updated/replaced during the install process.

This would make adding additional options to #Include unnecessary and would allow a fair bit of flexibility.

Chris
  • Administrators
  • 10727 posts
  • Last active:
  • Joined: 02 Mar 2004
I'd considered something along those lines but wasn't sure how to implement it (I seem to remember that someone else suggested it too). You've given an approach that seems quite workable and useful.

One downside to automatic resolution of function names is that if a user accidentally calls a nonexistent function (due to spelling error or forgetting to copy the function into the script), the script might wind up calling some unexpected function in the library. Furthermore, the risk of this increases as more functions get added to the library, especially if those functions have common names like ReadXML().

In any case, I'm going to read through your idea again when the time comes to work on the standard library mechanism (the contents of the library is another matter).

Thanks.

polyethene
  • Members
  • 5519 posts
  • Last active: May 17 2015 06:39 AM
  • Joined: 26 Oct 2012

Other than the standard library, what would you use this for in the near term?

I'd like a more standard and unified approach to includes - i.e. my includes stay separate from my scripts.

Generally, it will contain utility functions. For example, there might be a Encryption.ahk file that contains a variety of encryption methods. Also, there could be an XML.ahk to contain functions you might write to handle XML files.

Thanks a brilliant idea :)

autohotkey.com/net Site Manager

 

Contact me by email (polyethene at autohotkey.net) or message tidbit


Chris
  • Administrators
  • 10727 posts
  • Last active:
  • Joined: 02 Mar 2004

i.e. my includes stay separate from my scripts.

I don't know if it would help, but you could do:
#Include C:\My Scripts\My Includes ; Changes working directory for subsequent uses of #Include.
#Include File1.ahk
#Include File2.ahk

But maybe the whole point is that you're trying to avoid having to specify the location of your includes. If so, I don't think most people would find a folder inside the AutoHotkey directory to be a good place because files in there tend to get lost or accidentally deinstalled (e.g. if you have a deinstall helper, or if someone deletes the folder accidentally, forgetting that they have scripts in there).

majkinetor
  • Moderators
  • 4512 posts
  • Last active: May 20 2019 07:41 AM
  • Joined: 24 May 2006
The problem is chain reference, again

What if in some library I have functions A and B and A is implemented so to call B at some meoment:

A(..)
{
  ...
  B
}

Then, what happens when user specifies that he wants to import A function? AHK parser will have to import all functions being part of the chain reference (B can call C, C calls D...)
Posted Image

Tuncay
  • Members
  • 1945 posts
  • Last active: Feb 08 2015 03:49 PM
  • Joined: 07 Nov 2006
Is there any possibility of supporting for regular expression on #Include? For example
#Include *i *r ".\lib\.ahk$"
The *r stands for regex. Another idea is parse the file before including:
#Include *p foo.ahk

No signature.


Chris
  • Administrators
  • 10727 posts
  • Last active:
  • Joined: 02 Mar 2004

Then, what happens when user specifies that he wants to import A function? AHK parser will have to import all functions being part of the chain reference (B can call C, C calls D...)

If this is referring to something I posted, I don't understand. I can say that it's the script's responsibility to include all the files it needs to satisfy inter-function dependencies.

Is there any possibility of supporting for regular expression on #Include? For example

#Include *i *r ".\lib\.ahk$"
The *r stands for regex.

It doesn't seem like that much a benefit to me (I can't envision many people using it). If anyone else feels this should be added, please give as much detail or real-world examples as you can.

Another idea is parse the file before including:

#Include *p foo.ahk

Can you give more detail on what the benefits would be?

Thanks.

corrupt
  • Members
  • 2558 posts
  • Last active: Nov 01 2014 03:23 PM
  • Joined: 29 Dec 2004

The problem is chain reference, again

What if in some library I have functions A and B and A is implemented so to call B at some meoment:

A(..)
{
  ...
  B
}

Then, what happens when user specifies that he wants to import A function? AHK parser will have to import all functions being part of the chain reference (B can call C, C calls D...)


If this is in reference to the "Stardard Library" suggestion I made, then the idea would be to create scripts to be included that create only 1 function or the least amount of functions necessary to perform a task. This would cut down maintenance considerably and reduce the possible confusion of having other functions accidentally & unexpectedly included. This should be an important consideration IMHO.

If I've misunderstood and if your post was in reference to something else then please disregard this one :) .

PhiLho
  • Moderators
  • 6850 posts
  • Last active: Jan 02 2012 10:09 PM
  • Joined: 27 Dec 2005
I don't know exactly how other languages implement this. A good example is the CPAN library for Perl, that has hundred of libraries for every task you can imagine, and a standard way of documenting them.

For the problem of dependencies, I think the simpler and most effective, for a scripted language (so don't compare with Delphi!) is to include a whole file, not to selectively get one function out of a file.

Chances are that most required functions are in the same library file. And if not, that file must #Include the helper libraries. So there in no real problem.
Indeed, compiled scripts will include unneeded files, but that's a very minor issue. If we avoid gigantic files, it shouldn't grow too much the compiled script.

I am in favor of explicit dependencies, that's the way most languages do.
The INI file idea is interesting, but it is too easy to mess with it, loosing functions, referencing functions that no longer exist, etc. Now, perhaps we can imagine a script to update it. But we need at least two INI, one official and one for the functions of the user.

In all cases, this must be carefully designed, as it should last a long time!
Posted Image vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2")

Tuncay
  • Members
  • 1945 posts
  • Last active: Feb 08 2015 03:49 PM
  • Joined: 07 Nov 2006
Another idea is including files got from the script parameter:
#Include *i %1%
And Chris, sorry I stole your time. The construct
#Include *p foo.ahk
is useless, forget about it. :oops:

Hmmm ... I am thinking now ... and ... there is another idea (not wish!) :D:
#Import Function @Script.ahk
. With that, AutoHotkey loads that function in memory for sharing with other scripts, even compiled scripts. (or name it #Link or whatever).

No signature.


Chris
  • Administrators
  • 10727 posts
  • Last active:
  • Joined: 02 Mar 2004
Thanks for the clarification and new ideas.

corrupt
  • Members
  • 2558 posts
  • Last active: Nov 01 2014 03:23 PM
  • Joined: 29 Dec 2004

The INI file idea is interesting, but it is too easy to mess with it, loosing functions, referencing functions that no longer exist, etc. Now, perhaps we can imagine a script to update it. But we need at least two INI, one official and one for the functions of the user.

What would you think of using the same file but using a specific prefix for user functions? Something like: usr_myfunct1, usr_playwav, usr_autolog, etc... The update script could then ignore all functions with a usr_ prefix.

PhiLho
  • Moderators
  • 6850 posts
  • Last active: Jan 02 2012 10:09 PM
  • Joined: 27 Dec 2005

What would you think of using the same file but using a specific prefix for user functions? Something like: usr_myfunct1, usr_playwav, usr_autolog, etc... The update script could then ignore all functions with a usr_ prefix.

The idea was to simplify the installation process, by just overwriting the system INI, but leaving the user's one untouched.
With your idea, Chris has to write a setup script (what it uses? Inno? Nsis?) that carefully deletes obsolete entries, updates others and create new ones. Doable, but might not worth the work.
Plus by separating them, the system one can be read-only, and users won't have a chance of messing with it by error, wanting to change something in their own.
Of course, having a script to automate management of user script is easy to do and should reduce the risk of errors.

We could even add a level of complexity, like it is done in some PHP frameworks: users can have a mirror of the system file folder tree, in which AutoHotkey look first. If it finds the file to include, it takes it. Otherwise, it takes it from the official tree.
What for? Advanced users can tweak their version of system files, and still keep them after auto-update.
Now, it is perhaps too far fetched, and even a bad idea, as they would publish scripts using their own version but perhaps forgetting to provide them... It is better to propose official patches. And one can still do the changes and update with some diff utility instead of blindly overwriting the directories. More work, but that's life! ;-)
Let say I proposed it to evacuate the idea! :-)
Posted Image vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2")

majkinetor
  • Moderators
  • 4512 posts
  • Last active: May 20 2019 07:41 AM
  • Joined: 24 May 2006

If this is referring to something I posted, I don't understand. I can say that it's the script's responsibility to include all the files it needs to satisfy inter-function dependencies.


Don't know why are you all so confused about this (except PhiLho). Its obvious question when talking about single function inport. Its not important otherwise.

The stdlib will get big one day, and may contain hundreed of functions per category. Why to import them all if I need only one ? Ultimaively, I would like to include stdlib as a hole and don't think about location of specific function or the functions it reference. Some of those functions will be internal and messing with them is messing with architechture of stdlib.

Probably, this can be solved internaly when parsing.
For instance, to use whatever func in stdlib, you could specify just #include stdlib.ahk and leave to AHK parser to find where is this function and ignore the rest of the stdlib code. You always talk about compiled version of the script but I talk about non-exe script. Currently, when you do #include SomeLib.ahk, all will be parsed, checked for syntax errors, etc... With large library it will slow down startup, and will eat memory that is required to parse and represent un-important data. So, If have 1000 functions in stdlib and I use 1, they will all be parsed (correct me if I am wrong). Why not AHK parser search the desired function in stdlib.ahk (and its includes) and then, while parsing this function, search for references to other functions that are found in the function body among list of included files, and the recursion goes on. Finally, only desired chain of functions will be parsed, and represented in memory, thus, startup and memory will not suffer. So, if used 1 func that doesn't use other stdlib funcs, it will be the same as I copied this one in my script and commenting #include stdlib. If I used 1 func that reference 10 functions, it should be the same as I pasted those 11 funcs in my code.

Hope this xplains my thoughts a bit...
Posted Image

PhiLho
  • Moderators
  • 6850 posts
  • Last active: Jan 02 2012 10:09 PM
  • Joined: 27 Dec 2005

The stdlib will get big one day, and may contain hundreed of functions per category. Why to import them all if I need only one ?

Because modern computers are fast and have plenty of memory.
I understand your concern, but I think that even loading and parsing a 1MB library file (I hope they never get this big!) would not be noticeable on startup time.
Over-optimizing can be a waste of time and energy...

Plus I don't see any advantage, unless parsing and referencing is done one time before shipping AutoHotkey and stored in some "database". If this is done dynamically, not only AutoHotkey will still have to load the library and parse it (at least to skip non-relevant functions) anyway, but has to resolve dependencies!
Posted Image vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2")