1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
|
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift open source project
//
// Copyright (c) 2025 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
import SWBLibc
final class TerminalAttributes {
#if !os(Windows)
private var term_attrs = termios()
#endif
fileprivate init() {
}
fileprivate func save() {
#if !os(Windows)
if tcgetattr(STDIN_FILENO, &term_attrs) == -1 {
// If we got an error here, just assume it is because the terminal wasn't capable.
return
}
#endif
}
fileprivate func restore() {
#if !os(Windows)
// Ignore failures, there isn't anything we can do.
tcsetattr(STDIN_FILENO, TCSAFLUSH, &term_attrs)
#endif
}
func disableEcho() {
#if !os(Windows)
// Get the current terminal attributes.
var attrs = termios()
if tcgetattr(STDIN_FILENO, &attrs) == -1 {
// If we got an error here, just assume it is because the terminal wasn't capable.
return
}
// Clear the echo flag and update the attributes.
attrs.c_lflag &= ~tcflag_t(ECHO)
if tcsetattr(STDIN_FILENO, TCSAFLUSH, &attrs) == -1 {
perror("tcsetattr")
return
}
#endif
}
}
/// Save the active terminal attributes before executing `block` and restore them afterwards.
func withTerminalAttributes<T>(_ block: (TerminalAttributes) async throws -> T) async throws -> T {
let terminalAttributes = TerminalAttributes()
terminalAttributes.save()
defer { terminalAttributes.restore() }
return try await block(terminalAttributes)
}
|