Skip to content
Snippets Groups Projects
Commit e88b7dfc authored by lijenstina's avatar lijenstina
Browse files

Class Viewer: Improve the handling of comments, cleanup

Bumped version to 0.1.3
Pep 8 cleanup
Refactor menu code
Remove unused menu property
Use a BaseCheckPoll class for inheritance

Better support for comments:
- support inline comments
- trim the menu entries length to 60 characters
- skip the GPL block from the entries parsing

Some small UI changes
parent 7bdac2d3
Branches
Tags
No related merge requests found
......@@ -19,7 +19,7 @@
bl_info = {
"name": "Class Viewer",
"author": "Mackraken", "batFinger"
"version": (0, 1, 2),
"version": (0, 1, 3),
"blender": (2, 58, 0),
"location": "Text Editor > Toolbar, Text Editor > Right Click",
"warning": "",
......@@ -28,168 +28,176 @@ bl_info = {
"tracker_url": "https://developer.blender.org/maniphest/task/edit/form/2/",
"category": "Development"}
import bpy
from bpy.types import (
Operator,
Menu,
)
from bpy.props import IntProperty
# lists all defs, comment or classes
# space = current text editor
# sort = sort result
# tipo = kind of struct to look for
# escape = character right next to the class or def name
# note: GPL license block is skipped from the comment entries now
def getfunc(space, sort, tipo="def ", escape=""):
defs, license_clean, return_lists = [], [], []
if space.type == "TEXT_EDITOR" and space.text is not None:
txt = space.text
line_block_start, line_block_end = None, None
for i, l in enumerate(txt.lines):
try:
line = l.body
except:
line = ""
if tipo == "# ":
linex, line_c = "", ""
if tipo in line:
# find the license block
block_start = line.find("BEGIN GPL LICENSE BLOCK")
if block_start != -1:
line_block_start = i + 1
block_end = line.find("END GPL LICENSE BLOCK")
if block_end != -1:
line_block_end = i + 1
#lists all defs, comment or classes
#space = current text editor
#sort = sort result
#tipo = kind of struct to look for
#escape = character right next to the class or def name
def getfunc(space, sort, tipo="def ", escape= ""):
defs = []
if space.type=="TEXT_EDITOR":
if space.text!=None:
txt = space.text
for i, l in enumerate(txt.lines):
try:
line = l.body
except:
line=""
if line[0:len(tipo)]==tipo:
end = line.find(escape)
if end==0:
func = line[len(tipo)::]
# use line partition, get the last tuple element as it is the comment
line_c = line.partition("#")[2]
# strip the spaces from the left if any and
# cut the comment at the 60 characters length max
linex = line_c[:60].lstrip() if len(line_c) > 60 else line_c.lstrip()
if end == 0:
func = linex
else:
func = line[len(tipo):end]
defs.append([func, i+1])
if sort: defs.sort()
return defs
class TEXT_OT_Jumptoline(bpy.types.Operator):
bl_label = "Jump"
bl_idname = "text.jumptoline"
__doc__ = "Jump to line"
line = bpy.props.IntProperty(default=-1)
func = linex.rstrip(escape)
defs.append([func, i + 1])
elif line[0: len(tipo)] == tipo:
end = line.find(escape)
if end == 0:
func = line[len(tipo)::]
else:
func = line[len(tipo):end]
defs.append([func, i + 1])
if line_block_start and line_block_end:
# note : the slice should keep the first line of the license block
license_clean = defs[line_block_start: line_block_end]
return_lists = [line for line in defs if line not in license_clean] if license_clean else defs
if sort:
return_lists.sort()
return return_lists
def draw_menus(layout, space, tipo, escape):
items = getfunc(space, 1, tipo, escape)
if not items:
layout.label(text="Not found", icon="INFO")
return
for it in items:
layout.operator("text.jumptoline", text="{}".format(it[0])).line = it[1]
class BaseCheckPoll():
@classmethod
def poll(cls, context):
if context.area.spaces[0].type!="TEXT_EDITOR":
if context.area.spaces[0].type != "TEXT_EDITOR":
return False
else:
return context.area.spaces[0].text!=None
else:
return context.area.spaces[0].text is not None
class TEXT_OT_Jumptoline(Operator, BaseCheckPoll):
bl_label = "Jump"
bl_idname = "text.jumptoline"
bl_description = "Jump to line containing the text"
__doc__ = "Jump to line containing the passed line integer. Used by the Class Viewer add-on"
line = IntProperty(default=-1)
def execute(self, context):
scn = context.scene
if self.line == -1:
self.report({'WARNING'}, "No valid line found. Operation Cancelled")
return {'CANCELLED'}
if self.line!=-1:
bpy.ops.text.jump(line=self.line)
bpy.ops.text.jump(line=self.line)
self.report({'INFO'}, "Jump to line: {}".format(self.line))
return {'FINISHED'}
class CommentsMenu(bpy.types.Menu):
class CommentsMenu(Menu, BaseCheckPoll):
bl_idname = "OBJECT_MT_select_comments"
bl_label = "Select"
@classmethod
def poll(cls, context):
if context.area.spaces[0].type!="TEXT_EDITOR":
return False
else:
return context.area.spaces[0].text!=None
bl_label = "Comments"
def draw(self, context):
layout = self.layout
space = context.area.spaces[0]
items = getfunc(space, 1, "### ", "")
for it in items:
layout.operator("text.jumptoline",text=it[0]).line = it[1]
draw_menus(layout, space, "# ", "\n")
class DefsMenu(bpy.types.Menu):
class DefsMenu(Menu, BaseCheckPoll):
bl_idname = "OBJECT_MT_select_defs"
bl_label = "Select"
tipo = bpy.props.BoolProperty(default=False)
@classmethod
def poll(cls, context):
if context.area.spaces[0].type!="TEXT_EDITOR":
return False
else:
return context.area.spaces[0].text!=None
bl_label = "Definitions"
def draw(self, context):
scn = context.scene
layout = self.layout
space = context.area.spaces[0]
tipo = self.tipo
items = getfunc(space, 1, "def ", "(")
for it in items:
layout.operator("text.jumptoline",text=it[0]).line = it[1]
class ClassesMenu(bpy.types.Menu):
draw_menus(layout, space, "def ", "(")
class ClassesMenu(Menu, BaseCheckPoll):
bl_idname = "OBJECT_MT_select_classes"
bl_label = "Select"
@classmethod
def poll(cls, context):
if context.area.spaces[0].type!="TEXT_EDITOR":
return False
else:
return context.area.spaces[0].text!=None
bl_label = "Classes"
def draw(self, context):
layout = self.layout
space = context.area.spaces[0]
items = getfunc(space, 1, "class ", "(")
for it in items:
layout.operator("text.jumptoline",text=it[0]).line = it[1]
draw_menus(layout, space, "class ", "(")
def GotoComments(self, context):
self.layout.menu("OBJECT_MT_select_comments", text="Comments", icon='PLUGIN')
return False
def GotoDefs(self, context):
self.layout.menu("OBJECT_MT_select_defs", text="Defs", icon='PLUGIN')
return False
def menu_development_class_view(self, context):
self.layout.separator()
def GotoClasses(self, context):
self.layout.menu("OBJECT_MT_select_classes", text="Classes", icon='PLUGIN')
return False
self.layout.menu("OBJECT_MT_select_comments", icon='SHORTDISPLAY')
self.layout.menu("OBJECT_MT_select_defs", icon='FILE_TEXT')
self.layout.menu("OBJECT_MT_select_classes", icon='SCRIPTPLUGINS')
classes = [TEXT_OT_Jumptoline, ClassesMenu, DefsMenu, CommentsMenu]
classes = (
TEXT_OT_Jumptoline,
ClassesMenu,
DefsMenu,
CommentsMenu,
)
def register():
for c in classes:
bpy.utils.register_class(c)
bpy.types.TEXT_MT_toolbox.append(GotoComments)
bpy.types.TEXT_MT_toolbox.append(GotoDefs)
bpy.types.TEXT_MT_toolbox.append(GotoClasses)
for cls in classes:
bpy.utils.register_class(cls)
bpy.types.TEXT_MT_toolbox.append(menu_development_class_view)
def unregister():
for c in classes:
bpy.utils.unregister_class(c)
bpy.types.TEXT_MT_toolbox.remove(GotoComments)
bpy.types.TEXT_MT_toolbox.remove(GotoDefs)
bpy.types.TEXT_MT_toolbox.remove(GotoClasses)
for cls in classes:
bpy.utils.unregister_class(cls)
bpy.types.TEXT_MT_toolbox.remove(menu_development_class_view)
if __name__ == "__main__":
register()
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment