def render(self, width: int) -> str: """Render the table""" rendered_rows = [] for row in self.rows: # if all cells are with fixed width, expand last to fill the row if all([cell.width is not None for cell in row]): row[-1] = Group(row[-1], Line(" ")) # pre-render the row group = Group(*row, separator=self.box.BARS[0], sandwich=True) rendered_rows.append(group.render(width)) # rendered groups (rows and delimiters) groups = [self.hbound(None, rendered_rows[0]).render(width)] for i, row in enumerate(rendered_rows): groups.append(row) # render delimiter next_row = rendered_rows[i + 1] if i < len(rendered_rows) - 1 else None groups.append(self.hbound(row, next_row).render(width)) return "\n".join(groups)
def ask(self, exit_on: Optional[str] = None): """Ask the question and execute the callback linked to the uset choice""" exit_on = exit_on or self.exit_on if exit_on is not None: exc = Exception("`exit_on` must be an existing option") assert exit_on in self.options, exc width = self.console.columns choice = self.input(width) while choice not in self.options: error = Group( self.error_prompt, self.error_message, self.build_help(), separator=" ", ) self.console.print(error) choice = self.input(width) content = self.options[choice](width) if content is not None: self.console.print(content) if exit_on is not None and choice != exit_on: self.ask(exit_on)
def hbound(self, over: Optional[str], below: Optional[str]) -> Group: """Create the horizontal separator for two rendered rows""" first = over is None last = below is None over = over or " " * len(below) below = below or " " * len(over) corners_map = { 0: [self.box.TS[2], self.box.TS[3]], 1: [self.box.CORNERS[1], self.box.CORNERS[0]], # first row 2: [self.box.CORNERS[3], self.box.CORNERS[2]], # last row } pieces_map = { 0: self.box.BARS[1], # no bounds 1: self.box.TS[1], # over bound 3: self.box.TS[0], # under bound 4: self.box.CROSS, # over and under bound } corners = corners_map[1 * first + 2 * last] pieces = [] for i in range(1, len(over) - 1): over_bound = i < len(over) and over[i] == self.box.BARS[0] below_bound = i < len(below) and below[i] == self.box.BARS[0] piece = pieces_map[1 * over_bound + 3 * below_bound] pieces.append(Text(piece)) return Group(Text(corners[0]), *pieces, Text(corners[1]))
def add_column(self, *column: Union[str, Renderable], same_width: bool = False, append: bool = False): """Add a column of cells""" column = [ cell if isinstance(cell, Renderable) else Text(cell, expand=True) for cell in column ] if same_width: # get max width from cells with fixed width max_width = max([cell.width or -1 for cell in column]) if max_width > 0: # pre-render each element with the max width column = map(lambda cell: Group(cell, Line(" ")), column) column = map(lambda group: Text(group.render(max_width)), column) column = list(column) for i, cell in enumerate(column): # if needs to append, shift the index to the ne dof the list of rows i += len(self.rows) if append else 0 self.add_row(cell) if i >= len( self.rows) else self.rows[i].append(cell)
def bar(width: int) -> str: return Group( Text(self.bounds[0]), Text(self.innerbar(width)) if self.runnign else Line(self.full), Text(self.bounds[1]), ).render(width)
def bar(width: int) -> str: return Group( Text(self.bounds[0]), Line(self.fill, int((width - 3) * self.percent)), Text(self.fill if self.completed else self.head), Line(self.void), Text(self.bounds[1]), ).render(width)
def render(self, width: int) -> str: """Render the bar""" items = [ self.description, self.bar, Text(f"{int(self.percent*100):3g}%"), Text( f"{self.bounds[0]}{self.position}/{self.tot}{self.bounds[1]}"), ] items = items[1:] if self.description is None else items return Group(*items, separator=" ").render(width)
def input(self, width: Optional[int] = None) -> str: """Get user input""" width = width or self.console.columns prompt = Group(self.prompt, Text(" ")) return self.get_input(prompt.render(width))
def build_help(self) -> Group: """Build help from the existing options""" tokens = Group(*map(Text, self.options), separator=" | ") return Group(Text("["), tokens, Text("]"), separator=" ")
def render(self, width: int) -> str: """Render the loader""" items = [self.description, self.bar] items = items[1:] if self.description is None else items return Group(*items, separator=" ").render(width)