Skip to content

environment

dev_tool.tui.environment

__all__ = ['DiffMenu'] module-attribute

DiffMenu

The constructor for the EnvironmentDiffMenu class.

Parameters:

  • terminal (Terminal) –

    The blessed Terminal instance.

  • local (dict[str, str]) –

    The local environment variables.

  • remote (dict[str, str]) –

    The remote environment variables.

Source code in dev_tool/tui/environment/menu.py
def __init__(
    self,
    terminal: Terminal,
    local: dict[str, str],
    remote: dict[str, str]
) -> None:
    """
    The constructor for the EnvironmentDiffMenu class.

    :param terminal: The blessed Terminal instance.
    :param local: The local environment variables.
    :param remote: The remote environment variables.
    """

    self.local = local
    self.offset = 0
    self.remote = remote
    self.terminal = terminal

    self.added = {k: v for k, v in remote.items() if k not in local}
    self.modified = {k: {'local': local[k], 'remote': remote[k]} for k in local if k in remote and local[k] != remote[k]}
    self.removed = {k: v for k, v in local.items() if k not in remote}

local = local instance-attribute

offset = 0 instance-attribute

remote = remote instance-attribute

terminal = terminal instance-attribute

added = {k: v for k, v in remote.items() if k not in local} instance-attribute

modified = {k: {'local': local[k], 'remote': remote[k]} for k in local if k in remote and local[k] != remote[k]} instance-attribute

removed = {k: v for k, v in local.items() if k not in remote} instance-attribute

draw_menu

A method that draws the environment diff menu.

Source code in dev_tool/tui/environment/menu.py
def draw_menu(self) -> None:
    """A method that draws the environment diff menu."""

    output = []
    output.append(self.terminal.home + self.terminal.clear)

    header = ' Environment variables'
    background = ' ' * self.terminal.width

    output.append(
        move(self.terminal, 0, 0) +
        self.terminal.on_color_rgb(43, 40, 59) +
        self.terminal.bold +
        self.terminal.color_rgb(255, 255, 255) +
        background +
        self.terminal.normal
    )

    output.append(
        move(self.terminal, 0, 0) +
        self.terminal.on_color_rgb(43, 40, 59) +
        self.terminal.bold +
        self.terminal.color_rgb(255, 255, 255) +
        header +
        self.terminal.normal
    )

    changes = self._draw_changes()
    visible_height = self.terminal.height - 6
    visible_changes = changes[self.offset:self.offset + visible_height]

    for index, line in enumerate(visible_changes):
        output.append(move(self.terminal, 2 + index, 4) + line)

    question_line = self.terminal.height - 3
    output.append(
        move(self.terminal, question_line, 4) +
        'Apply to development.env: overwrite [y], merge keeping ours [o], merge keeping theirs [t], cancel [n]'
    )

    status_text = ' Press up/down to scroll | y overwrite | o merge ours | t merge theirs | n cancel | q quit'
    status_bg = ' ' * self.terminal.width
    status_line = self.terminal.height - 1

    output.append(
        move(self.terminal, status_line, 0) +
        self.terminal.on_color_rgb(70, 68, 80) +
        self.terminal.color_rgb(255, 255, 255) +
        status_bg +
        self.terminal.normal
    )

    output.append(
        move(self.terminal, status_line, 0) +
        self.terminal.on_color_rgb(70, 68, 80) +
        self.terminal.color_rgb(255, 255, 255) +
        status_text +
        self.terminal.normal
    )

    print(''.join(output), end='', flush=True)  # noqa: T201

handle_input

A method that handles input for the menu.

Parameters:

  • key (str) –

    The key name.

Returns:

  • MergeChoice | None –

    The selected choice or None to continue.

Source code in dev_tool/tui/environment/menu.py
def handle_input(self, key: str) -> MergeChoice | None:
    """
    A method that handles input for the menu.

    :param key: The key name.
    :return: The selected choice or None to continue.
    """

    changes = self._draw_changes()
    offset = max(0, len(changes) - (self.terminal.height - 6))

    match key:
        case Key.UP:
            self.offset = max(0, self.offset - 1)
        case Key.DOWN:
            self.offset = min(offset, self.offset + 1)
        case _ if key in (Key.ESCAPE, Key.BACKSPACE, Key.DELETE):
            return MergeChoice.CANCEL
        case _:
            return self._CHOICES.get(key.lower())

    return None

run

A method that runs the menu loop.

Returns:

  • MergeChoice –

    The choice the user made, or cancel if the menu was left.

Source code in dev_tool/tui/environment/menu.py
def run(self) -> MergeChoice:
    """
    A method that runs the menu loop.

    :return: The choice the user made, or cancel if the menu was left.
    """

    result: MergeChoice | None = None

    with TerminalSuspension(self.terminal) as suspension:
        while result is None:
            suspension.acknowledge()

            with self.terminal.fullscreen(), self.terminal.cbreak(), self.terminal.hidden_cursor():
                self.draw_menu()

                while result is None and not suspension.resumed:
                    key = self.terminal.inkey(timeout=INPUT_POLL_SECONDS)

                    if key:
                        result = self.handle_input(key.name or key)

                        if result is None:
                            self.draw_menu()

    return result if result is not None else MergeChoice.CANCEL