def update_highlighting(event): if not get_workbench().ready: # don't slow down loading process return if jedi_utils.get_version_tuple() < (0, 9): logging.warning("Jedi version is too old. Disabling name highlighter") return global tree if not tree: # using lazy importing to speed up Thonny loading tree = jedi_utils.import_python_tree() assert isinstance(event.widget, tk.Text) text = event.widget if not hasattr(text, "name_highlighter"): text.name_highlighter = VariablesHighlighter(text) # Alternatives: # NB! usages() is too slow when used on library names # text.name_highlighter = CombinedHighlighter(text) # text.name_highlighter = UsagesHighlighter(text) text.name_highlighter.schedule_update()
def print_tree(node, level=0): python_tree = jedi_utils.import_python_tree() indent = " " * level # if (isinstance(node, python_tree.PythonNode) and node.type == "sim" if node.type in ("simple_stmt", ) or isinstance(node, python_tree.Flow): print(indent, node.type, node.start_pos, node.end_pos) if hasattr(node, "children"): for child in node.children: print_tree(child, level + 1)
def tag_tree(node): nonlocal last_line, last_col python_tree = jedi_utils.import_python_tree() if node.type == "simple_stmt" or isinstance( node, (python_tree.Flow, python_tree.Scope)): start_line, start_col = node.start_pos end_line, end_col = node.end_pos # Before dealing with this node, # handle the case, where last vertical tag was meant for # same column, but there were empty or comment lines between if start_col == last_col: for i in range(last_line + 1, start_line): # NB! tag not visible when logically empty line # doesn't have indent prefix text.tag_add("ver_False_False", "%d.%d" % (i, last_col - 1), "%d.%d" % (i, last_col)) print("ver_False_False", "%d.%d" % (i, last_col - 1), "%d.%d" % (i, last_col)) print(node) # usually end_col is 0 # exceptions: several statements on the same line (semicoloned statements) # also unclosed parens in if-header for lineno in range(start_line, end_line if end_col == 0 else end_line + 1): top = lineno == start_line and lineno > 1 bottom = False # start_line == end_line-1 # horizontal line (only for first or last line) if top or bottom: text.tag_add( "hor_%s_%s" % (top, bottom), "%d.%d" % (lineno, start_col), "%d.%d" % (lineno + 1 if end_col == 0 else lineno, 0), ) print( "hor_%s_%s" % (top, bottom), "%d.%d" % (lineno, start_col), "%d.%d" % (lineno + 1, 0), ) # vertical line (only for indented statements) # Note that I'm using start col for all lines # (statement's indent shouldn't decrease in continuation lines) if start_col > 0: text.tag_add( "ver_%s_%s" % (top, bottom), "%d.%d" % (lineno, start_col - 1), "%d.%d" % (lineno, start_col), ) print( "ver_%s_%s" % (top, bottom), "%d.%d" % (lineno, start_col - 1), "%d.%d" % (lineno, start_col), ) last_line = lineno last_col = start_col # Recurse if node.type != "simple_stmt" and hasattr(node, "children"): for child in node.children: tag_tree(child)
""" NB! Stippling doesn't work on mac: http://wiki.tcl.tk/44444 http://rkeene.org/projects/tcl/tk.fossil/tkthistory/2954673 """ import logging import os.path from tkinter import font import thonny from thonny import get_workbench, jedi_utils from thonny.codeview import get_syntax_options_for_tag python_tree = jedi_utils.import_python_tree() def create_bitmap_file(width, height, predicate, name): cache_dir = os.path.join(thonny.THONNY_USER_DIR, "image_cache") name = "%s_%d_%d.xbm" % (name, width, height) filename = os.path.join(cache_dir, name) # if os.path.exists(filename): # return filename hex_lines = [] if width % 8 == 0: row_size = width else: # need to pad row size so that it is multiple of 8
def get_positions(self): tree = jedi_utils.import_python_tree() locs = [] def process_scope(scope): if isinstance(scope, tree.Function): # process all children after name node, # (otherwise name of global function will be marked as local def) local_names = set() global_names = set() for child in scope.children[2:]: process_node(child, local_names, global_names) else: if hasattr(scope, "subscopes"): for child in scope.subscopes: process_scope(child) elif hasattr(scope, "children"): for child in scope.children: process_scope(child) def process_node(node, local_names, global_names): if isinstance(node, tree.GlobalStmt): global_names.update([n.value for n in node.get_global_names()]) elif isinstance(node, tree.Name): if node.value in global_names: return if node.is_definition(): # local def locs.append(node) local_names.add(node.value) elif node.value in local_names: # use of local locs.append(node) elif isinstance(node, tree.BaseNode): # ref: jedi/parser/grammar*.txt if node.type == "trailer" and node.children[0].value == ".": # this is attribute return if isinstance(node, tree.Function): global_names = set( ) # outer global statement doesn't have effect anymore for child in node.children: process_node(child, local_names, global_names) source = self.text.get("1.0", "end") module = jedi_utils.parse_source(source) for child in module.children: if isinstance(child, tree.BaseNode) and jedi_utils.is_scope(child): process_scope(child) loc_pos = set(( "%d.%d" % (usage.start_pos[0], usage.start_pos[1]), "%d.%d" % (usage.start_pos[0], usage.start_pos[1] + len(usage.value)), ) for usage in locs) return loc_pos