Skip to content

Instantly share code, notes, and snippets.

@tin2tin
Last active September 19, 2019 14:36
Show Gist options
  • Save tin2tin/7c5859e60f2d6ce1274c68822ef9d57c to your computer and use it in GitHub Desktop.
Save tin2tin/7c5859e60f2d6ce1274c68822ef9d57c to your computer and use it in GitHub Desktop.
Intellisense for Blender Text Editor
# ***** BEGIN GPL LICENSE BLOCK *****
#
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ***** END GPL LICENCE BLOCK *****
bl_info = {
"name": "Intellisense for Text Editor",
"author": "Mackraken",
"version": (0, 3),
"blender": (2, 80, 0),
"api": 41851,
"location": "Ctrl + Space at Text Editor",
"description": "Adds intellense to the Text Editor",
"warning": "Only works with 2.57 intellisense",
"wiki_url": "",
"tracker_url": "",
"category": "Text Editor"}
import bpy
def enabled(self, context):
enable = context.scene.use_intellisense
if enable:
conf = context.window_manager.keyconfigs.active
map = conf.keymaps['Text']
found1 = False
found2 = False
for key in map.keymap_items:
if key.name == "Line Break" and key.type=="RET":
if key.idname != "text.test_line":
key.idname = "text.test_line"
found1 = True
if key.name == "Text Editor Intellisense":
found2 = True
if not found2:
key = map.keymap_items.new(idname = "text.intellisense", type = "i", ctrl=True, value = "PRESS")
bpy.types.Scene.use_intellisense = bpy.props.BoolProperty(name= "Enabled", default = False, update = enabled)
def complete(context):
from console import intellisense
from console_python import get_console
sc = context.space_data
text = sc.text
region = context.region
for area in context.screen.areas:
if area.type=="CONSOLE":
region = area.regions[1]
break
console = get_console(hash(region))[0]
line = text.current_line.body
cursor = text.current_character
result = intellisense.expand(line, cursor, console.locals, bpy.app.debug)
return result
class TEXT_MT_intellimenu(bpy.types.Menu):
bl_label = ""
bl_idname = "intelliMenu"
text = ""
def draw(self, context):
layout = self.layout
#Very ugly see how can i fix this
options = complete(context)
options = options[2].split(" ")
for op in options:
layout.operator("text.intellioptions", text=op).text=op
#This operator executes when hits Ctrl+Space at the text editor
class Intellisense(bpy.types.Operator):
#'''Tooltip'''
bl_idname = "text.intellisense"
bl_label = "Text Editor Intellisense"
text = ""
# @classmethod
# def poll(cls, context):
# return context.active_object is not None
def execute(self, context):
sc = context.space_data
text = sc.text
if text.current_character>0:
result = complete(context)
#print(result)
if result[2]=="":
text.current_line.body = result[0]
bpy.ops.text.move(type='LINE_END')
else:
bpy.ops.wm.call_menu(name=TEXT_MT_intellimenu.bl_idname)
return {'FINISHED'}
#this operator completes the line with the options you choose from the menu
class Intellioptions(bpy.types.Operator):
#'''Tooltip'''
bl_idname = "text.intellioptions"
bl_label = "Intellisense options"
text: bpy.props.StringProperty()
@classmethod
def poll(cls, context):
return context.active_object is not None
def execute(self, context):
sc = context.space_data
text = sc.text
comp = self.text
line = text.current_line.body
lline = len(line)
lcomp = len(comp)
#intersect text
intersect = [-1,-1]
for i in range(lcomp):
val1 = comp[0:i+1]
for j in range(lline):
val2 = line[lline-j-1::]
#print(" ",j, val2)
if val1==val2:
intersect = [i, j]
break
if intersect[0]>-1:
newline = line[0:lline-intersect[1]-1]+comp
else:
newline = line + comp
#print(newline)
text.current_line.body = newline
bpy.ops.text.move(type='LINE_END')
return {'FINISHED'}
def send_console(context, all=0):
sc = context.space_data
text = sc.text
console = None
for area in bpy.context.screen.areas:
if area.type=="CONSOLE":
from console_python import get_console
console = get_console(hash(area.regions[1]))[0]
if console==None:
return {'FINISHED'}
lines = []
if all:
lines = text.lines
else:
lines = [text.current_line]
space = " "
tab = " "
for l in lines:
line = l.body
if "=" in line:
var = line.split("=")
if not "." in var[0] and var[1]!="":
print("push "+line)
while line[0]==space or line[0]==tab:
line = line[1::]
try:
console.push(line)
except:
pass
else:
print("not processed")
elif "import" in line:
console.push(line)
else:
print("not processed")
class TestLine(bpy.types.Operator):
#'''Tooltip'''
bl_idname = "text.test_line"
bl_label = "Test line"
all: bpy.props.IntProperty(default = False)
# @classmethod
# def poll(cls, context):
# return context.active_object is not None
def execute(self, context):
#print("test line")
all = self.all
if context.scene.use_intellisense:
sc = context.space_data
text = sc.text
send_console(context, all)
if not all:
bpy.ops.text.line_break()
return {'FINISHED'}
class SetBreakPoint(bpy.types.Operator):
bl_idname = "text.set_breakpoint"
bl_label = "Set Breakpoint"
def execute(self, context):
sc = bpy.context.space_data
text = sc.text
line = text.current_line
br = " #breakpoint"
print(line.body.find(br))
if line.body.find(br)>-1:
line.body = line.body.replace(br, "")
else:
line.body += br
return {'FINISHED'}
class Debug(bpy.types.Operator):
bl_idname = "text.debug"
bl_label = "Debug"
def execute(self, context):
binpath = bpy.app.binary_path
addonspath = binpath[0:binpath.rindex("\\")+1]+str(bpy.app.version[0])+"."+str(bpy.app.version[1])+"\\scripts\\addons\\"
print(addonspath)
sc = context.space_data
text = sc.text
br = " #breakpoint"
filepath = addonspath+"debug.py"
file = open(filepath, "w")
file.write("import pdb\n")
for line in text.lines:
l = line.body
if line.body.find(br)>-1:
indent = ""
for letter in line.body:
if not letter.isalpha():
indent+=letter
else:
break
file.write(l[0:-len(br)]+"\n")
file.write(indent+"pdb.set_trace()\n")
else:
file.write(line.body+"\n")
file.close()
import pdb
import debug
pdb.runcall("debug")
return {'FINISHED'}
class IntellisensePanel(bpy.types.Panel):
bl_label = "Intellisense"
bl_idname = "text.test_line"
bl_space_type = "TEXT_EDITOR"
bl_region_type = "UI"
#bl_context = "object"
text: bpy.props.StringProperty()
def draw(self, context):
layout = self.layout
row = layout.row()
text = self.text
row = layout.row()
row.prop(context.scene, "use_intellisense")
layout.operator("text.intellisense", text ="Intellisense")
row = layout.row()
row.operator("text.debug", text ="Debug")
row = layout.row()
row.operator("text.set_breakpoint")
row = layout.row()
row.operator("text.test_line").all=False
row = layout.row()
row.operator("text.test_line", text ="Test All").all=True
classes = [Intellisense, Intellioptions, TEXT_MT_intellimenu, IntellisensePanel, TestLine, SetBreakPoint, Debug]
def register():
for c in classes:
bpy.utils.register_class(c)
def unregister():
for c in classes:
bpy.utils.unregister_class(c)
if __name__ == "__main__":
register()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment