Files
Berry/completions_menu.py

89 lines
2.6 KiB
Python
Raw Normal View History

from textual.screen import ModalScreen
from textual.containers import Container
from context_menu import ButtonStatic
from textual.widgets import TextArea, OptionList
from textual.widgets.option_list import Option
from textual.widget import Widget
from textual.geometry import Region, Spacing, Offset
class CompletionsMenu(Widget):
DEFAULT_CSS = """
CompletionsMenu {
width: auto;
height: auto;
overlay: screen;
position: absolute;
background: $surface;
min-width: 30;
OptionList {
padding: 0 1;
background: $surface;
border: $panel tall;
width: 30;
}
}
"""
def __init__(self, options: list[dict], text_area: TextArea):
super().__init__()
self.options = options
self.text_area = text_area
self.options_list = None
def compose(self):
self.options_list = OptionList(*[self.render_option(option) for option in self.options])
yield self.options_list
def update(self, new_choices: list[dict]):
self.options = new_choices
self.options_list.set_options([self.render_option(option) for option in self.options])
def hide(self):
self.display = "none"
def show(self):
self.display = "block"
def render_option(self, option_data: dict):
icon = ""
match option_data["type"]:
case 1: # text
icon = "󰦨"
case 2 | 3: # method / function
icon = "[blueviolet]󰅩[/]"
case 14: # keyword
icon = ""
case 7: # class
icon = "[orange][/]"
case 9: # module
icon = "[cornflowerblue][/]"
case _:
icon = str(option_data["type"])
return icon + " " + option_data["text"]
def align_to_cursor(self):
x, y = self.text_area.cursor_screen_offset
dropdown = self.options_list
width, height = dropdown.outer_size
# Constrain the dropdown within the screen.
x, y, _width, _height = Region(x - 1, y + 1, width, height).constrain(
"inside",
"none",
Spacing.all(0),
self.screen.scrollable_content_region,
)
self.absolute_offset = Offset(x, y)
def on_mount(self):
#self.options_list.styles.height = len(self.options_list.children) + 2
self.align_to_cursor()