From 57dd78566bc9e990282b6e0811fdbdd1cf9a9d02 Mon Sep 17 00:00:00 2001 From: r08222011 Date: Thu, 4 Jan 2024 17:18:27 +0800 Subject: [PATCH 1/2] Full-width characters compatibility and `max_width` adjustability --- cowsay/main.py | 69 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 55 insertions(+), 14 deletions(-) diff --git a/cowsay/main.py b/cowsay/main.py index b923f87..7869f1e 100644 --- a/cowsay/main.py +++ b/cowsay/main.py @@ -1,5 +1,6 @@ from __future__ import annotations import re +import string from .characters import CHARS @@ -15,26 +16,65 @@ class CowsayError(LookupError): def wrap_lines(lines: list, max_width: int = 49) -> list: + # Buffers that will be used in the last. new_lines = [] + new_lines_width = [] + for line in lines: - for line_part in [ - line[i: i+max_width] for i in range(0, len(line), max_width) - ]: - new_lines.append(line_part) - return new_lines + # Check whether the line width is overflow (greater than + # max_width) because of half-width and full-width characters. + line_buffer = "" + line_width = 0 + + # Loop over the characters in the line. + for i in range(len(line)): + + character = line[i] + + if character in list(string.printable): + # Half width characters. + char_width = 1 + else: + # Full width characters. + char_width = 2 + + # Check whether the `line_buffer` is overflowed. + overflow = (line_width + char_width > max_width) + + if overflow: + # Add `line_buffer` and `line_width`. + new_lines.append(line_buffer) + new_lines_width.append(line_width) -def generate_bubble(text: str) -> list: + # Reinitialize the `line_buffer` and `line_width`. + line_buffer = character + line_width = char_width + else: + # Add this character to `line_buffer` if not overflowed. + line_buffer += character + line_width += char_width + + if (i == (len(line) - 1)): + # Last character. + new_lines.append(line_buffer) + new_lines_width.append(line_width) + + return new_lines, new_lines_width + + +def generate_bubble(text: str, max_width: int = 49) -> list: lines = [line.strip() for line in text.split('\n')] - lines = wrap_lines([line for line in lines if line]) - text_width = max([len(line) for line in lines]) + lines, lines_width = wrap_lines( + lines=[line for line in lines if line], max_width=max_width) + text_width = max(lines_width) output = [" " + "_" * text_width] if len(lines) > 1: output.append(" /" + " " * text_width + "\\") - for line in lines: - output.append("| " + line + " " * (text_width - len(line) + 1) + "|") + for line, line_width in zip(lines, lines_width): + output.append("| " + line + " " * (text_width - line_width + 1) + "|") if len(lines) > 1: output.append(" \\" + " " * text_width + "/") output.append(" " + "=" * text_width) @@ -52,12 +92,13 @@ def generate_char(char_lines: str, text_width: int) -> list: return output -def draw(text: str, char_lines: str, to_console: bool = True) -> None | str: +def draw(text: str, char_lines: str, to_console: bool = True, + max_width: int = 49) -> None | str: if len(re.sub(r'\s', '', text)) == 0: raise CowsayError('Pass something meaningful to cowsay') - output = generate_bubble(text) + output = generate_bubble(text, max_width=max_width) text_width = max([len(line) for line in output]) - 4 # 4 is the frame output += generate_char(char_lines, text_width) if to_console: @@ -67,9 +108,9 @@ def draw(text: str, char_lines: str, to_console: bool = True) -> None | str: return '\n'.join(output) -def get_output_string(char: str, text: str) -> str: +def get_output_string(char: str, text: str, max_width: int = 49) -> str: if char in CHARS: - return draw(text, CHARS[char], to_console=False) + return draw(text, CHARS[char], to_console=False, max_width=max_width) else: raise CowsayError(f'Available Characters: {char_names}') From 30a49494acd43b706520e1433f94af8c899460db Mon Sep 17 00:00:00 2001 From: r08222011 Date: Thu, 4 Jan 2024 17:35:22 +0800 Subject: [PATCH 2/2] use enumerate --- cowsay/main.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cowsay/main.py b/cowsay/main.py index 7869f1e..fc89da2 100644 --- a/cowsay/main.py +++ b/cowsay/main.py @@ -28,9 +28,7 @@ def wrap_lines(lines: list, max_width: int = 49) -> list: line_width = 0 # Loop over the characters in the line. - for i in range(len(line)): - - character = line[i] + for i, character in enumerate(line): if character in list(string.printable): # Half width characters.