@@ -445,6 +445,12 @@ private func promptAnswer(for step: WizardStep) throws -> Any {
|
445 | 445 | case "text": |
446 | 446 | let initial = anyCodableString(step.initialvalue) |
447 | 447 | let prompt = step.placeholder ?? "Value" |
| 448 | +if step.sensitive == true { |
| 449 | +let sensitivePrompt = initial.isEmpty ? prompt : "\(prompt) (leave blank to keep existing)" |
| 450 | +let value = try readSensitiveLineWithPrompt(sensitivePrompt) |
| 451 | +let trimmed = value.trimmingCharacters(in: .whitespacesAndNewlines) |
| 452 | +return trimmed.isEmpty ? initial : trimmed |
| 453 | +} |
448 | 454 | let value = try readLineWithPrompt("\(prompt)\(initial.isEmpty ? "" : " [\(initial)]")") |
449 | 455 | let trimmed = value.trimmingCharacters(in: .whitespacesAndNewlines) |
450 | 456 | return trimmed.isEmpty ? initial : trimmed |
@@ -524,3 +530,28 @@ private func readLineWithPrompt(_ prompt: String) throws -> String {
|
524 | 530 | } |
525 | 531 | return line |
526 | 532 | } |
| 533 | + |
| 534 | +private func readSensitiveLineWithPrompt(_ prompt: String) throws -> String { |
| 535 | +print("\(prompt): ", terminator: "") |
| 536 | +fflush(stdout) |
| 537 | + |
| 538 | +var original = termios() |
| 539 | +guard tcgetattr(STDIN_FILENO, &original) == 0 else { |
| 540 | +throw WizardCliError.gatewayError("Could not configure hidden terminal input.") |
| 541 | +} |
| 542 | + |
| 543 | +var hidden = original |
| 544 | + hidden.c_lflag &= ~tcflag_t(ECHO) |
| 545 | +guard tcsetattr(STDIN_FILENO, TCSANOW, &hidden) == 0 else { |
| 546 | +throw WizardCliError.gatewayError("Could not configure hidden terminal input.") |
| 547 | +} |
| 548 | +defer { |
| 549 | + _ = tcsetattr(STDIN_FILENO, TCSANOW, &original) |
| 550 | +print("") |
| 551 | +} |
| 552 | + |
| 553 | +guard let line = readLine() else { |
| 554 | +throw WizardCliError.cancelled |
| 555 | +} |
| 556 | +return line |
| 557 | +} |