///|
fn preferred_dir_path(home : String) -> String {
@path.Path::join(home, ".moon-mini").to_string()
}
///|
fn preferred_file_path(home : String) -> String {
@path.Path::join(preferred_dir_path(home), "preferred.txt").to_string()
}
///|
priv struct PreferredConfig {
username : String?
license : String?
host : String?
preferred_target : String?
}
///|
priv enum PreferredKey {
UsernameField
LicenseField
HostField
TargetField
}
///|
priv struct PreferredEntry {
key : PreferredKey
value : String
}
///|
fn PreferredConfig::empty() -> PreferredConfig {
{ username: None, license: None, host: None, preferred_target: None }
}
///|
fn PreferredKey::name(self : PreferredKey) -> String {
match self {
UsernameField => "username"
LicenseField => "license"
HostField => "host"
TargetField => "target"
}
}
///|
fn parse_preferred_value(line : String, key : PreferredKey) -> String? {
let key_name = key.name()
let prefix = "\{key_name} "
guard line.has_prefix(prefix) else { None }
let value = line.view(start_offset=prefix.length()).trim().to_owned()
guard !value.is_empty() else { None }
Some(value)
}
///|
fn parse_preferred_entry(line : String) -> PreferredEntry? {
for key in [UsernameField, LicenseField, HostField, TargetField] {
guard parse_preferred_value(line, key) is Some(value) else { continue }
return Some({ key, value })
}
None
}
///|
fn PreferredConfig::apply_entry(
self : PreferredConfig,
entry : PreferredEntry,
) -> PreferredConfig {
match entry.key {
UsernameField => { ..self, username: Some(entry.value) }
LicenseField => { ..self, license: Some(entry.value) }
HostField => { ..self, host: Some(entry.value) }
TargetField => { ..self, preferred_target: Some(entry.value) }
}
}
///|
fn PreferredConfig::parse(content : String) -> PreferredConfig {
let mut preferred = PreferredConfig::empty()
for raw_line in content.split("\n") {
let line = raw_line.trim().to_owned()
guard !line.is_empty() else { continue }
guard parse_preferred_entry(line) is Some(entry) else { continue }
preferred = preferred.apply_entry(entry)
}
preferred
}
///|
fn PreferredConfig::to_content(self : PreferredConfig) -> String {
let lines : Array[String] = []
push_preferred_line(lines, UsernameField, self.username)
push_preferred_line(lines, LicenseField, self.license)
push_preferred_line(lines, HostField, self.host)
push_preferred_line(lines, TargetField, self.preferred_target)
lines.join("\n")
}
///|
fn push_preferred_line(
lines : Array[String],
key : PreferredKey,
value : String?,
) -> Unit {
if value is Some(value) {
lines.push("\{key.name()} \{value}")
}
}
///|
async fn load_preferred_config(
preferred_file : String,
) -> PreferredConfig raise CliError {
guard path_exists(preferred_file) else { PreferredConfig::empty() }
try @fs.read_file(preferred_file) catch {
err =>
raise CliError(
"failed to read preferences \{preferred_file}: \{Repr(err)}",
)
} noraise {
content =>
try content.text() catch {
err =>
raise CliError(
"failed to decode preferences \{preferred_file}: \{Repr(err)}",
)
} noraise {
text => PreferredConfig::parse(text)
}
}
}
///|
async fn save_preferred_config(
preferred_file : String,
preferred : PreferredConfig,
) -> Unit raise CliError {
write_or_truncate_string_file(preferred_file, preferred.to_content())
}