//
// RGBSimpleTextIO.swit
//
// Created by coti on 25/3/16.
// This is a list of functions that simplify reading from
// and writing to the Swift console.
// Last updated 30-01-2018 (headerdoc added)
// Last updated 11-10-2018
// Last updated 11-10-2019 (Suppressed deprecated enum)
//
import Foundation
//MARK: Read numbers with prompt, no min or max specific limits
/// Read an Int with the given prompt
///
/// - Parameter p: The prompt to be shown
/// - Returns: An Int value
public func readIntWithPrompt(_ p:String = "") -> Int {
repeat {
print(p, terminator: "")
if let temp = readLine(),
let number = Int(temp) {
return number
}
} while true
}
/// Read a Float with the given prompt
///
/// - Parameter p: The prompt to be shown
/// - Returns: A Float value
public func readFloatWithPrompt(_ p:String = "") -> Float {
repeat {
print(p, terminator: "")
if let temp = readLine(),
let number = Float(temp) {
return number
}
} while true
}
/// Read a Double with the given prompt
///
/// - Parameter p: The prompt to be shown
/// - Returns: A Double value
public func readDoubleWithPrompt(_ p:String = "") -> Double {
repeat {
print(p, terminator: "")
if let temp = readLine(),
let number = Double(temp) {
return number
}
} while true
}
//MARK: Read numbers with prompt, with min and max specific limits
/// Read an Int with the given prompt, must be within minValue and maxValue
///
/// - Parameters:
/// - p: The prompt to be shown
/// - minValue: the minimum acceptable value
/// - maxValue: the maximum acceptable value
/// - Returns: An Int value
public func readIntWithPrompt(_ p:String = "", minValue:Int?, maxValue:Int?) -> Int {
guard
let min = minValue,
let max = maxValue,
min <= max
else {
writeMessageToError("\nInterval is not valid\n")
fatalError()
}
let limits = "[\(min), \(max)] "
repeat {
let number = readIntWithPrompt(p + limits)
if number >= min && number <= max {
return number
} else {
print("\nPlease enter a value in the range" + limits + "\n")
}
} while true
}
/// Read a Float with the given prompt, must be within minValue and maxValue
///
/// - Parameters:
/// - p: The prompt to be shown
/// - minValue: the minimum acceptable value
/// - maxValue: the maximum acceptable value
/// - Returns: A Float value
public func readFloatWithPrompt(_ p:String = "", minValue:Float?, maxValue:Float?) -> Float {
guard
let min = minValue,
let max = maxValue,
min <= max
else {
writeMessageToError("\nInterval is not valid\n")
fatalError()
}
let limits = "[\(min), \(max)] "
repeat {
let number = readFloatWithPrompt( p + limits)
if number >= min && number <= max {
return number
} else {
print("\nPlease enter a value in the range" + limits + "\n")
}
} while true
}
/// Read a Double with the given prompt, must be within minValue and maxValue
///
/// - Parameters:
/// - p: The prompt to be shown
/// - minValue: the minimum acceptable value
/// - maxValue: the maximum acceptable value
/// - Returns: A Double value
func readDoubleWithPrompt(_ p:String = "", minValue:Double?, maxValue:Double?) -> Double {
guard
let min = minValue,
let max = maxValue,
min <= max
else {
writeMessageToError("\nInterval is not valid\n")
fatalError()
}
let limits = "[\(min), \(max)] "
repeat {
let number = readDoubleWithPrompt(p + limits)
if number >= min && number <= max {
return number
} else {
print("\nPlease enter a value in the range" + limits + "\n")
}
} while true
}
//MARK: Read string with prompt
/// Read an String with the given prompt
///
/// - Parameter p: The prompt to be shown
/// - Returns: The value of the String entered by the user
public func readStringWithPrompt(_ p:String = "") -> String {
repeat {
print("\(p)", terminator:"")
if let x = readLine(strippingNewline: true) {
return x
}
} while true
}
/// Read a String with the given prompt, must not be empty
///
/// - Parameter p: The prompt to be shown
/// - Returns: The NON-EMPTY value of the String entered by the user
public func readNonEmptyStringWithPrompt(_ p:String = "") -> String {
repeat {
print("\(p)", terminator:"")
if let x = readLine(strippingNewline: true),
!x.isEmpty {
return x
}
} while true
}
/// Read an option (String) with the given prompt, must be within the given list of options
///
/// - Parameters:
/// - prompt: The prompt to be shown
/// - options: The list of options to be shown in the menu
/// - Returns: A String that will be one of the options
public func readOption(withPrompt prompt:String,
fromOptions options:[String]) -> String {
var option = ""
repeat {
option = readNonEmptyStringWithPrompt(prompt)
} while !options.contains(option.uppercased())
return option
}
/// Read a list of String with prompt; type ENTER to finish
/// Read an String with the given prompt
///
/// - Parameter p: The prompt to be shown
/// - Returns: The list of strings entered by the user, item by item.
public func readListOfStringsWithPrompt(_ p:String) -> [String] {
print("\(p) [ENTER to finish]\n\n")
var result = [String]()
repeat {
let x = readStringWithPrompt("Enter string: ")
if x.isEmpty {
return result
}
result.append(x)
} while true
}
//MARK: Write message in black to stdout or red to stderr
/// Write a message (black)
/// Show an String in black on white
///
/// - Parameter message: The message to be shown in black on white
/// - Returns: Nothing
public func writeMessage(_ message: String) {
print("\u{001B}[;m\(message)")
}
/// Write a message (red)
/// Show an String in red on white
///
/// - Parameter message: The message to be shown in red on white
/// - Returns: Nothing
public func writeMessageToError(_ message: String) {
fputs("\u{001B}[0;31m\(message)\u{001B}[;m\n", stderr)
}
/// Ask the user whether he wants to exit or not
///
/// - Returns: true if user enters YySsJj, false otherwise
func askIfWeExitOrNot() -> Bool {
let op = ["Y", "y", "S", "s", "j", "J", "n", "N"]
let p = "\nDo you really want to exit the program? " + "\n\n[\("SYJN")] : "
let tmp = readOption(withPrompt: p, fromOptions: op)
return tmp.uppercased() != "N"
} //End of askIfWeExitOrNot