How to use runMenuCommand() in python script?
-
How to call nested commands? For example, if I want to call View - Show Symbol - Show Indent Guide, I tried
notepad.runMenuCommand('View\Show Symbol','Show Indent Guide')
and
notepad.runMenuCommand('View','Show Indent Guide')
, but nothing happens.Also, I want to invoke one python script through another one. I tried
notepad.runPluginCommand('Python Script','Scripts\anotherScript')
. Didn’t work.
I also tried making anotherScript a menu item (through python script configuration) first, and thennotepad.runPluginCommand('Python Script','anotherScript')
. Also didn’t work.Thanks in advance.
-
for builtin menu function you do use menuCommand, for foreign menus like the famous TextFX you use runMenuCommand.
To answer your first question
notepad.menuCommand(MENUCOMMAND.VIEW_INDENT_GUIDE)
Concerning your second question I would say it depends what exactly is needed to be done like providing arguments …
What about using the python way and importing it?Eko
-
@古旮,
It turns out you don’t need to prefix with the “View” menu first:
notepad.runMenuCommand('Show Symbol','Show Indent Guide')
From the PythonScript console, if you want to run a script, the syntax is
notepad.runPluginCommand('Python Script', 'anotherScript')
– whether that script is only in the Scripts submenu, or whether it’s also been made a menu-item through the Configuration. At least for me, on NPP 7.5.8 with PythonScript 1.3.0.0.However, when I tried to run one script from another, I got a dialog box: “Another script is currently running. Running two scripts at the same time could produce unpredicable [sic] results, and is therefore disabled.” So they obviously don’t want you doing it that way.
I had partial success in using Python’s
import
syntax:console.show() console.write("Hello World") import SomeOtherScript # note that you drop the ".py" off of SomeOtherScript.py
If I ran this, it would write to the PythonScript console, then attempt to run SomeOtherScript. However, the attempt would only be successful if
SomeOtherScript.py
included thefrom Npp import *
: most of my scripts rely on that having been imported instartup.py
, but apparently when you add the level of indirection throughimport
, it loses that overhead. When I addedfrom Npp import *
, then it would work.As a second “however”: it would also only import/run the extra script once. If I tried again, it wouldn’t. My experiments and researched showed that it’s because the “module” (script) has already been “imported”, and since the PythonScript module has just one instance of Python, it stays “imported”. I have some ideas on how to get around that … but not enough time to get to that right now. I’ll come back to this later today.
-
@古旮,
Okay, I found a couple more minutes right away while waiting for something else to get ready:
If the primary script is below, and if
anotherScript.py
starts withfrom Npp import *
, (and ifprimaryScript.py
andanotherScript.py
are in the same directory), then I believe the following will work: it will re-run anotherScript every time primaryScript is run.console.show() console.write("\nHello World\n") # run the script called "anotherScript.py": if 'anotherScript' in globals(): console.write("anotherScript already exists\n") reload(anotherScript) else: console.write("anotherScript will be loaded\n") import anotherScript console.write("\nThe End\n")
(There may be some other caveats, but this combination worked in my experiments.)
In your final version, you don’t need all the console.write()s: those were just to show what was going on.
-
It turns out you don’t need to prefix with the “View” menu first:
nice one - wasn’t aware of this, so menuCommand is not needed anymore??
You are correct, python caches imported modules to avoid and prevent import loops.
One way to force to reimport the module would be to use the reload function but a
better way would be do define the function needed and call it explicitly likeSomeOtherScript.py contains
import time def someOtherFunction(): print('someOtherFunction:{}'.format(time.time()))
and the main script contains something like
import SomeOtherScript print('main script') SomeOtherScript.someOtherFunction()
Eko
-
I find that I can use the Python function
execfile()
to run one script from another…no need to worry about import/reload etc. -
yes, you can use exec or execfile to execute python code but have to be aware
that it differs how the code gets included.
Let’s assume you do have a script with name SomeOtherScript.py and within there is
one function SomeOtherFunction as well as one variable SomeOtherVariableIf you import SomeOtherScript then you’ve ensured that SomeOtherFunction and SomeOtherVariable
are only accessible via the module namespace.By using execfile or exec without using the optional global and local dicts you are importing
SomeOtherFunction and SomeOtherVariable into the namespace of the current script which might
override existing functions/variables.Eko
-
@Eko-palypse said:
By using execfile or exec without using the optional global and local dicts you are importing
SomeOtherFunction and SomeOtherVariable into the namespace of the current script which might
override existing functions/variables.Yes but Pythonscripts are usually small things with very well compartmentalized naming. At least mine are. I use the technique that someone else here showed, where funcs/vars have names that start with abbreviations of the script file names. Thus no collisions; but yes, no guarantees.
-
absolutely agreed - there is no wrong or right here as long as there is no requirement which
forces either the one or the other way to use.Eko
-
@Alan-Kilborn said:
I use the technique that someone else here showed, where funcs/vars have names that start with abbreviations of the script file names
BTW this is a good thing to do in general. Consider a different scenario, no longer the one where running one script from another. Say you run script 1. Ok, fine, script one is finished and done. Now you want to use script 2. Well, script 1’s variables and functions still exist, so you could potentially be accessing old data from script 2. Not with the artificial namespace forcing (the names starting with abbrevs)–doesn’t happen.
-
I assume as long as you are the only one who maintains and executes the scripts it is ok
but as soon as further people are involved it might get a little bit tricky and, personally,
I find it hard to read and is there really a benefit of, let’s say XYZ_myfunction contrary to XYZ.myfunction?
Guess, is a matter of taste.Eko