Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'release/ui/space_text.py')
-rw-r--r--release/ui/space_text.py514
1 files changed, 490 insertions, 24 deletions
diff --git a/release/ui/space_text.py b/release/ui/space_text.py
index 5c6c5c0d21b..c6ce1cb71d6 100644
--- a/release/ui/space_text.py
+++ b/release/ui/space_text.py
@@ -1,14 +1,6 @@
import bpy
-# temporary
-ICON_LINENUMBERS_OFF = 588
-ICON_WORDWRAP_OFF = 584
-ICON_SYNTAX_OFF = 586
-ICON_TEXT = 120
-ICON_HELP = 1
-ICON_SCRIPTPLUGINS = 1
-
class TEXT_HT_header(bpy.types.Header):
__space_type__ = "TEXT_EDITOR"
__idname__ = "TEXT_HT_header"
@@ -18,27 +10,26 @@ class TEXT_HT_header(bpy.types.Header):
text = st.text
layout = self.layout
- layout.template_header(context)
+ layout.template_header()
if context.area.show_menus:
- row = layout.row(align=True)
- row.itemM(context, "TEXT_MT_text")
+ row = layout.row()
+ row.itemM("TEXT_MT_text")
if text:
- row.itemM(context, "TEXT_MT_edit")
- row.itemM(context, "TEXT_MT_format")
+ row.itemM("TEXT_MT_edit")
+ row.itemM("TEXT_MT_format")
if text and text.modified:
row = layout.row()
# row.color(redalert)
- row.itemO("TEXT_OT_resolve_conflict", text="", icon=ICON_HELP)
+ row.itemO("TEXT_OT_resolve_conflict", text="", icon='ICON_HELP')
row = layout.row(align=True)
- row.itemR(st, "line_numbers", text="", icon=ICON_LINENUMBERS_OFF)
- row.itemR(st, "word_wrap", text="", icon=ICON_WORDWRAP_OFF)
- row.itemR(st, "syntax_highlight", text="", icon=ICON_SYNTAX_OFF)
- # row.itemR(st, "do_python_plugins", text="", icon=ICON_SCRIPTPLUGINS)
+ row.itemR(st, "line_numbers", text="")
+ row.itemR(st, "word_wrap", text="")
+ row.itemR(st, "syntax_highlight", text="")
- layout.template_ID(context, st, "text", new="TEXT_OT_new", open="TEXT_OT_open", unlink="TEXT_OT_unlink")
+ layout.template_ID(st, "text", new="TEXT_OT_new", unlink="TEXT_OT_unlink")
if text:
row = layout.row()
@@ -63,9 +54,10 @@ class TEXT_PT_properties(bpy.types.Panel):
layout = self.layout
flow = layout.column_flow()
- flow.itemR(st, "line_numbers", icon=ICON_LINENUMBERS_OFF)
- flow.itemR(st, "word_wrap", icon=ICON_WORDWRAP_OFF)
- flow.itemR(st, "syntax_highlight", icon=ICON_SYNTAX_OFF)
+ flow.itemR(st, "line_numbers")
+ flow.itemR(st, "word_wrap")
+ flow.itemR(st, "syntax_highlight")
+ flow.itemR(st, "live_edit")
flow = layout.column_flow()
flow.itemR(st, "font_size")
@@ -84,14 +76,14 @@ class TEXT_PT_find(bpy.types.Panel):
col = layout.column(align=True)
row = col.row()
row.itemR(st, "find_text", text="")
- row.itemO("TEXT_OT_find_set_selected", text="", icon=ICON_TEXT)
+ row.itemO("TEXT_OT_find_set_selected", text="", icon='ICON_TEXT')
col.itemO("TEXT_OT_find")
# replace
col = layout.column(align=True)
row = col.row()
row.itemR(st, "replace_text", text="")
- row.itemO("TEXT_OT_replace_set_selected", text="", icon=ICON_TEXT)
+ row.itemO("TEXT_OT_replace_set_selected", text="", icon='ICON_TEXT')
col.itemO("TEXT_OT_replace")
# mark
@@ -139,8 +131,482 @@ class TEXT_MT_text(bpy.types.Menu):
# XXX uiDefIconTextBlockBut(block, text_plugin_scriptsmenu, NULL, ICON_RIGHTARROW_THIN, "Text Plugins", 0, yco-=20, 120, 19, "");
#endif
+class TEXT_MT_edit_view(bpy.types.Menu):
+ __space_type__ = "TEXT_EDITOR"
+ __label__ = "View"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.item_enumO("TEXT_OT_move", "type", "FILE_TOP", text="Top of File")
+ layout.item_enumO("TEXT_OT_move", "type", "FILE_BOTTOM", text="Bottom of File")
+
+class TEXT_MT_edit_select(bpy.types.Menu):
+ __space_type__ = "TEXT_EDITOR"
+ __label__ = "Select"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.itemO("TEXT_OT_select_all")
+ layout.itemO("TEXT_OT_select_line")
+
+class TEXT_MT_edit_markers(bpy.types.Menu):
+ __space_type__ = "TEXT_EDITOR"
+ __label__ = "Markers"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.itemO("TEXT_OT_markers_clear")
+ layout.itemO("TEXT_OT_next_marker")
+ layout.itemO("TEXT_OT_previous_marker")
+
+class TEXT_MT_format(bpy.types.Menu):
+ __space_type__ = "TEXT_EDITOR"
+ __label__ = "Format"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.itemO("TEXT_OT_indent")
+ layout.itemO("TEXT_OT_unindent")
+
+ layout.itemS()
+
+ layout.itemO("TEXT_OT_comment")
+ layout.itemO("TEXT_OT_uncomment")
+
+ layout.itemS()
+
+ layout.item_menu_enumO("TEXT_OT_convert_whitespace", "type")
+
+class TEXT_MT_edit_to3d(bpy.types.Menu):
+ __space_type__ = "TEXT_EDITOR"
+ __label__ = "Text To 3D Object"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.item_booleanO("TEXT_OT_to_3d_object", "split_lines", False, text="One Object");
+ layout.item_booleanO("TEXT_OT_to_3d_object", "split_lines", True, text="One Object Per Line");
+
+class TEXT_MT_edit(bpy.types.Menu):
+ __space_type__ = "TEXT_EDITOR"
+ __label__ = "Edit"
+
+ def poll(self, context):
+ st = context.space_data
+ return st.text != None
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.itemO("ED_OT_undo")
+ layout.itemO("ED_OT_redo")
+
+ layout.itemS()
+
+ layout.itemO("TEXT_OT_cut")
+ layout.itemO("TEXT_OT_copy")
+ layout.itemO("TEXT_OT_paste")
+
+ layout.itemS()
+
+ layout.itemM("TEXT_MT_edit_view")
+ layout.itemM("TEXT_MT_edit_select")
+ layout.itemM("TEXT_MT_edit_markers")
+
+ layout.itemS()
+
+ layout.itemO("TEXT_OT_jump")
+ layout.itemO("TEXT_OT_properties")
+
+ layout.itemS()
+
+ layout.itemM("TEXT_MT_edit_to3d")
+
+
+def get_console(text):
+ '''
+ helper function for console operators
+ currently each text datablock gets its own console - code.InteractiveConsole()
+ ...which is stored in this function.
+ '''
+ import sys, code, io
+
+ try: consoles = get_console.consoles
+ except:consoles = get_console.consoles = {}
+
+ # clear all dead consoles, use text names as IDs
+ for id in list(consoles.keys()):
+ if id not in bpy.data.texts:
+ del consoles[id]
+
+ if not text:
+ return None, None, None
+
+ id = text.name
+
+ try:
+ namespace, console, stdout = consoles[id]
+ except:
+ namespace = locals()
+ namespace['bpy'] = bpy
+
+ console = code.InteractiveConsole(namespace)
+
+ if sys.version.startswith('2'): stdout = io.BytesIO() # Py2x support
+ else: stdout = io.StringIO()
+
+ consoles[id]= namespace, console, stdout
+
+ return namespace, console, stdout
+
+class TEXT_OT_console_exec(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
+
+ st = context.space_data
+ text = st.text
+
+ if not text:
+ return ('CANCELLED',)
+
+ namespace, console, stdout = get_console(text)
+
+ line = text.current_line.line
+
+ # 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.PROMPT_MULTI) or line.startswith(self.PROMPT):
+ line = line[len(self.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.PROMPT_MULTI
+ else:
+ prefix = self.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',)
+
+
+def autocomp(bcon):
+ '''
+ This function has been taken from a BGE console autocomp I wrote a while ago
+ the dictionaty bcon is not needed but it means I can copy and paste from the old func
+ which works ok for now.
+
+ could be moved into its own module.
+ '''
+
+
+ def is_delimiter(ch):
+ '''
+ For skipping words
+ '''
+ if ch == '_':
+ return False
+ if ch.isalnum():
+ return False
+
+ return True
+
+ def is_delimiter_autocomp(ch):
+ '''
+ When autocompleteing will earch back and
+ '''
+ if ch in '._[] "\'':
+ return False
+ if ch.isalnum():
+ return False
+
+ return True
+
+
+ def do_autocomp(autocomp_prefix, autocomp_members):
+ '''
+ return text to insert and a list of options
+ '''
+ autocomp_members = [v for v in autocomp_members if v.startswith(autocomp_prefix)]
+
+ print("AUTO: '%s'" % autocomp_prefix)
+ print("MEMBERS: '%s'" % str(autocomp_members))
+
+ if not autocomp_prefix:
+ return '', autocomp_members
+ elif len(autocomp_members) > 1:
+ # find a common string between all members after the prefix
+ # 'ge' [getA, getB, getC] --> 'get'
+
+ # get the shortest member
+ min_len = min([len(v) for v in autocomp_members])
+
+ autocomp_prefix_ret = ''
+
+ for i in range(len(autocomp_prefix), min_len):
+ char_soup = set()
+ for v in autocomp_members:
+ char_soup.add(v[i])
+
+ if len(char_soup) > 1:
+ break
+ else:
+ autocomp_prefix_ret += char_soup.pop()
+
+ print(autocomp_prefix_ret)
+ return autocomp_prefix_ret, autocomp_members
+ elif len(autocomp_members) == 1:
+ return autocomp_members[0][len(autocomp_prefix):], []
+ else:
+ return '', []
+
+
+ def BCon_PrevChar(bcon):
+ cursor = bcon['cursor']-1
+ if cursor<0:
+ return None
+
+ try:
+ return bcon['edit_text'][cursor]
+ except:
+ return None
+
+
+ def BCon_NextChar(bcon):
+ try:
+ return bcon['edit_text'][bcon['cursor']]
+ except:
+ return None
+
+ def BCon_cursorLeft(bcon):
+ bcon['cursor'] -= 1
+ if bcon['cursor'] < 0:
+ bcon['cursor'] = 0
+
+ def BCon_cursorRight(bcon):
+ bcon['cursor'] += 1
+ if bcon['cursor'] > len(bcon['edit_text']):
+ bcon['cursor'] = len(bcon['edit_text'])
+
+ def BCon_AddScrollback(bcon, text):
+
+ bcon['scrollback'] = bcon['scrollback'] + text
+
+
+ def BCon_cursorInsertChar(bcon, ch):
+ if bcon['cursor']==0:
+ bcon['edit_text'] = ch + bcon['edit_text']
+ elif bcon['cursor']==len(bcon['edit_text']):
+ bcon['edit_text'] = bcon['edit_text'] + ch
+ else:
+ bcon['edit_text'] = bcon['edit_text'][:bcon['cursor']] + ch + bcon['edit_text'][bcon['cursor']:]
+
+ bcon['cursor']
+ if bcon['cursor'] > len(bcon['edit_text']):
+ bcon['cursor'] = len(bcon['edit_text'])
+ BCon_cursorRight(bcon)
+
+
+ TEMP_NAME = '___tempname___'
+
+ cursor_orig = bcon['cursor']
+
+ ch = BCon_PrevChar(bcon)
+ while ch != None and (not is_delimiter(ch)):
+ ch = BCon_PrevChar(bcon)
+ BCon_cursorLeft(bcon)
+
+ if ch != None:
+ BCon_cursorRight(bcon)
+
+ #print (cursor_orig, bcon['cursor'])
+
+ cursor_base = bcon['cursor']
+
+ autocomp_prefix = bcon['edit_text'][cursor_base:cursor_orig]
+
+ print("PREFIX:'%s'" % autocomp_prefix)
+
+ # Get the previous word
+ if BCon_PrevChar(bcon)=='.':
+ BCon_cursorLeft(bcon)
+ ch = BCon_PrevChar(bcon)
+ while ch != None and is_delimiter_autocomp(ch)==False:
+ ch = BCon_PrevChar(bcon)
+ BCon_cursorLeft(bcon)
+
+ cursor_new = bcon['cursor']
+
+ if ch != None:
+ cursor_new+=1
+
+ pytxt = bcon['edit_text'][cursor_new:cursor_base-1].strip()
+ print("AUTOCOMP EVAL: '%s'" % pytxt)
+ #try:
+ if pytxt:
+ bcon['console'].runsource(TEMP_NAME + '=' + pytxt, '<input>', 'single')
+ # print val
+ else: ##except:
+ val = None
+
+ try:
+ val = bcon['namespace'][TEMP_NAME]
+ del bcon['namespace'][TEMP_NAME]
+ except:
+ val = None
+
+ if val:
+ autocomp_members = dir(val)
+
+ autocomp_prefix_ret, autocomp_members = do_autocomp(autocomp_prefix, autocomp_members)
+
+ bcon['cursor'] = cursor_orig
+ for v in autocomp_prefix_ret:
+ BCon_cursorInsertChar(bcon, v)
+ cursor_orig = bcon['cursor']
+
+ if autocomp_members:
+ BCon_AddScrollback(bcon, ', '.join(autocomp_members))
+
+ del val
+
+ else:
+ # Autocomp global namespace
+ autocomp_members = bcon['namespace'].keys()
+
+ if autocomp_prefix:
+ autocomp_members = [v for v in autocomp_members if v.startswith(autocomp_prefix)]
+
+ autocomp_prefix_ret, autocomp_members = do_autocomp(autocomp_prefix, autocomp_members)
+
+ bcon['cursor'] = cursor_orig
+ for v in autocomp_prefix_ret:
+ BCon_cursorInsertChar(bcon, v)
+ cursor_orig = bcon['cursor']
+
+ if autocomp_members:
+ BCon_AddScrollback(bcon, ', '.join(autocomp_members))
+
+ bcon['cursor'] = cursor_orig
+
+
+class TEXT_OT_console_autocomplete(bpy.types.Operator):
+ '''
+ Operator documentatuon text, will be used for the operator tooltip and python docs.
+ '''
+ __label__ = "Console Autocomplete"
+
+ def execute(self, context):
+
+ st = context.space_data
+ text = st.text
+
+ namespace, console, stdout = get_console(text)
+
+ line = text.current_line.line
+
+ if not console:
+ return ('CANCELLED',)
+
+
+ # fake cursor, use for autocomp func.
+ bcon = {}
+ bcon['cursor'] = text.current_character
+ bcon['console'] = console
+ bcon['edit_text'] = line
+ bcon['namespace'] = namespace
+ bcon['scrollback'] = '' # nor from the BGE console
+
+
+ # This function isnt aware of the text editor or being an operator
+ # just does the autocomp then copy its results back
+ autocomp(bcon)
+
+ # Now we need to copy back the line from blender back into the text editor.
+ # This will change when we dont use the text editor anymore
+
+ # clear the line
+ bpy.ops.TEXT_OT_move(type='LINE_END')
+ bpy.ops.TEXT_OT_move_select(type = 'LINE_BEGIN')
+ bpy.ops.TEXT_OT_delete(type = 'PREVIOUS_CHARACTER')
+
+ if bcon['scrollback']:
+ bpy.ops.TEXT_OT_move_select(type = 'LINE_BEGIN')
+ bpy.ops.TEXT_OT_insert(text = bcon['scrollback'].strip() + '\n')
+ bpy.ops.TEXT_OT_move_select(type='LINE_BEGIN')
+
+ bpy.ops.TEXT_OT_insert(text = bcon['edit_text'])
+
+ # Read only
+ if 0:
+ text.current_character = bcon['cursor']
+ else:
+ bpy.ops.TEXT_OT_move(type = 'LINE_BEGIN')
+
+ for i in range(bcon['cursor']):
+ bpy.ops.TEXT_OT_move(type='NEXT_CHARACTER')
+
+
+ return ('FINISHED',)
+
+
+
bpy.types.register(TEXT_HT_header)
bpy.types.register(TEXT_PT_properties)
bpy.types.register(TEXT_PT_find)
bpy.types.register(TEXT_MT_text)
+bpy.types.register(TEXT_MT_format)
+bpy.types.register(TEXT_MT_edit)
+bpy.types.register(TEXT_MT_edit_view)
+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_console_exec)
+bpy.ops.add(TEXT_OT_console_autocomplete)