import String from "String" type HandlerId = HandlerId export type HandlerId /** * Clears the current terminal line. * * @since 0.26.3 */ clearLine :: {} -> String export clearLine = () => "\x1b[2K\r" /** * Moves the terminal cursor up by the provided number of lines. * * @since 0.26.3 */ moveCursorUp :: Integer -> String export moveCursorUp = (lines) => `\x1b[${show(lines)}A` /** * Clears from the cursor position to the end of the screen. * * @since 0.26.3 */ clearToEndOfScreen :: {} -> String export clearToEndOfScreen = () => "\x1b[J" /** * Hides the terminal cursor. * * @since 0.26.3 */ hideCursor :: {} -> String export hideCursor = () => "\x1b[?25l" /** * Shows the terminal cursor. * * @since 0.26.3 */ showCursor :: {} -> String export showCursor = () => "\x1b[?25h" END_COLOR = "\x1b[0m" colorize :: String -> String -> String colorize = (color, v) => color ++ v ++ END_COLOR // via https://en.wikipedia.org/wiki/ANSI_escape_code /** * Ansi styles to be used with the ansiColor function. * * @since 0.11.0 */ export ansi = { FGBlack: "30", FGRed: "31", FGGreen: "32", FGYellow: "33", FGBlue: "34", FGMagenta: "35", FGCyan: "36", FGWhite: "37", FGBrightBlack: "90", FGBrightRed: "91", FGBrightGreen: "92", FGBrightYellow: "93", FGBrightBlue: "94", FGBrightMagenta: "95", FGBrightCyan: "96", FGBrightWhite: "97", BGBlack: "40", BGRed: "41", BGGreen: "42", BGYellow: "43", BGBlue: "44", BGMagenta: "45", BGCyan: "46", BGWhite: "47", BGBrightBlack: "100", BGBrightRed: "101", BGBrightGreen: "102", BGBrightYellow: "103", BGBrightBlue: "104", BGBrightMagenta: "105", BGBrightCyan: "106", BGBrightWhite: "107", FormatUnderline: "4", FormatNoUnderline: "24", FormatBold: "1", FormatNoBold: "21", FormatInvert: "7", } /** * Adds ansi escape codes to a string given a list of styles. * * @since 0.11.0 * @example * ansiColor([ansi.FormatBold, ansi.FGBrightRed], "will be red and bold") */ ansiColor :: List String -> String -> String export ansiColor = (parts, str) => colorize( `\x1b[${String.join(";", parts)}m`, str ) export text = { black: ansiColor([ansi.FGBlack]), red: ansiColor([ansi.FGRed]), green: ansiColor([ansi.FGGreen]), yellow: ansiColor([ansi.FGYellow]), blue: ansiColor([ansi.FGBlue]), magenta: ansiColor([ansi.FGMagenta]), cyan: ansiColor([ansi.FGCyan]), white: ansiColor([ansi.FGWhite]), brightBlack: ansiColor([ansi.FGBrightBlack]), brightRed: ansiColor([ansi.FGBrightRed]), brightGreen: ansiColor([ansi.FGBrightGreen]), brightYellow: ansiColor([ansi.FGBrightYellow]), brightBlue: ansiColor([ansi.FGBrightBlue]), brightMagenta: ansiColor([ansi.FGBrightMagenta]), brightCyan: ansiColor([ansi.FGBrightCyan]), brightWhite: ansiColor([ansi.FGBrightWhite]), underline: ansiColor([ansi.FormatUnderline]), bold: ansiColor([ansi.FormatBold]), boldUnderline: ansiColor([ansi.FormatBold, ansi.FormatUnderline]), } export dark = { black: ansiColor([ansi.FGBlack, ansi.BGBlack]), red: ansiColor([ansi.FGRed, ansi.BGBlack]), green: ansiColor([ansi.FGGreen, ansi.BGBlack]), yellow: ansiColor([ansi.FGYellow, ansi.BGBlack]), blue: ansiColor([ansi.FGBlue, ansi.BGBlack]), magenta: ansiColor([ansi.FGMagenta, ansi.BGBlack]), cyan: ansiColor([ansi.FGCyan, ansi.BGBlack]), white: ansiColor([ansi.FGWhite, ansi.BGBlack]), } export light = { black: ansiColor([ansi.FGBrightBlack, ansi.BGWhite]), red: ansiColor([ansi.FGBrightRed, ansi.BGWhite]), green: ansiColor([ansi.FGBrightGreen, ansi.BGWhite]), yellow: ansiColor([ansi.FGBrightYellow, ansi.BGWhite]), blue: ansiColor([ansi.FGBrightBlue, ansi.BGWhite]), magenta: ansiColor([ansi.FGBrightMagenta, ansi.BGWhite]), cyan: ansiColor([ansi.FGBrightCyan, ansi.BGWhite]), white: ansiColor([ansi.FGBrightWhite, ansi.BGWhite]), } type TTYMode = NormalMode | RawMode #iftarget llvm enableTTYRawMode :: {} -> {} export enableTTYRawMode = extern "madlib__stdio__enableTTYRawMode" disableTTYRawMode :: {} -> {} export disableTTYRawMode = extern "madlib__stdio__disableTTYRawMode" onKeyPressed :: (String -> {}) -> HandlerId export onKeyPressed = extern "madlib__stdio__onKeyPressed" clearKeyPressedHandler :: HandlerId -> {} export clearKeyPressedHandler = extern "madlib__stdio__clearKeyPressHandler" getWindowSizeFFI :: {} -> List Integer getWindowSizeFFI = extern "madlib__stdio__getWindowSize" getWindowSize :: {} -> #[Integer, Integer] export getWindowSize = () => where(getWindowSizeFFI()) { [c, r] => #[c, r] _ => #[0, 0] } getTTYModeFFI :: {} -> Integer getTTYModeFFI = extern "madlib__stdio__getTTYMode" getTTYMode :: {} -> TTYMode export getTTYMode = () => getTTYModeFFI() == 0 ? NormalMode : RawMode isTTY :: {} -> Boolean export isTTY = extern "madlib__stdio__isTTY" onWindowResizedFFI :: ({} -> {}) -> HandlerId onWindowResizedFFI = extern "madlib__stdio__onWindowResized" onWindowResized :: (#[Integer, Integer] -> {}) -> HandlerId export onWindowResized = (cb) => onWindowResizedFFI(() => { cb(getWindowSize()) }) clearWindowResizeHandler :: HandlerId -> {} export clearWindowResizeHandler = extern "madlib__stdio__clearWindowResizeHandler" #elseif js #- {Node} import prelude_terminal_readline from "readline" {/Node} -# #- let readLineInterface = null -# enableTTYRawMode :: {} -> {} export enableTTYRawMode = () => #- { if (process.stdin.isTTY) { readLineInterface = prelude_terminal_readline.createInterface({ input: process.stdin }) prelude_terminal_readline.emitKeypressEvents(process.stdin, readLineInterface) process.stdin.setRawMode(true) } } -# disableTTYRawMode :: {} -> {} export disableTTYRawMode = () => #- { if (process.stdin.isTTY) { process.stdin.setRawMode(false) if (readLineInterface) { readLineInterface.close() readLineInterface = null } } } -# onKeyPressed :: (String -> {}) -> HandlerId export onKeyPressed = (cb) => #- { function keyPressHandle(_, key) { cb(key.sequence); } process.stdin.on("keypress", keyPressHandle) return keyPressHandle; } -# clearKeyPressedHandler :: HandlerId -> {} export clearKeyPressedHandler = (id) => #- { process.stdin.off("keypress", id) } -# getWindowSize :: {} -> #[Integer, Integer] export getWindowSize = () => #[ #- process.stdout.columns -#, #- process.stdout.rows -#, ] getTTYMode :: {} -> TTYMode export getTTYMode = () => #- { if (process.stdin.isRaw) { return { __constructor: "RawMode", __a: 0 } } return { __constructor: "NormalMode", __a: 0 } } -# isTTY :: {} -> Boolean export isTTY = () => #- { return !!(process.stdout && process.stdout.isTTY) } -# _onWindowResized :: ({} -> #[Integer, Integer]) -> (#[Integer, Integer] -> {}) -> HandlerId export _onWindowResized = (_getWindowSize, cb) => #- { function windowResizeHandle() { cb(_getWindowSize()) } process.on('SIGWINCH', windowResizeHandle) return windowResizeHandle } -# onWindowResized :: (#[Integer, Integer] -> {}) -> HandlerId export onWindowResized = _onWindowResized(getWindowSize) clearWindowResizeHandler :: HandlerId -> {} export clearWindowResizeHandler = (id) => #- { process.off('SIGWINCH', id) } -# #endif