Replies: 6 comments
-
You can set the Modules directory to be any one directory you want, but it's only one directory. IDK if that supports subdirectories which would be nice, but it probably doesn't. I don't think paths work like that. It would be possible to file a separate enhancement issue to make this feature more flexible. IIUC, it just adds a path to the internal path list Python/AutoKey uses for searching for things to import. This doesn't sound complicated, but might have unintended consequences if used too broadly. Apparently the only advantage to using this method is that you can directly import functions/modules from it without any extra work/syntax. These functions still can't use the AutoKey API calls without the injection workaround. Maybe a meta-workaround :) for this would be to write a couple of AutoKey scripts. One would paste the injection code block into a module (while you are creating/editing it) and another would paste the invocation of the injection code block into the calling script. It appears that the first one of these is constant code that requires no variables. The second one requires the name of the module as a parameter. Since it's a one-time thing, a dialog box could be used to get the module name. The only tricky part is making sure that the proper Python indentation levels are maintained when the code blocks are pasted, but we can probably safely assume that this code is being pasted with no unexpected previous indentation in effect and if it's wrong in some special case, the user is still editing the code and can correct it manually. Since these new scripts are normal AutoKey scripts, they can be invoked in the AutoKey script editing panel or in any external editor the user prefers. While this is still considerably convoluted, it should work. Having the above two scripts would somewhat automate the process and make it easier to document/explain to other users. |
Beta Was this translation helpful? Give feedback.
-
It's good to know that the modules that are placed into the AutoKey modules directory also need the injector. You've come up with a functioning injector, though, so that's solved. For automating the insertion of the injector code into the AutoKey script and the external module, you could manually create each of those and then populate them with the contents of AutoKey phrases. If you wanted to get fancy and automate the whole thing, you could script it and have the script create both of them for you after prompting you, like you said, for the script name, and also prompting you for the script's location. Also, the indents wouldn't be an issue if you appended the pasted contents to the file. You could make certain all is well by starting the paste with a newline. By the way, does AutoKey offer a variable for referring to the location of the user-defined module directory? If not, that would make a nice enhancement wish to simplify this sort of scripting. |
Beta Was this translation helpful? Give feedback.
-
By the way, I updated the code above to give basic and API-injected examples for the two different ways to use modules. |
Beta Was this translation helpful? Give feedback.
-
I also found what may be a bug. If you make a change to a module file once AutoKey has found it the first time, AutoKey won't see your change until you close and restart AutoKey (checking to make sure its process was killed before restarting), which can cause you to believe you made a mistake in your newly-added or edited code when it's actually just that AutoKey hasn't read it yet. Is that a bug or intended behavior? |
Beta Was this translation helpful? Give feedback.
-
IIUC, what you are proposing is one level beyond what I proposed. My solution was to "manually" insert the injection code when it is needed while making that easy to do with with a couple of AutoKey scripts. It sounds like you want it to be fully automated and done every time you add a new script. I don't like that for two reasons. 1) It clutters scripts that don't require API calls and 2) It's common (for me at least) to create scripts in a text editor and have AutoKey discover them. It's unclear how these would be automatically modified with the injection code and it could be duplicated if I had already added it. The bug you uncovered might be very easy to fix. AutoKey has a set of directories it watches for external changes. If the Modules directory isn't in that list, then it should be easy to add it. I'm not sure what else it would have to do once it detects such a change. |
Beta Was this translation helpful? Give feedback.
-
Ah, I thought you were after an automated solution. No worries. I'll file a bug report on that bug after I get it written up (have to write up all the steps). |
Beta Was this translation helpful? Give feedback.
-
This is a continuation of a side-discussion that began inside of the Combining hotkeys in one file #711 discussion. It has gotten big enough that it needs its own place to be, so I'm continuing it here. The first part below is in response to @josephj11:
Nope. It turns out that I was wrong.
I was completely wrong. Global and local values can only contain non-serializable objects (anything but functions and classes). I should have remembered that, because it's part of the details I had put into the Persistent Values page when I had first thoroughly experimented with them.
Oddly enough, the script example (from the the Combining hotkeys in one file #711 discussion) that pretends to insert a function into a global value should have thrown an error, but it didn't. When I added those parentheses to the store API call, it did, indeed, run the function, but it ran it locally within the script I was in at the time. It didn't actually put the function or its value into the global value. My script didn't actually retrieve it, but ran it directly, which gave the illusion of it having been retrieved from within the same script [sigh]. I also experimented with using the parentheses in the set and the get calls to see if there was a difference (there is) or if that would make this work (it didn't).
When it comes to global values, giving a global value the value of a string works perfectly and will continue to work as described above until you either change the value or delete it. For example, put this API call into any AutoKey script, run the script, and then delete the API call afterwards (it only needs to be run once):
Now you can use the
store.get_global_value("MyGlobalValue")
API call in any script from then on to get the global value and use it in whatever way you like. A couple of examples:When you no longer need that global value, you can put the
store.remove_global_value("MyGlobalValue")
API call into any AutoKey script, run the script to delete the global value, and then delete the API call from the script afterwards.I've been messing around with this stuff all morning and have come up with a short list of ways to use code/data from somewhere other than the current AutoKey script. I can come up with only three ways (but could probably come up with more if creative solutions were of interest):
1. Run another internal AutoKey script:
You would put some stand-alone code into an AutoKey script that you can run with the
engine.run_script(...)
API call from any other AutoKey script.For example,I created the MyInternalScript with a function in it that's executed from within that script. That script has these contents:
I then put this code into another AutoKey script and ran it:
It displayed the dialog that was run by the called script.
Note that I tried putting a function into the MyInternalScript script and then using parentheses on that engine API call to execute the function and that didn't work, so it seems that all the work must be done within the called script, which means these will not function the way imported modules do.
2. Run an imported external module from AutoKey's user-defined Modules directory:
You can store your Python files in AutoKey's Modules directory. There isn't a Modules directory by default, but you can choose one in this way:
In the AutoKey GTK front-end:
1. Open the Edit menu.
2. Choose Preferences from the menu.
3. Click the Script Engine tab.
4. Click the drop-down selector.
5. Choose a folder.
6. Click the Open button.
7. Click the OK button.
In the AutoKey Qt front-end:
1. Open the Settings menu.
2. Choose Configure AutoKey from the menu.
3. Click Script Engine in the left pane.
4. Click the Browse button.
5. Browse to the folder you'd like to use.
6. Click the OK button.
7. Click the Save button.
Then, once your Python file/s is/are in that directory, you can use an import statement in any AutoKey script or Python script to use its/their contents the way you would with any other import.
Example 1 - basic:
For this basic example, you could create the MyModule.py file inside of the folder you've chosen for your AutoKey modules and put these contents into it:
You can then create an AutoKey script with these contents to import your module and use its objects:
Example 2 - using the API injector:
For this example that uses the API injector, you could create the MyModule.py file inside of the folder you've chosen for your AutoKey modules and put these contents into it:
Then, you can create a script in AutoKey and put these contents into it to import that module, inject the AutoKey API into it, and create a few example objects:
That displays three dialogs, one after another. Two were initiated by the AutoKey script and one was initiated by the external Python script/module using your injector. Very cool.
3. Run an imported external module from any directory:
You can create a Python file anywhere on your system and use it as a module or script that you can import into AutoKey.
Example 1 - basic:
For this basic example, I made the example.py file on my Desktop, so the path to my file is shown below. It contains these contents:
Then, I created an AutoKey script with these contents to use that module:
Example 2 - using the API injector:
For this example that uses the API injector, I made the example.py file on my Desktop, so the path to my file is shown below. It contains your API injector function as a proof of concept. The contents of the example.py file are:
Last, but not least, I created a script in AutoKey and put these contents into it to import that external Python module/script from my Desktop, inject the AutoKey API into it, and create a few example objects:
That displays three dialogs, one after another. Two were initiated by the AutoKey script and one was initiated by the external Python script/module using your injector. Very cool.
Beta Was this translation helpful? Give feedback.
All reactions