If you need to run any script in any context area. You might need to use a new operator to make the shortcut available due to the lack of operator. The one that scripting editor used will poll the context and only work in scripting area.



Code
import bpy
def create_summary(text: str, length: int = 300) -> str:
return f"Code Preview:\n\n{text[:length]}"
def list_textname_callback(scene, context):
return [
(text.name, text.name, create_summary(text.as_string()))
for text in bpy.data.texts
]
class TEXT_OT_run_specified_script(bpy.types.Operator):
bl_idname = "text.run_specified_script"
bl_label = "Run specified text script"
bl_options = {'REGISTER'}
# fmt: off
script_name: bpy.props.EnumProperty(
name="Run script from:",
description="Run this specified script.",
items=list_textname_callback
)
# fmt: on
def invoke(self, context, event):
# Prompt to ask
return context.window_manager.invoke_props_dialog(self)
def execute(self, context):
script = bpy.data.texts.get(self.script_name, None)
if script != None:
exec(
compile(
script.as_string(),
filename=f"{script.name}",
mode='exec',
),
)
else:
self.report({'WARNING'}, "No script found.")
return {'FINISHED'}
def _menu_func(self, context):
self.layout.operator(
TEXT_OT_run_specified_script.bl_idname,
text=TEXT_OT_run_specified_script.bl_label,
)
fmt: off
classes = [
TEXT_OT_run_specified_script,
]
fmt: on
def register():
for c in classes:
bpy.utils.register_class(c)
bpy.types.TOPBAR_MT_window.append(_menu_func)
def unregister():
for c in reversed(classes):
bpy.utils.unregister_class(c)
bpy.types.TOPBAR_MT_window.remove(_menu_func)
if name == "main":
try:
unregister()
except:
pass
register()
Details:
The arbitrary script you want to run is loaded and executed by another operator. Operator is a class inherited from bpy.types.Operator and been registered to Blender system.
Most of the button in Blender is an UI to invoke operator. The short-cut keymap need an bl_idname to hook on. But the original text.run_script (The small play button in your text editor) cannot select arbitrary script and run, also it cannot be run outside the text editor due to the poll method block unnecessary context call.
That's why you need another operator doing the same thing but accept changing script and run it in every where.
TL;DR:
This addon is only a play button that can accessed in anywhere and run any text block (doesn't even need to be a python script). This addon provide a bl_idname for short cut to assign to, make it possible to bind to shortcut.
If anyone here and want this to be a valid addon, go for the github page and download it. It will be put under testing addon.
