def format_column(column_name, column, value): text = str(value) if column_name == "resource_status": uvalue = value.upper() if "FAIL" in uvalue: color = colorama.Fore.RED elif "ROLLBACK" in uvalue: color = colorama.Fore.YELLOW elif "IN_PROGRESS" in uvalue: color = colorama.Fore.BLUE elif uvalue == "DELETE_COMPLETE": color = colorama.Fore.LIGHTBLACK_EX elif "COMPLETE" in uvalue: color = colorama.Fore.GREEN else: color = colorama.Fore.WHITE text = "%s%s%s" % (color, value, colorama.Style.RESET_ALL) if ansiwrap.ansilen(text) > column.max_length: half_length = (column.max_length - 1) / 2.0 output_text = "%s%s%s" % ( text[:int(math.floor(half_length))], ELLIPSIS, text[-int(math.ceil(half_length)):], ) else: output_text = text padding = " " * max( 0, min(column.max_value_length, column.max_length) - ansiwrap.ansilen(output_text), ) return "%s%s" % (padding, output_text)
def ansi_ljust(s: str, width: int) -> str: """Like s.ljust(width), but accounting for ANSI colors.""" needed: int = width - ansiwrap.ansilen(s) if needed > 0: return s + " " * needed else: return s
def extended_len(x): """ Executable prefixes and suffixes like numberers complicate life compared to simple strings, because they are generators, and the length of their returned strings is not particularly knoable. """ return ansilen(x) if is_string(x) else len(x)
def side_by_side(a, b, pad): a_lines = a.splitlines() b_lines = b.splitlines() max_line = max([ansilen(a_line) for a_line in a_lines]) return '\n'.join([ansiljust(a_line, max_line+pad) + b_line for a_line, b_line in itertools.izip_longest(a_lines, b_lines, fillvalue='')])
def render(self): if self.state_counts: state_str = self.state.replace(State.PENDING, "ready").upper() line = "{help} {state} P:{P} Q:{Q} R:{R} D:{D} E:{E} K:{K}".format( help=self.key_mode.help(), state=log.format(state_str, bold=False, color=STATE_TO_COLOR[self.state]), P=self.state_count_str(State.PENDING), Q=self.state_count_str(State.QUEUED), R=self.state_count_str(State.RUNNING), D=self.state_count_str(State.DONE), E=self.state_count_str(State.ERROR), K=self.state_count_str(State.WORKER_ERROR), ) else: line = self.key_mode.help() screen_size = termsize.getTerminalWidth() # NOTE: would use StringIO but we need to examine the string using # `ansilen` at each step output_line = "" for c in line: if ansilen(output_line) >= screen_size: break output_line += c print(f"\r{log.Control.ERASE_LINE}{output_line}", end="", flush=True)
def ansilen(s): """ Return the length of the string minus any ANSI control codes. Args: s (string): The input string to check. Returns: int: The string length. """ if hasattr(textwrap, 'ansilen'): return textwrap.ansilen(s) else: return len(s)
def __len__(self): """ What is the string length of the instantiated template now? NB This can change over time, as n does. Fixed-width format strings limit how often it can change (to when n crosses a power-of-10 boundary > the fixed template length can accommodate). This implementation saves the templated string it has created for reuse. """ t = self.template result = t.format(n=self.n) self._formatted = result return ansilen(result)
def boxedtext(title, text, tint, width=75): ''' Put text in a lovely unicode block element box. The top of the box will contain a title. The box elements will be colored. ''' remainder = width - 2 - len(title) ul = u'\u2554' # u'\u250C' ur = u'\u2557' # u'\u2510' ll = u'\u255A' # u'\u2514' lr = u'\u255D' # u'\u2518' bar = u'\u2550' # u'\u2500' strut = u'\u2551' # u'\u2502' template = '%-' + str(width) + 's' print('') print(colored(''.join([ul, bar*3, ' ', title, ' ', bar*remainder, ur]), tint)) for line in text.split('\n'): lne = line.rstrip() add = ' '*(width-ansiwrap.ansilen(lne)) print(' '.join([colored(strut, tint), lne, add, colored(strut, tint)])) print(colored(''.join([ll, bar*(width+3), lr]), tint))
def founds_printify(analyzer: BaseAnalyzer, give_error=True): from colored import fg, bg, attr def ansi_ljust(s, width): needed = width - ansiwrap.ansilen(s) if needed > 0: return s + ' ' * needed else: return s for found in analyzer.found: found["code"] = highlight_colors(analyzer.language, found["code"]) filename_line_col_max = len(analyzer.filename) + max([len(str(x['lineno']) + str(x['col'])) for x in analyzer.found]) + 2 code_max = max([ansiwrap.ansilen(x['code']) for x in analyzer.found]) lines = "" for found in analyzer.found: filename_line_col = (analyzer.filename + ":" + str(found['lineno']) + ":" + str(found['col'])).ljust(filename_line_col_max + 4) code = ansi_ljust(found['code'], code_max + 4) line = f"{fg(164)}{filename_line_col}{attr(0)}{code}{{ " if found['name'] != found['from']: line += f"{fg('red')}{found['name']}{attr(0)}() -> " line += f"{fg(46)}{found['from']}{attr(0)}() }}" lines += line + "\n" if len(analyzer.found) == 0: return f"{analyzer.filename}: No potentially dangerous functions found" if give_error else None return lines
def ansi_ljust(s, width): needed = width - ansiwrap.ansilen(s) if needed > 0: return s + " " * needed else: return s
def ansiljust(string, length): return string + (' ' * max(0, length - ansilen(string)))
def show(self) -> "Grid": # We have to handle y/rows manually because of forced blank lines, # terminal scrolling, etc; but x/columns are no trouble. start_x = x = TERM.get_location()[1] printed_rows = 0 for index, cell in enumerate(self.cells): last_in_row = index % self.cells_per_row == 0 one_per_row = self.cells_per_row < 2 first_in_row = index == 0 if last_in_row and (one_per_row or not first_in_row): # Print enough lines to begin a new row below the previous one TERM.print_esc("\n" * self.cell_rows) printed_rows += 1 if self.max_rows and printed_rows > self.max_rows: break x = start_x content: FromCallable = self._get_content(cell) if isinstance(content, Image): content_cols = content.cols content_rows = content.rows elif not content: content_cols = content_rows = 0 else: content_cols = ansilen(max(content.splitlines(), key=ansilen)) content_rows = ansilen(content.splitlines()) # Calculate paddings inside the cell to align the content inner_x = round((self.cell_cols / 2) - (content_cols / 2)) inner_y = math.floor((self.cell_rows / 2) - (content_rows / 2)) # Print the vertical padding as blank lines TERM.print_esc("\n" * inner_y) if isinstance(content, Image): content.show(x=x + inner_x, z=-1) else: print(textwrap.indent(content, " " * (x + inner_x))) # If needed, print blank lines to "complete the cell", # i.e. content height didn't fill it. # The cursor needs to always be at the cell row's bottom, # for the next "put back" escape code to work properly. TERM.print_esc("\n" * (self.cell_rows - content_rows - inner_y)) # "Undo" any terminal scrolling and put cursor back to the row # beginning so we can print more content in line. TERM.print_esc(TERM.move_relative_y(-self.cell_rows - 1)) x += self.cell_cols TERM.print_esc("\n" * self.cell_rows) return self
def __len__(self): return ansilen(self.rest if self.counter else self.first)