From 7688f7e215d0360f636ef3996d25706bd524da31 Mon Sep 17 00:00:00 2001 From: alisceon Date: Sat, 20 Sep 2025 09:36:21 +0200 Subject: [PATCH] more cats! --- home/alisceon/base.nix | 2 +- home/conf/xonsh/kiddycad.cow | 6 --- home/conf/xonsh/kittycatsay.py | 95 ++++++++++++++++++++++++++++++++++ home/conf/xonsh/xonshrc | 5 +- 4 files changed, 98 insertions(+), 10 deletions(-) delete mode 100644 home/conf/xonsh/kiddycad.cow create mode 100644 home/conf/xonsh/kittycatsay.py diff --git a/home/alisceon/base.nix b/home/alisceon/base.nix index 2bb6332..b87d03e 100644 --- a/home/alisceon/base.nix +++ b/home/alisceon/base.nix @@ -112,7 +112,7 @@ # xonsh extras xdg.configFile."xonsh/theo.py".source = ../conf/xonsh/theo.py; - xdg.configFile."xonsh/kiddycad.cow".source = ../conf/xonsh/kiddycad.cow; + xdg.configFile."xonsh/kittycatsay.py".source = ../conf/xonsh/kittycatsay.py; # Ensure fish exists for the completer backend home.packages = [ pkgs.fish ]; } # end file diff --git a/home/conf/xonsh/kiddycad.cow b/home/conf/xonsh/kiddycad.cow deleted file mode 100644 index 9ec3a19..0000000 --- a/home/conf/xonsh/kiddycad.cow +++ /dev/null @@ -1,6 +0,0 @@ -$the_cow = <<"EOC"; - $thoughts | ╱|、 - $thoughts| (˚ˎ 。7 - |、˜〵 - じしˍ,)ノ -EOC \ No newline at end of file diff --git a/home/conf/xonsh/kittycatsay.py b/home/conf/xonsh/kittycatsay.py new file mode 100644 index 0000000..f41522c --- /dev/null +++ b/home/conf/xonsh/kittycatsay.py @@ -0,0 +1,95 @@ +import os +import sys + +DEFAULT_CAT = r""" ╱|、 + (˚ˎ 。7 {{HBAR}}{{HBAR}} + |、˜〵 + じしˍ,)ノ""" + +BOXES = { + "rounded": { + "hbar": "─", + "vbar": "│", + "corner_tl": "╭", + "corner_tr": "╮", + "corner_bl": "╰", + "corner_br": "╯", + "joiner": "┤", + } + +} + +def main(): + parser = False + args = False + isatty = sys.stdin.isatty() + message = "" + if not isatty: + message = sys.stdin.read().strip() + if len(sys.argv) > 1: + import argparse + parser = argparse.ArgumentParser(description="Display a message in a speech bubble next to a kittycat.") + parser.add_argument("--box", type=str, choices=BOXES.keys(), default="rounded", help="The style of the speech bubble.") + parser.add_argument("-W", type=int, default=0, help="The maximum width of the message before wrapping. Defaults to terminal width minus kittycat width.") + parser.add_argument("-f", "--file", type=str, default="./kittycats/default.cat", help="The path to the kittycat file to use.") + if isatty: + parser.add_argument("message", type=str, help="The message to display.") + args = parser.parse_args() + message = args.message + else: + args = parser.parse_args() + if len(message) == 0: + message = [ + "Meow.", + "We still don't support multi-line input.", + "Try a pipe why don't you?", + "Wi wi wi wi.", + "Weh weh weh.", + ][int((int.from_bytes(open("/dev/urandom", "rb").read(1), "big") / 256) * 5)] + kittycat = DEFAULT_CAT + box_style = "rounded" + wrapping = 0 + if args: + if os.path.isfile(args.file): + kittycat = open(args.file).read() + box_style = args.box + wrapping = args.W + outcat = get_kittycat(kittycat, message, BOXES[box_style], wrap=wrapping) + print(outcat) + +def get_kittycat(cat: str, msg: str, box: dict[str, str], wrap = 0): + for kw in box.keys(): + cat = cat.replace(r"{{" + kw.upper() + r"}}", box[kw]) + cat_lines = cat.splitlines() + cat_width = max(len(line) for line in cat_lines) + max_msg_height = len(cat_lines) - 2 + max_msg_width = os.get_terminal_size()[0] - cat_width - 2 + if not wrap < max_msg_width: + raise ValueError("Wrap width exceeds maximum message width") + wrap = wrap if wrap else max_msg_width + msg = msg.replace("\n", " ") + msg_lines = [] + msg_words = msg.split(" ") + while msg_words: + line = "" + while msg_words and len(line) + len(msg_words[0]) + 1 <= wrap: + line += (msg_words.pop(0) + " ") + msg_lines.append(line.rstrip()) + if len(msg_lines) > max_msg_height: + raise ValueError(f"Message exceeds maximum height of {max_msg_height} given {wrap} character wrap") + longest_msg_line = max(len(line) for line in msg_lines) + msg_lines = [line.ljust(longest_msg_line) for line in msg_lines] + msg_lines = [box["joiner"] + " " + msg_lines.pop(0) + " " + box["vbar"]] + [box["vbar"] + " " + line + " " + box["vbar"] for line in msg_lines] + top_bar = box["corner_tl"] + box["hbar"] * (longest_msg_line + 2) + box["corner_tr"] + bottom_bar = box["corner_bl"] + box["hbar"] * (longest_msg_line + 2) + box["corner_br"] + msg_lines = [top_bar, *msg_lines, bottom_bar] + outcat_lines = [] + for i, line in enumerate(cat_lines): + box_line = "" + if i < len(msg_lines): + box_line = msg_lines[i] + outcat_lines.append(line + box_line) + return "\n".join(outcat_lines) + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/home/conf/xonsh/xonshrc b/home/conf/xonsh/xonshrc index 16940c8..9eebac2 100644 --- a/home/conf/xonsh/xonshrc +++ b/home/conf/xonsh/xonshrc @@ -1,6 +1,5 @@ if $XONSH_INTERACTIVE: from datetime import datetime - import os t0 = datetime.now() ## ENV ## $XONSH_COLOR_STYLE = 'native' @@ -45,11 +44,11 @@ aliases["ls"] = "exa" aliases["ll"] = "exa -lah" aliases["grep"] = "rg" aliases["theo"] = "python ~/.config/xonsh/theo.py" +aliases["kittycatsay"] = "python ~/.config/xonsh/kittycatsay.py" if $XONSH_INTERACTIVE: hour = t0.hour - $COWCOL = os.get_terminal_size()[0] - 6 - theo | cowsay -W $COWCOL -f ~/.config/xonsh/kiddycad.cow + theo | kittycatsay """ if 5 <= hour < 10: theo | cowsay -d