1import os.path
2import logging
3import tkinter as tk
4
5from thonny import get_workbench, jedi_utils
6from thonny.ui_utils import control_is_pressed
7
8logger = logging.getLogger(__name__)
9
10
11def goto_definition(event):
12    if not control_is_pressed(event.state):
13        return
14
15    assert isinstance(event.widget, tk.Text)
16    text = event.widget
17
18    source = text.get("1.0", "end")
19    index = text.index("insert")
20    index_parts = index.split(".")
21    line, column = int(index_parts[0]), int(index_parts[1])
22    try:
23        editor = text.master.home_widget
24        path = editor.get_filename()
25    except Exception as e:
26        logger.warning("Could not get path", exc_info=e)
27        path = None
28
29    defs = jedi_utils.get_definitions(source, line, column, path)
30    if len(defs) > 0:
31        # TODO: handle multiple results like PyCharm
32        module_path = str(defs[0].module_path)
33        if not os.path.isfile(module_path):
34            logger.warning("%s is not a file", module_path)
35            return
36
37        module_name = defs[0].module_name
38        line = defs[0].line
39        if module_path and line is not None:
40            get_workbench().get_editor_notebook().show_file(module_path, line)
41        elif module_name == "" and line is not None:  # current editor
42            get_workbench().get_editor_notebook().get_current_editor().select_range(line)
43
44
45def load_plugin() -> None:
46    wb = get_workbench()
47    wb.bind_class("CodeViewText", "<1>", goto_definition, True)
48