You'll need to adjust with the terminal line discipline (termios) to turn off buffering and give you each character as it's typed. You'll also probably want to turn off terminal echo.
// You said no frameworks. But I'm guessing you'll accept libc.
import Darwin.libc
// Fetch the terminal settings
var term = termios()
tcgetattr(STDIN_FILENO, &term)
// Save them if you need to restore them later
var savedTerm = term
// Turn off canonical input (buffered) and echo
term.c_lflag &= ~(UInt(ICANON) | UInt(ECHO))
// Set the terminal settings immediately
tcsetattr(STDIN_FILENO, TCSANOW, &term)
// Now you can read a character directly
let c = getchar()
// It's an Int32 Unicode code point, so you may want to convert
// it to something more useful
if let input = UnicodeScalar(Int(c)) {
print("Got \(input)")
}
// Restore the settings if you need to. Most shells will do this automatically
tcgetattr(STDIN_FILENO, &savedTerm)