#![allow(unused)]
use std::ffi::OsString;
use aopt::shell::get_complete_cli;
use aopt::shell::value::once_values;
use cote::prelude::*;
use cote::shell::shell::Complete;
use cote::shell::value::Values;
use cote::shell::CompletionManager;
pub const OS: [&str; 4] = ["HarmonyOS", "Windows", "Android", "MacOS"];
#[derive(Debug, Cote)]
#[cote(shellcomp)]
struct OperateSystem {
preserve_user: bool,
#[sub(scvalues)]
migrate: Option<Migrate>,
#[sub(scvalues)]
install: Option<Install>,
#[sub()]
update: Option<Update>,
}
#[derive(Debug, Cote)]
pub struct Migrate {
#[arg(scvalues = read_server_from_cfg())]
server: Option<String>,
#[pos()]
from: Option<String>,
#[pos()]
to: Option<String>,
}
#[derive(Debug, Cote)]
pub struct Install {
#[arg(scvalues = read_server_from_cfg())]
server: Option<String>,
#[pos(scvalues = OS)]
name: Option<String>,
}
#[derive(Debug, Cote)]
pub struct Update {
yes: bool,
only: bool,
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
if try_complete("sub_shell_completion").is_ok() {
return Ok(());
}
let _ = OperateSystem::parse_env()?;
Ok(())
}
pub fn try_complete(name: &str) -> Result<(), Box<dyn std::error::Error>> {
let cli = get_complete_cli()?;
if cli.write_stdout(name, name).is_ok() {
return Ok(());
}
cli.complete(|shell| {
let mut ctx = cli.get_context()?;
let mut parser = OperateSystem::into_parser()?;
let mut policy = OperateSystem::into_policy().with_prepolicy(true);
let _ = parser.parse_policy(Args::from(&cli.args), &mut policy);
let migr = parser.take_val::<Migrate>("migrate").ok();
let from = migr.and_then(|v| v.from);
let mut manager = CompletionManager::new(parser);
let migr = manager.find_manager_mut("migrate")?;
migr.set_values(migr.parser().find_uid("from")?, OS);
migr.set_values(migr.parser().find_uid("to")?, list_os_except(from));
OperateSystem::inject_completion_values(&mut manager)?;
shell.set_buff(std::io::stdout());
manager.complete(shell, &mut ctx)?;
Ok(())
})?;
Ok(())
}
pub fn read_server_from_cfg<O>() -> impl Values<O> {
once_values(|_| {
Ok(["a.com", "b.org", "c.io"]
.iter()
.map(OsString::from)
.collect())
})
}
pub fn list_os_except<O>(from: Option<String>) -> impl Values<O> {
once_values(move |_| {
let mut vals = OS.to_vec();
if let Some(idx) = from.as_ref().and_then(|r| vals.iter().position(|v| v == r)) {
vals.swap_remove(idx);
}
Ok(vals.iter().map(OsString::from).collect())
})
}