ui.ts 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. import { z } from "zod"
  2. import { NamedError } from "../util/error"
  3. export namespace UI {
  4. const LOGO = [
  5. `█▀▀█ █▀▀█ █▀▀ █▀▀▄ █▀▀ █▀▀█ █▀▀▄ █▀▀`,
  6. `█░░█ █░░█ █▀▀ █░░█ █░░ █░░█ █░░█ █▀▀`,
  7. `▀▀▀▀ █▀▀▀ ▀▀▀ ▀ ▀ ▀▀▀ ▀▀▀▀ ▀▀▀ ▀▀▀`,
  8. ]
  9. export const CancelledError = NamedError.create("UICancelledError", z.void())
  10. export const Style = {
  11. TEXT_HIGHLIGHT: "\x1b[96m",
  12. TEXT_HIGHLIGHT_BOLD: "\x1b[96m\x1b[1m",
  13. TEXT_DIM: "\x1b[90m",
  14. TEXT_DIM_BOLD: "\x1b[90m\x1b[1m",
  15. TEXT_NORMAL: "\x1b[0m",
  16. TEXT_NORMAL_BOLD: "\x1b[1m",
  17. TEXT_WARNING: "\x1b[93m",
  18. TEXT_WARNING_BOLD: "\x1b[93m\x1b[1m",
  19. TEXT_DANGER: "\x1b[91m",
  20. TEXT_DANGER_BOLD: "\x1b[91m\x1b[1m",
  21. TEXT_SUCCESS: "\x1b[92m",
  22. TEXT_SUCCESS_BOLD: "\x1b[92m\x1b[1m",
  23. TEXT_INFO: "\x1b[94m",
  24. TEXT_INFO_BOLD: "\x1b[94m\x1b[1m",
  25. }
  26. export function println(...message: string[]) {
  27. print(...message)
  28. Bun.stderr.write("\n")
  29. }
  30. export function print(...message: string[]) {
  31. blank = false
  32. Bun.stderr.write(message.join(" "))
  33. }
  34. let blank = false
  35. export function empty() {
  36. if (blank) return
  37. println("" + Style.TEXT_NORMAL)
  38. blank = true
  39. }
  40. export function logo() {
  41. empty()
  42. for (const row of LOGO) {
  43. print(" ")
  44. for (let i = 0; i < row.length; i++) {
  45. const color =
  46. i > 18 ? Bun.color("white", "ansi") : Bun.color("gray", "ansi")
  47. const char = row[i]
  48. print(color + char)
  49. }
  50. println()
  51. }
  52. empty()
  53. }
  54. export async function input(prompt: string): Promise<string> {
  55. const readline = require("readline")
  56. const rl = readline.createInterface({
  57. input: process.stdin,
  58. output: process.stdout,
  59. })
  60. return new Promise((resolve) => {
  61. rl.question(prompt, (answer: string) => {
  62. rl.close()
  63. resolve(answer.trim())
  64. })
  65. })
  66. }
  67. }