Last active
May 28, 2024 17:29
-
-
Save dduan/272d8c20bb6521695bd04e290b489774 to your computer and use it in GitHub Desktop.
Put terminal in raw mode, clear the screen, run some code. Reset the terminal to original mode when the code finish running.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#if canImport(Darwin) | |
import Darwin | |
#else | |
import Glibc | |
#endif | |
enum RawModeError: Error { | |
case notATerminal | |
case failedToGetTerminalSetting | |
case failedToSetTerminalSetting | |
} | |
func runInRawMode(_ task: @escaping () throws -> Void) throws { | |
var originalTermSetting = termios() | |
guard isatty(STDIN_FILENO) != 0 else { | |
throw RawModeError.notATerminal | |
} | |
guard tcgetattr(STDIN_FILENO, &originalTermSetting) >= 0 else { | |
throw RawModeError.failedToGetTerminalSetting | |
} | |
var raw = originalTermSetting | |
raw.c_iflag &= ~(UInt(BRKINT) | UInt(ICRNL) | UInt(INPCK) | UInt(ISTRIP) | UInt(IXON)) | |
raw.c_oflag &= ~(UInt(OPOST)) | |
raw.c_cflag |= UInt(CS8) | |
raw.c_lflag &= ~(UInt(ECHO) | UInt(ICANON) | UInt(IEXTEN) | UInt(ISIG)) | |
raw.c_cc.16 = 0 | |
raw.c_cc.17 = 1 | |
guard tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw) >= 0 else { | |
throw RawModeError.failedToSetTerminalSetting | |
} | |
defer { | |
tcsetattr(STDIN_FILENO, TCSAFLUSH, &originalTermSetting) | |
} | |
print("\u{1b}[2J") | |
try task() | |
} | |
// Example usage: run a loop until 'q' is pressed | |
let q = Character("q").asciiValue! | |
try runInRawMode { | |
while true { | |
var char: UInt8 = 0 | |
read(STDIN_FILENO, &char, 1) | |
if char == q { | |
exit(0) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment