use crate::commands::traits::{CommandInfo, RegisterCommand};
use crate::localization::MessageId;
use crate::tui::app::{App, AppAction};
use super::CommandResult;
pub(in crate::commands) const COMMAND_INFO: CommandInfo = CommandInfo {
name: "rlm",
aliases: &["recursive", "digui"],
usage: "/rlm [N] <file_or_text>",
description_id: MessageId::CmdRlmDescription,
};
pub(in crate::commands) struct RlmCmd;
impl RegisterCommand for RlmCmd {
fn info() -> &'static CommandInfo {
&COMMAND_INFO
}
fn execute(app: &mut App, arg: Option<&str>) -> CommandResult {
rlm(app, arg)
}
}
pub fn rlm(app: &mut App, arg: Option<&str>) -> CommandResult {
let (max_depth, target) = match super::util::parse_depth_prefixed_arg(arg, 1) {
Ok(parsed) => parsed,
Err(message) => return CommandResult::error(message),
};
let target = match target {
Some(p) if !p.trim().is_empty() => p.trim().to_string(),
_ => {
return CommandResult::error(
"Usage: /rlm [N] <file_or_text>\n\n\
Opens a persistent RLM context with sub_rlm depth N (0-3, default 1)."
.to_string(),
);
}
};
let source_arg = if resolves_to_existing_file(app, &target) {
format!(r#"file_path: "{target}""#)
} else {
format!("content: {target:?}")
};
let message = format!(
"Open and use a persistent RLM session for this request. Call `rlm_open` with name `slash_rlm` and {source_arg}. Then call `rlm_configure` with `sub_rlm_max_depth: {max_depth}`. Use `rlm_eval` to inspect the context through `peek`, `search`, and `chunk`, and call `finalize(...)` from the REPL when ready. If a `var_handle` is returned, use `handle_read` for bounded slices or projections before answering."
);
CommandResult::with_message_and_action(
format!("Opening persistent RLM context at depth {max_depth}..."),
AppAction::SendMessage(message),
)
}
fn resolves_to_existing_file(app: &App, input: &str) -> bool {
let path = std::path::Path::new(input);
let candidate = if path.is_absolute() {
path.to_path_buf()
} else {
app.workspace.join(path)
};
candidate.is_file()
}