python console in ~80 lines
Shift+Enter in the text editor executes the TEXT_OT_line_console operator defined in space_text.py The operator's class stores a namespace for each text block. Eventually this should have its own input rather then using the text editor. Tested with py3.1 and 2.6 TEXT_OT_insert was only using the first char from a string, added support for inserting strings.
This commit is contained in:
parent
184dca5396
commit
78703a9ef8
|
@ -226,6 +226,101 @@ class TEXT_MT_edit(bpy.types.Menu):
|
|||
|
||||
layout.itemM("TEXT_MT_edit_to3d")
|
||||
|
||||
|
||||
class TEXT_OT_line_console(bpy.types.Operator):
|
||||
'''
|
||||
Operator documentatuon text, will be used for the operator tooltip and python docs.
|
||||
'''
|
||||
__label__ = "Console Execute"
|
||||
|
||||
# Each text block gets its own console info.
|
||||
console = {}
|
||||
|
||||
# Both prompts must be the same length
|
||||
PROMPT = '>>> '
|
||||
PROMPT_MULTI = '... '
|
||||
|
||||
def execute(self, context):
|
||||
import sys
|
||||
|
||||
# clear all dead consoles, use text names as IDs
|
||||
for id in list(self.__class__.console.keys()):
|
||||
if id not in bpy.data.texts:
|
||||
del self.__class__.console[id]
|
||||
|
||||
# print("Selected: " + context.active_object.name)
|
||||
st = context.space_data
|
||||
text = st.text
|
||||
|
||||
if not text:
|
||||
return ('CANCELLED',)
|
||||
|
||||
line = st.text.current_line.line
|
||||
id = text.name
|
||||
|
||||
try:
|
||||
namespace, console, stdout = self.__class__.console[id]
|
||||
except:
|
||||
import code, io
|
||||
|
||||
namespace = locals().update({'bpy':bpy})
|
||||
console = code.InteractiveConsole(namespace)
|
||||
|
||||
if sys.version.startswith('2'): # Py2.x support
|
||||
stdout = io.BytesIO()
|
||||
else:
|
||||
stdout = io.StringIO()
|
||||
|
||||
|
||||
|
||||
self.__class__.console[id]= namespace, console, stdout
|
||||
del code, io
|
||||
|
||||
# redirect output
|
||||
sys.stdout = stdout
|
||||
sys.stderr = stdout
|
||||
|
||||
# run the console
|
||||
if not line.strip():
|
||||
line = '\n' # executes a multiline statement
|
||||
|
||||
if line.startswith(self.__class__.PROMPT_MULTI) or line.startswith(self.__class__.PROMPT):
|
||||
line = line[len(self.__class__.PROMPT):]
|
||||
was_prefix = True
|
||||
else:
|
||||
was_prefix = False
|
||||
|
||||
|
||||
is_multiline = console.push(line)
|
||||
|
||||
stdout.seek(0)
|
||||
output = stdout.read()
|
||||
|
||||
# cleanup
|
||||
sys.stdout = sys.__stdout__
|
||||
sys.stderr = sys.__stderr__
|
||||
sys.last_traceback = None
|
||||
|
||||
# So we can reuse, clear all data
|
||||
stdout.truncate(0)
|
||||
|
||||
if is_multiline:
|
||||
prefix = self.__class__.PROMPT_MULTI
|
||||
else:
|
||||
prefix = self.__class__.PROMPT
|
||||
|
||||
# Kindof odd, add the prefix if we didnt have one. makes it easier to re-read.
|
||||
if not was_prefix:
|
||||
bpy.ops.TEXT_OT_move(type='LINE_BEGIN')
|
||||
bpy.ops.TEXT_OT_insert(text = prefix)
|
||||
|
||||
bpy.ops.TEXT_OT_move(type='LINE_END')
|
||||
|
||||
# Insert the output into the editor
|
||||
bpy.ops.TEXT_OT_insert(text= '\n' + output + prefix)
|
||||
|
||||
return ('FINISHED',)
|
||||
|
||||
bpy.types.register(TEXT_HT_header)
|
||||
bpy.types.register(TEXT_PT_properties)
|
||||
bpy.types.register(TEXT_PT_find)
|
||||
|
@ -237,3 +332,5 @@ bpy.types.register(TEXT_MT_edit_select)
|
|||
bpy.types.register(TEXT_MT_edit_markers)
|
||||
bpy.types.register(TEXT_MT_edit_to3d)
|
||||
|
||||
bpy.ops.add(TEXT_OT_line_console)
|
||||
|
||||
|
|
|
@ -285,6 +285,10 @@ static void text_keymap(struct wmWindowManager *wm)
|
|||
WM_keymap_add_item(keymap, "TEXT_OT_to_3d_object", MKEY, KM_PRESS, KM_ALT, 0);
|
||||
|
||||
WM_keymap_add_item(keymap, "TEXT_OT_line_break", RETKEY, KM_PRESS, 0, 0);
|
||||
#ifndef DISABLE_PYTHON
|
||||
WM_keymap_add_item(keymap, "TEXT_OT_line_console", RETKEY, KM_PRESS, KM_SHIFT, 0); /* python operator - space_text.py */
|
||||
#endif
|
||||
|
||||
WM_keymap_add_item(keymap, "TEXT_OT_line_number", KM_TEXTINPUT, KM_ANY, KM_ANY, 0);
|
||||
WM_keymap_add_item(keymap, "TEXT_OT_insert", KM_TEXTINPUT, KM_ANY, KM_ANY, 0); // last!
|
||||
}
|
||||
|
|
|
@ -248,8 +248,6 @@ static int reload_exec(bContext *C, wmOperator *op)
|
|||
#ifndef DISABLE_PYTHON
|
||||
if(text->compiled)
|
||||
BPY_free_compiled_text(text);
|
||||
|
||||
text->compiled = NULL;
|
||||
#endif
|
||||
|
||||
text_update_edited(text);
|
||||
|
@ -2229,19 +2227,21 @@ static int insert_exec(bContext *C, wmOperator *op)
|
|||
SpaceText *st= CTX_wm_space_text(C);
|
||||
Text *text= CTX_data_edit_text(C);
|
||||
char *str;
|
||||
int done, ascii;
|
||||
int done = 0, i;
|
||||
|
||||
str= RNA_string_get_alloc(op->ptr, "text", NULL, 0);
|
||||
ascii= str[0];
|
||||
|
||||
if(st && st->overwrite) {
|
||||
for(i=0; str[i]; i++) {
|
||||
done |= txt_replace_char(text, str[i]);
|
||||
}
|
||||
} else {
|
||||
for(i=0; str[i]; i++) {
|
||||
done |= txt_add_char(text, str[i]);
|
||||
}
|
||||
}
|
||||
|
||||
MEM_freeN(str);
|
||||
|
||||
if(!ascii)
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
if(st && st->overwrite)
|
||||
done= txt_replace_char(text, ascii);
|
||||
else
|
||||
done= txt_add_char(text, ascii);
|
||||
|
||||
if(!done)
|
||||
return OPERATOR_CANCELLED;
|
||||
|
@ -2273,7 +2273,7 @@ static int insert_invoke(bContext *C, wmOperator *op, wmEvent *event)
|
|||
/* run the script while editing, evil but useful */
|
||||
if(ret==OPERATOR_FINISHED && CTX_wm_space_text(C)->live_edit)
|
||||
run_script_exec(C, op);
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue