# Copyright 2022 The Pigweed Authors # # Licensed under the Apache License, Version 2.0 (the "License"); you may not # use this file except in compliance with the License. You may obtain a copy of # the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations under # the License. """Wrapper fuctions to add borders around prompt_toolkit containers.""" from typing import Callable, List, Optional, Union from prompt_toolkit.layout import ( AnyContainer, FormattedTextControl, HSplit, VSplit, Window, ) def create_border( # pylint: disable=too-many-arguments content: AnyContainer, content_height: Optional[int] = None, title: Union[Callable[[], str], str] = '', border_style: Union[Callable[[], str], str] = '', base_style: Union[Callable[[], str], str] = '', top: bool = True, bottom: bool = True, left: bool = True, right: bool = True, horizontal_char: str = '━', vertical_char: str = '┃', top_left_char: str = '┏', top_right_char: str = '┓', bottom_left_char: str = '┗', bottom_right_char: str = '┛', left_margin_columns: int = 0, right_margin_columns: int = 0, ) -> HSplit: """Wrap any prompt_toolkit container in a border.""" top_border_items: List[AnyContainer] = [] if left: top_border_items.append( Window(width=1, height=1, char=top_left_char, style=border_style) ) title_text = None if title: if isinstance(title, str): title_text = FormattedTextControl( [('', f'{horizontal_char}{horizontal_char} {title} ')] ) else: title_text = FormattedTextControl(title) top_border_items.append( Window( title_text, char=horizontal_char, # Expand width to max available space dont_extend_width=False, style=border_style, ) ) if right: top_border_items.append( Window(width=1, height=1, char=top_right_char, style=border_style) ) content_items: List[AnyContainer] = [] if left: content_items.append( Window( width=1, height=content_height, char=vertical_char, style=border_style, ) ) if left_margin_columns > 0: content_items.append( Window( width=left_margin_columns, height=content_height, char=' ', style=border_style, ) ) content_items.append(content) if right_margin_columns > 0: content_items.append( Window( width=right_margin_columns, height=content_height, char=' ', style=border_style, ) ) if right: content_items.append( Window(width=1, height=2, char=vertical_char, style=border_style) ) bottom_border_items: List[AnyContainer] = [] if left: bottom_border_items.append( Window(width=1, height=1, char=bottom_left_char) ) bottom_border_items.append( Window( char=horizontal_char, # Expand width to max available space dont_extend_width=False, ) ) if right: bottom_border_items.append( Window(width=1, height=1, char=bottom_right_char) ) rows: List[AnyContainer] = [] if top: rows.append(VSplit(top_border_items, height=1, padding=0)) rows.append(VSplit(content_items, height=content_height)) if bottom: rows.append( VSplit(bottom_border_items, height=1, padding=0, style=border_style) ) return HSplit(rows, style=base_style)