Featured post

new redirect for blender.org bpy docs.

http://www.blender.org/api/blender_python_api_current/ As of 10/11 november 2015 we can now link to the current api docs and not be worr...

August 19, 2012

Blender Interactive Python Console

The console does a lot of things right, like auto-complete using ctrl+space and storing a history of the most recent unique line entries. Internally the history behaves like a set, if a line exists in the history it does not get added.

There are some things that the console doesn't do
  • allow kb shift + cursor to set a selection
  • allow key combo at end of line to copy current line
  • allow key combo to copy last n entries in history
These are all things I frequently want to be able to do. The C files for console are reasonably understandable, i hope when the weather cools down to write a patch and lobby for it.

In the meantime i poked around in bpy to see what is already exposed to python, just in case a c-patch is beyond my brainpower or is rejected.
[lines.body for lines in bpy.context.area.spaces.active.history][:4]


naive method 1

That displays the last 4 unique history entries in the console. But the problem is that active state might not be available if running as a operator script. We'll see. Too warm to really think here atm.

Not sure if there are neater ways to do this, but this will keep me going for a while. Will have to add a few options like copy 2 / 4 / 6 / 12 lines to clipboard. Right now it is hardcoded to 4. This script gets added as Console View -> Console (button) -> Copy History
bl_info = {
"name": "Console History",
"author": "Dealga McArdle",
"version": (0, 1, 0),
"blender": (2, 6, 4),
"location": "Console - Copy History",
"description": "Adds Copy History options to Console button.",
"wiki_url": "",
"tracker_url": "",
"category": "Console"}
import bpy
def copy_history(ctx):
history = ""
try:
history = [lines.body for lines in ctx.area.spaces.active.history][:4]
history = '\n'.join(history)
except:
print('no history found')
return history
class AddToClipboard(bpy.types.Operator):
bl_label = ""
bl_idname = "console.copy_history_n"
def execute(self, context):
content = copy_history(context)
context.window_manager.clipboard = content
return {'FINISHED'}
def history_menu(self, context):
layout = self.layout
layout.operator("console.copy_history_n", text='Copy History')
def register():
bpy.utils.register_class(AddToClipboard)
bpy.types.CONSOLE_MT_console.prepend(history_menu)
def unregister():
bpy.utils.unregister_class(AddToClipboard)
bpy.types.CONSOLE_MT_console.remove(history_menu)
if __name__ == "__main__":
register()


naive method 2, i like this

Last night Campbell Barton added an operator for console view to copy the current input stack into a string, where each new line is indicated by a newline character. This is an early implementation of using that function to store the stack inside clipboard for pasting into the text editor view. Things will probably change, this script may be invalidated within a short space of time but it's really handy, and i hope more people will use it.
bl_info = {
"name": "Console History",
"author": "Dealga McArdle",
"version": (0, 1, 0),
"blender": (2, 6, 4),
"location": "Console - Copy History",
"description": "Adds Copy History options to Console button.",
"wiki_url": "",
"tracker_url": "",
"category": "Console"}
import bpy
def sanitize_console_dump(tm):
def of_interest(line):
return not starts_with_token(line) and not incomplete(line)
def starts_with_token(line):
tokens = "#~","#!"
for token in tokens:
if line.startswith(token):
return True
return False
def incomplete(line):
return line.endswith('.')
tm = tm.split('\n')
cleaner = [line for line in tm if of_interest(line)]
return'\n'.join(cleaner)
class AddToClipboard(bpy.types.Operator):
bl_label = ""
bl_idname = "console.copy_history_n"
def execute(self, context):
bpy.ops.console.copy_as_script()
tm = context.window_manager.clipboard
context.window_manager.clipboard = sanitize_console_dump(tm)
return {'FINISHED'}
def history_menu(self, context):
layout = self.layout
layout.operator("console.copy_history_n", text='Copy History')
def register():
bpy.utils.register_class(AddToClipboard)
bpy.types.CONSOLE_MT_console.prepend(history_menu)
def unregister():
bpy.utils.unregister_class(AddToClipboard)
bpy.types.CONSOLE_MT_console.remove(history_menu)
if __name__ == "__main__":
register()