From a081f0b4e3304f905295d16cf260eb101025254e Mon Sep 17 00:00:00 2001 From: Bauke Date: Fri, 9 Dec 2022 12:26:08 +0100 Subject: [PATCH] Rewrite scripts in Deno and move to $BAUKE_DIR. --- .bauke/.vscode/settings.json | 6 + .bauke/bin/codium-extensions | 10 ++ .bauke/bin/project-avatar | 8 ++ .bauke/bin/simple-git-push | 6 + .bauke/bin/tauon-controls | 6 + .../data}/codium-extensions.txt | 1 + .bauke/scripts/codium-extensions.ts | 65 +++++++++ .bauke/scripts/project-avatar.ts | 107 ++++++++++++++ .bauke/scripts/simple-git-push.ts | 46 ++++++ .bauke/scripts/tauon-controls.ts | 38 +++++ .bauke/scripts/utilities.ts | 8 ++ .local/bin/codium-extensions | 62 -------- .local/bin/project-avatar | 132 ------------------ .local/bin/simple-git-push | 43 ------ .local/bin/tauon-controls | 35 ----- .profile | 2 + .zshrc | 15 +- 17 files changed, 307 insertions(+), 283 deletions(-) create mode 100644 .bauke/.vscode/settings.json create mode 100755 .bauke/bin/codium-extensions create mode 100755 .bauke/bin/project-avatar create mode 100755 .bauke/bin/simple-git-push create mode 100755 .bauke/bin/tauon-controls rename {.config => .bauke/data}/codium-extensions.txt (92%) create mode 100644 .bauke/scripts/codium-extensions.ts create mode 100644 .bauke/scripts/project-avatar.ts create mode 100644 .bauke/scripts/simple-git-push.ts create mode 100644 .bauke/scripts/tauon-controls.ts create mode 100644 .bauke/scripts/utilities.ts delete mode 100755 .local/bin/codium-extensions delete mode 100755 .local/bin/project-avatar delete mode 100755 .local/bin/simple-git-push delete mode 100755 .local/bin/tauon-controls diff --git a/.bauke/.vscode/settings.json b/.bauke/.vscode/settings.json new file mode 100644 index 0000000..c5d71f6 --- /dev/null +++ b/.bauke/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "deno.enable": true, + "[typescript]": { + "editor.defaultFormatter": "denoland.vscode-deno" + } +} diff --git a/.bauke/bin/codium-extensions b/.bauke/bin/codium-extensions new file mode 100755 index 0000000..7561588 --- /dev/null +++ b/.bauke/bin/codium-extensions @@ -0,0 +1,10 @@ +#!/usr/bin/env zsh + +codium_extensions_file="$BAUKE_DIR/data/codium-extensions.txt" + +deno run \ + --allow-read="$codium_extensions_file" \ + --allow-run="codium" \ + --allow-write="$codium_extensions_file" \ + "$BAUKE_DIR/scripts/codium-extensions.ts" \ + "$@" diff --git a/.bauke/bin/project-avatar b/.bauke/bin/project-avatar new file mode 100755 index 0000000..ec3ff08 --- /dev/null +++ b/.bauke/bin/project-avatar @@ -0,0 +1,8 @@ +#!/usr/bin/env zsh + +deno run \ + --allow-run="convert,gegl,mat2" \ + --allow-read \ + --allow-write \ + "$BAUKE_DIR/scripts/project-avatar.ts" \ + "$@" diff --git a/.bauke/bin/simple-git-push b/.bauke/bin/simple-git-push new file mode 100755 index 0000000..a803f2f --- /dev/null +++ b/.bauke/bin/simple-git-push @@ -0,0 +1,6 @@ +#!/usr/bin/env zsh + +deno run \ + --allow-run="git" \ + "$BAUKE_DIR/scripts/simple-git-push.ts" \ + "$@" diff --git a/.bauke/bin/tauon-controls b/.bauke/bin/tauon-controls new file mode 100755 index 0000000..576a0db --- /dev/null +++ b/.bauke/bin/tauon-controls @@ -0,0 +1,6 @@ +#!/usr/bin/env zsh + +deno run \ + --allow-net="127.0.0.1:7813,127.0.0.1:7814" \ + "$BAUKE_DIR/scripts/tauon-controls.ts" \ + "$@" diff --git a/.config/codium-extensions.txt b/.bauke/data/codium-extensions.txt similarity index 92% rename from .config/codium-extensions.txt rename to .bauke/data/codium-extensions.txt index d5defc5..bcc4337 100644 --- a/.config/codium-extensions.txt +++ b/.bauke/data/codium-extensions.txt @@ -1,4 +1,5 @@ brunnerh.insert-unicode +denoland.vscode-deno Holllo.love jock.svg ritwickdey.LiveServer diff --git a/.bauke/scripts/codium-extensions.ts b/.bauke/scripts/codium-extensions.ts new file mode 100644 index 0000000..3da5c14 --- /dev/null +++ b/.bauke/scripts/codium-extensions.ts @@ -0,0 +1,65 @@ +import { Command } from "https://deno.land/x/cliffy@v0.25.5/command/mod.ts"; + +import { runAndReturnStdout } from "./utilities.ts"; + +async function main(): Promise { + const { options } = await new Command() + .name("codium-extensions") + .description("Small managing utility for VS Codium extensions!") + .option( + "-f, --file ", + "The file to use for storing data.", + { + default: + new URL("../data/codium-extensions.txt", import.meta.url).pathname, + }, + ) + .option("--install", "Install saved extensions.") + .option("--list", "List installed extensions.") + .option("--list-saved", "List saved extensions.") + .option("--save", "Save installed extensions.") + .parse(Deno.args); + + if (options.install) { + const extensions = await getSavedExtensions(options.file); + const process = Deno.run({ + cmd: [ + "codium", + ...extensions.flatMap((id) => ["--install-extension", id]), + ], + }); + await process.status(); + } + + if (options.list) { + const extensions = await getInstalledExtensions(); + console.log(extensions.join("\n")); + } + + if (options.listSaved) { + const extensions = await getSavedExtensions(options.file); + console.log(extensions.join("\n")); + } + + if (options.save) { + const extensions = await getInstalledExtensions(); + await Deno.writeTextFile(options.file, extensions.join("\n") + "\n"); + console.log(`Wrote ${extensions.length} extensions to ${options.file}`); + } +} + +async function getInstalledExtensions(): Promise { + const extensions = await runAndReturnStdout({ + cmd: ["codium", "--list-extensions"], + }); + return extensions.trim().split("\n"); +} + +async function getSavedExtensions(file: string): Promise { + const extensions = await Deno.readTextFile(file); + return extensions.trim().split("\n"); +} + +if (import.meta.main) { + void main(); +} diff --git a/.bauke/scripts/project-avatar.ts b/.bauke/scripts/project-avatar.ts new file mode 100644 index 0000000..3080c81 --- /dev/null +++ b/.bauke/scripts/project-avatar.ts @@ -0,0 +1,107 @@ +import { Command } from "https://deno.land/x/cliffy@v0.25.5/command/mod.ts"; +import { existsSync } from "https://deno.land/std@0.167.0/node/fs.ts"; + +async function main(): Promise { + const { args, options } = await new Command() + .name("project-avatar") + .description("Project Avatar Generator") + .arguments(" ") + .option("--width ", "The width of the image.", { + default: 256, + }) + .option("--height ", "The height of the image.", { + default: 256, + }) + .option("--font-size ", "Font size for the text.", { + default: 150, + }) + .option("--overwrite", "Overwrite an existing image.") + .option("--clean", "Use MAT2 to clean the image.") + .parse(Deno.args); + + const [file, text] = args; + + if (existsSync(file)) { + if (options.overwrite) { + await Deno.remove(file); + } else { + console.log("File exists, use --overwrite to overwrite."); + Deno.exit(1); + } + } + + await Deno.run({ + cmd: [ + "gegl", + "-o", + file, + "--", + ...geglGraph({ + fontSize: options.fontSize, + height: options.height, + text, + width: options.width, + }), + ], + }).status(); + + if (!existsSync(file)) { + console.log("Something went wrong with GEGL."); + Deno.exit(1); + } + + await Deno.run({ + cmd: [ + "convert", + file, + "-background", + "transparent", + "-gravity", + "center", + "-extent", + `${options.width}x${options.height}`, + file, + ], + }).status(); + + if (options.clean) { + await Deno.run({ cmd: ["mat2", "--inplace", file] }).status(); + } +} + +type GraphOptions = { + fontSize: number; + height: number; + text: string; + width: number; +}; + +function geglGraph({ fontSize, height, text, width }: GraphOptions): string[] { + const graph = ` + gegl:text + string=${text} + width=${width} + height=${height} + color=white + font=Inter Heavy + size=${fontSize} + alignment=1 + vertical-alignment=1 + gegl:dropshadow + x=0 + y=0 + color=black + opacity=1 + grow-radius=4 + radius=0 + gegl:long-shadow + angle=90 + color=black + length=20`; + + return graph.replace(/\s\s+/g, "\n").trim().split("\n"); +} + +if (import.meta.main) { + void main(); +} diff --git a/.bauke/scripts/simple-git-push.ts b/.bauke/scripts/simple-git-push.ts new file mode 100644 index 0000000..cb986a5 --- /dev/null +++ b/.bauke/scripts/simple-git-push.ts @@ -0,0 +1,46 @@ +import { Command } from "https://deno.land/x/cliffy@v0.25.5/command/mod.ts"; + +import { runAndReturnStdout } from "./utilities.ts"; + +async function main(): Promise { + const { args } = await new Command() + .name("simple-git-push") + .description("Git push with some extra semantics.") + .arguments("[...args:string]") + .parse(Deno.args); + + const availableRemotes = await gitRemote(); + + if (availableRemotes.length === 0) { + console.log("No remotes found"); + Deno.exit(0); + } + + const remotesToPush = ["origin", "github"]; + for (const remote of availableRemotes) { + if (remotesToPush.includes(remote)) { + await gitPush(remote, args); + } + } +} + +async function gitPush(remote: string, args: string[]): Promise { + await Deno.run({ + cmd: [ + "git", + "push", + "--follow-tags", + remote, + ...args, + ], + }).status(); +} + +async function gitRemote(): Promise { + const output = await runAndReturnStdout({ cmd: ["git", "remote"] }); + return output.trim().split("\n").filter((remote) => remote.length > 0); +} + +if (import.meta.main) { + void main(); +} diff --git a/.bauke/scripts/tauon-controls.ts b/.bauke/scripts/tauon-controls.ts new file mode 100644 index 0000000..0d3b749 --- /dev/null +++ b/.bauke/scripts/tauon-controls.ts @@ -0,0 +1,38 @@ +import { Command } from "https://deno.land/x/cliffy@v0.25.5/command/mod.ts"; + +const hiddenApi = "http://127.0.0.1:7813"; +const remoteApi = "http://127.0.0.1:7814/api1"; + +async function main(): Promise { + const { options } = await new Command() + .name("tauon-controls") + .description("Small remote control CLI for Tauon Music Box!") + .option("--next-song", "Play the next song.") + .option("--play-pause", "Toggle play or pause.") + .option("--previous-song", "Play the previous song.") + .option( + "--volume ", + "Change the volume by a relative amount", + ) + .parse(Deno.args); + + if (options.nextSong) { + await fetch(`${remoteApi}/next`); + } + + if (options.playPause) { + await fetch(`${hiddenApi}/playpause/`); + } + + if (options.previousSong) { + await fetch(`${remoteApi}/back`); + } + + if (options.volume !== undefined) { + await fetch(`${remoteApi}/setvolumerel/${options.volume}`); + } +} + +if (import.meta.main) { + void main(); +} diff --git a/.bauke/scripts/utilities.ts b/.bauke/scripts/utilities.ts new file mode 100644 index 0000000..db2cd79 --- /dev/null +++ b/.bauke/scripts/utilities.ts @@ -0,0 +1,8 @@ +import { TextDecoder } from "https://deno.land/std@0.167.0/node/util.ts"; + +export async function runAndReturnStdout( + options: Deno.RunOptions, +): Promise { + const process = Deno.run({ stdout: "piped", ...options }); + return new TextDecoder().decode(await process.output()); +} diff --git a/.local/bin/codium-extensions b/.local/bin/codium-extensions deleted file mode 100755 index a471958..0000000 --- a/.local/bin/codium-extensions +++ /dev/null @@ -1,62 +0,0 @@ -#!/usr/bin/env python3 - -import argparse -import pathlib -import subprocess -import typing - - -def main() -> None: - parser = argparse.ArgumentParser(description="Small Tauon remote control CLI") - parser.add_argument( - "action", - choices=["install", "list", "list-saved", "save"], - help="Which action should be performed.", - ) - parser.add_argument( - "-f", - "--file", - help="Use a different file than $HOME/.config/codium-extensions.txt.", - default=pathlib.Path.home().joinpath(".config/codium-extensions.txt"), - ) - args = parser.parse_args() - - if args.action == "install": - print("Installing saved extensions") - for extension in get_saved_extensions(args.file): - subprocess.run(["codium", "--install-extension", extension]) - elif args.action == "list": - print("Listing installed extensions") - print("\n".join(get_installed_extensions())) - elif args.action == "list-saved": - with open(args.file, "r") as file: - print("Listing saved extensions") - print(file.read()) - elif args.action == "save": - with open(args.file, "w") as file: - extensions = get_installed_extensions() - file.writelines("\n".join(extensions)) - file.write("\n") - print(f"Wrote {len(extensions)} extensions to {args.file}") - - -def get_installed_extensions() -> typing.List[str]: - extensions = subprocess.run( - [ - "codium", - "--list-extensions", - ], - capture_output=True, - check=True, - encoding="utf8", - ) - return extensions.stdout.splitlines() - - -def get_saved_extensions(path: str) -> typing.List[str]: - with open(path, "r") as file: - return file.read().splitlines() - - -if __name__ == "__main__": - main() diff --git a/.local/bin/project-avatar b/.local/bin/project-avatar deleted file mode 100755 index d249d6a..0000000 --- a/.local/bin/project-avatar +++ /dev/null @@ -1,132 +0,0 @@ -#!/usr/bin/env python3 - -import argparse -import os -import re -import subprocess -import sys -import typing - - -def main() -> None: - parser = create_parser() - args = parser.parse_args() - - if os.path.isfile(args.filename): - if args.overwrite: - os.remove(args.filename) - else: - print("Target file already exists, use --overwrite to overwrite.") - sys.exit(1) - - subprocess.run( - [ - "gegl", - "-o", - args.filename, - "--", - *gegl_graph(args.height, args.width, args.text, args.font_size), - ], - check=True, - ) - - if not os.path.isfile(args.filename): - print("Something went wrong with GEGL") - sys.exit(1) - - subprocess.run( - [ - "convert", - args.filename, - "-background", - "transparent", - "-gravity", - "center", - "-extent", - f"{args.width}x{args.height}", - args.filename, - ], - check=True, - ) - - if args.clean: - subprocess.run( - [ - "mat2", - "--inplace", - args.filename, - ], - check=True, - ) - - -def create_parser() -> argparse.ArgumentParser: - parser = argparse.ArgumentParser(description="Project Avatar Generator") - parser.add_argument( - "filename", - help="The image filename to write to.", - ) - parser.add_argument( - "text", - help="The text for the project avatar.", - ) - parser.add_argument( - "--width", - help="The width of the image.", - type=int, - default=256, - ) - parser.add_argument( - "--height", - help="The height of the image.", - type=int, - default=256, - ) - parser.add_argument( - "--overwrite", - help="Overwrite an existing image.", - action="store_true", - ) - parser.add_argument( - "--clean", - help="Use MAT2 to clean the image.", - action="store_true", - ) - parser.add_argument( - "--font-size", - help="The font size to use for the text.", - type=int, - default=150, - ) - return parser - - -def gegl_graph(height: int, width: int, text: str, font_size: int) -> typing.List[str]: - graph = f""" - gegl:text - string={text} - width={width} - height={height} - color=white - font=Heavitas - size={font_size} - alignment=1 - vertical-alignment=1 - gegl:dropshadow - x=0 - y=0 - color=black - opacity=1 - grow-radius=4 - radius=0 - gegl:long-shadow - angle=90 - color=black - length=20 - """ - - return re.sub("\s\s+", "\n", graph).strip().splitlines() - - -if __name__ == "__main__": - main() diff --git a/.local/bin/simple-git-push b/.local/bin/simple-git-push deleted file mode 100755 index f2f72e0..0000000 --- a/.local/bin/simple-git-push +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env python3 - -import argparse -import subprocess -import sys -import typing - - -def main() -> None: - available_remotes = git_remote() - - if len(available_remotes) == 0: - print("No remotes found") - sys.exit(0) - - # Parse any extra arguments passed to use them in git_push, this way - # simple-git-push acts like an aliased command. - extra_args = argparse.ArgumentParser(add_help=False).parse_known_args()[1] - remotes_to_push = ["origin", "github"] - - for remote in available_remotes: - if remote in remotes_to_push: - git_push(remote, extra_args) - - -def git_remote() -> typing.List[str]: - """Run `git remote` and return found remote names.""" - - command = ["git", "remote"] - output = subprocess.run(command, capture_output=True, encoding="utf8") - return output.stdout.splitlines() - - -def git_push(remote: str, extra_args: typing.List[str]) -> None: - """Run `git push` for the given remote.""" - - command = ["git", "push", "--follow-tags", remote, *extra_args] - print(f"""Pushing: {" ".join(command)}""") - subprocess.run(command) - - -if __name__ == "__main__": - main() diff --git a/.local/bin/tauon-controls b/.local/bin/tauon-controls deleted file mode 100755 index b5666cc..0000000 --- a/.local/bin/tauon-controls +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env python3 - -import argparse -import requests - -HIDDEN_API = "http://0.0.0.0:7813" -REMOTE_API = "http://0.0.0.0:7814/api1" - - -def main() -> None: - parser = argparse.ArgumentParser(description="Small Tauon remote control CLI") - group = parser.add_mutually_exclusive_group(required=True) - group.add_argument("--next-song", action="store_true") - group.add_argument("--play-pause", action="store_true") - group.add_argument("--previous-song", action="store_true") - group.add_argument("--volume", type=int) - args = parser.parse_args() - - if args.next_song: - call_api(f"{REMOTE_API}/next") - if args.play_pause: - call_api(f"{HIDDEN_API}/playpause/") - if args.previous_song: - call_api(f"{REMOTE_API}/back") - if args.volume is not None: - call_api(f"{REMOTE_API}/setvolumerel/{args.volume}") - - -def call_api(endpoint: str) -> None: - response = requests.get(endpoint) - print(f"HTTP {response.status_code} ({endpoint})") - - -if __name__ == "__main__": - main() diff --git a/.profile b/.profile index 2927baf..a0d0ac9 100644 --- a/.profile +++ b/.profile @@ -1 +1,3 @@ +export BAUKE_DIR="$HOME/.bauke" +export PATH="$PATH:$BAUKE_DIR/bin" export PATH="$PATH:$HOME/.local/bin" diff --git a/.zshrc b/.zshrc index 654d5bb..d206fc5 100644 --- a/.zshrc +++ b/.zshrc @@ -1,26 +1,19 @@ source "$HOME/.oh-my-zsh/oh-my-zsh.sh" -export EDITOR=nano +export EDITOR="nano" export LESS="-F -X $LESS" +export BAUKE_DIR="$HOME/.bauke" export CARGO_BIN="$HOME/.cargo/bin" export LOCAL_BIN="$HOME/.local/bin" +export PNPM_HOME="$HOME/.local/share/pnpm" export PATH="$PATH:$CARGO_BIN" -export PATH="$PATH:$LOCAL_BIN" +export PATH="$PATH:$PNPM_HOME" source "$HOME/.aliases.zsh" source "$HOME/.functions.zsh" source "$HOME/.zle.zsh" -export NVS_HOME="$HOME/.local/share/nvs" -source "$NVS_HOME/nvs.sh" - -export PNPM_HOME="$HOME/.local/share/pnpm" -export PATH="$PATH:$PNPM_HOME" - -export DENO_INSTALL="$HOME/.deno" -export PATH="$PATH:$DENO_INSTALL/bin" - eval "$(register-python-argcomplete pipx)" eval "$(starship init zsh)"