Improving Python Editing In Blender
This project enables users to develop Python scripts with greater ease by including a number of new features to the text editor and improving upon the existing functionality.
For information on the changes made to Blender and the way it fits in with current development see the Integration Document
Or for information on using the new system, see the User Manual
The key aspect of this project has been the text plug-in system. This system allows Python scripts to be created that interact directly with the user, and the text on which the user is working. For information on how to write a text plug-in, see the section on Writing a Text Plug-in below.
These videos demonstrate the features introduced by this project. For a more complete list see below.
The following list outlines the features brought to Blender by this project:
- Code/member suggestion and completion [done]
- Scrollable documentation access panel [done]
- Whole word operations [done]
- Insert/overwrite support [done]
- Header lists active file (or "Internal") and modified status (*) [done]
- External modifications are checked for and reported with options [done]
- Word wrap
It will also fix the following issues:
- Library linked Text can be edited [fixed]
- Backspace at top of file inserted blank line on undo [fixed]
Additional features that are being considered or would be good extensions to the project:
- Better search: all text search, find and replace [done]
- Interaction between Blender clipboard and text clipboard [done]
- Additional line and positional markers, which would then allow... [done]
- Code templates and snippets1 [done]
- Mindrones' Wishlist2
- Better support for other languages
- Script output redirect
Other issues found:
- Redo fails when re-deleting backward-selected text [fixed]
- Pressing up at the top or down at the bottom breaks undo [fixed]
When editing Python scripts it is often desirable to have a list of functions and variables defined in the current script. It is also useful to have the ability to list the various functions and fields of a given object.
The code completion section of this project brings both of these to the user and provides a platform for further completion methods (such as snippets or tags) to be implemented.
The actual completion comes from the ability to type only a few (if any) of the characters of the method or field before invoking the suggestions list. For template-like completion the system makes it very easy to add. A script can be written with the shortcut ⇆ Tab that strips out at the word preceding the cursor, looks it up in some template dict and
insert()s the template into the code positioning the cursor in the right place with
setCursorPos(). If time allows I will produce such a script and a tutorial on its creation at the end of the project.
To invoke completion simply enable syntax highlighting and press CtrlSpace. This will list all modules, functions and variables available or defined in the script. Additional scripts work to complete import statements:
...and member fields:
import Blender Blender.|
| marks the cursor position. The last period or space typed will invoke these context sensitive scripts. CtrlSpace may also be used here.
On similar lines to code completion a quick view of the documentation for an object is displayable. This aims to reduce the need for using external documentation by bringing it into the interface.
Currently, whilst inside a function:
print somefunc(somevar, | )
Pressing CtrlI will list the
somefunc function's documentation text. If the cursor is not inside a function's parentheses it will attempt to display the documentation string for the name preceding it:
will display the text "The main Blender module"
Editors typically have a set of operations that users have come to expect yet Blender lacked a number of these.
Text overwrite support. Before this project you could only insert text and the Ins key had little use. Now the Ins toggles insert/overwrite modes and changes the cursor to reflect this.
Whole word operations (implemented in some editors as Ctrl←, CtrlDel, Ctrl← Backspace, etc.) have been added. Unfortunately, CtrlLeft/right are reserved for screen switching so Alt equivalents have been substituted where appropriate:
|AltLeft/right||Moves the cursor left/right by one word or group of symbols.|
|Deletes the word to the left/right of the cursor.|
Word wrap is another missing feature and is very useful for writing text that is not part of a script. Word wrap will have a toggle button associated with it but is not yet implemented.
Writing a Text Plug-in
To write your own text plug-in take a look at the template under File → Script Templates → Text Plugin. The BPy module, together with the new Text object functions allow a variety of useful tools to be created.
The BPyTextPlugin Module
The central component of many text plug-ins is the python module BPyTextPlugin. This module provides tools for parsing and obtaining useful information about a given Text object. Here is a short description of how it works and the interface for using it in your own scripts.
The method of most use is
get_cached_descriptor(txtobj) which returns an instance of
ScriptDesc when passed a Blender Text object. If the text has not been previously parsed or for whatever reason, it is decided to reparse the text,
parse_text(txtobj) is called. This method can also be used to force a re-parse.
import BPyTextPlugin, bpy txt = bpy.data.texts.active desc = BPyTextPlugin.get_cached_descriptor(txt) BPyTextPlugin.print_cache_for(txt)
The best way to understand the
ScriptDesc instance is to look at the BPyTextPlugin module itself. Its
defs fields provide lists of
FuncDesc instances which further describe the text. The
classes field provides access to classes with their own
Each descriptor has a
lineno field for accessing the number of the line on which it is first defined, and a
name field for obtaining the symbol name.
Changes To The Text Object
Once a script has obtained the information it requires it can feed this information to the user by two new methods:
| ||Displays word-wrapped documentation in an easily dismissable panel|
| ||Displays suggestions list limited to show items with the specified prefix.|
It may also create markers (see below) by calling
| || Marks the current selection with the specified group, colour and behaviour flags. Use |
* Markers with this flag must be of the same length and mark equal text
Example using the suggestion and documentation tools:
import bpy from BPyTextPlugin import suggest_cmp txt = bpy.data.texts.active sugs = [('suggest_me', 'v'), # v for variable ('suggest_this', 'f') # f for function ] sugs.sort(cmp=suggest_cmp) txt.showDocs('Some kind of documentation string, automatically word-wrapped') txt.suggest(sugs, 'suggest_')
Note: It is no longer necessary to sort the suggestions list but it is still recommended. Use
sort(cmp=BPyTextPlugin.suggest_cmp) for sorting.
Other additions to the Blender Text object (
| ||Returns the cursor position (row, col). Note that line numbers are usually 1-based in python, whereas row is 0-based here.|
| ||Sets the position of the cursor in the Text object (or as close as possible). Selections are cleared.|
| ||Returns the selection cursor position (row, col). Note that line numbers are usually 1-based in python, whereas row is 0-based here.|
| || Sets the position of the selection cursor in the Text object (or as close as possible). Selections are extended to this point, use |
| || Inserts |
| ||Reads a line from the Text object in accordance with other readline methods.|
| ||Resets the IO pointer to the beginning (for reading).|
With these tools, many plug-ins can be produced, from class browsers to template completion scripts.
Markers provide a neat way to jump around text and edit repeated portions in one go. They allow templates to be constructed where certain bits must be filled in and expand on the find and replace options.
To see markers in action see the video above or take a look at my template script:
The template syntax used in this script is based on GEdit's snippets1
During the first week, I shall learn as much as possible about the current implementation and outline the possibilities. Some of the simpler features and fixes may be carried out here. The remainder of the time will be split as follows:
Stage 1: Implement the back end functions for code completion, documentation and other features. Output is generally directed at the console at this stage.
Stage 2: Create UI elements for displaying the requested information. Output is fed to these on request.
Stage 3: Implement advanced UI features and interaction (scrollable documentation panel, member selection). Also allow the user to enable/disable these features, possibly adding options to User Preferences although this should be limited.
Stage 4: Seemless integration: enabling context sensitive pop-up without specific user request (eg. when the user types a . after a valid variable or pressing tab for snippet completion).
Stage 5: Final testing, debugging and tidy-up. Optimizing the code for best possible performance.
On completion of the project, changes merged with the trunk will be documented for the general public. The wiki page at Manual/Python_Scripting#The_Text_Editor will be updated.
I am a 21 year old Mathematics student who has just finished his final year. I am about to embark on a Masters degree in Computer Animation. I have been developing software since an early age and have experience in many languages including Pascal, Java, C, C++ and Python. I have worked on the development of an open source renderfarm for Blender3 and make use of many open source tools in my daily life.
I love the idea of making something useful for all and hope that this project will do just that.