use omgbase_surface::read::find_doc_by_ref;
use omgbase_surface::reference_path;
use serde_json::{Value as Json, json};
use crate::cli::argv::{Mode, Opt, number, parse_args};
use crate::cli::context::Cli;
use crate::cli::help::{render_help_for, wants_help};
use crate::cli::output::{CliError, EXIT_OK, Result, truncation_footer};
use super::{doc_locator, machine_out};
pub fn outline(cli: &mut Cli, args: &[String]) -> Result<i32> {
if wants_help(args) {
return render_help_for(cli, "outline");
}
let a = parse_args(args, &[Opt::value("depth"), Opt::flag("skeleton")])?;
let Some(r) = a.pos(0) else {
return Err(CliError::usage("outline requires a <doc|path>"));
};
let depth = number(&a, "depth")?;
let skeleton = a.flag("skeleton");
let (doc, header) = if cli.remote_mode() {
let header = if r.starts_with("d_") {
r.to_owned()
} else {
reference_path(r)
};
(r.to_owned(), header)
} else {
let repo = cli.repo()?;
let info = find_doc_by_ref(cli.store()?.conn(), &repo.repo_id, r)?
.ok_or_else(|| CliError::engine("doc_missing", format!("no document {r}")))?;
(info.doc_id, reference_path(&info.path))
};
let mut req = serde_json::Map::new();
doc_locator(&mut req, &doc);
if let Some(d) = depth {
req.insert("depth".to_owned(), json!(d));
}
if skeleton {
req.insert("resolution".to_owned(), json!("skeleton"));
}
let result = cli.call("docs_outline", Json::Object(req))?;
let truncated = result
.get("truncated")
.and_then(Json::as_bool)
.unwrap_or(false);
let style = cli.style;
if let Some(code) = machine_out(cli, &result, None, None) {
if truncated && cli.flags.mode != Mode::Json {
truncation_footer(cli.io, &style, "budget");
}
return code;
}
cli.io.out(&style.wordmark(&header));
cli.io.out(&style.rule());
let text = result.get("text").and_then(Json::as_str).unwrap_or("");
for line in text.split('\n') {
cli.io.out(line);
}
if truncated {
truncation_footer(cli.io, &style, "budget");
}
Ok(EXIT_OK)
}