use runmat_builtins::Value;
use runmat_builtins::{
BuiltinCompletionPolicy, BuiltinDescriptor, BuiltinErrorDescriptor, BuiltinOutputMode,
BuiltinParamArity, BuiltinParamDescriptor, BuiltinParamType, BuiltinSignatureDescriptor,
};
use runmat_macros::runtime_builtin;
use super::op_common::cmd_parsing::parse_hold_mode;
use super::state::{set_hold, HoldMode};
use crate::builtins::plotting::type_resolvers::bool_type;
const HOLD_OUTPUT_STATUS: [BuiltinParamDescriptor; 1] = [BuiltinParamDescriptor {
name: "enabled",
ty: BuiltinParamType::LogicalArray,
arity: BuiltinParamArity::Required,
default: None,
description: "True when hold is enabled after command execution.",
}];
const HOLD_INPUTS_NONE: [BuiltinParamDescriptor; 0] = [];
const HOLD_INPUTS_MODE: [BuiltinParamDescriptor; 1] = [BuiltinParamDescriptor {
name: "mode",
ty: BuiltinParamType::Any,
arity: BuiltinParamArity::Optional,
default: Some("\"toggle\""),
description: "Hold mode ('on'|'off'|'all') or numeric/logical scalar.",
}];
const HOLD_SIGNATURES: [BuiltinSignatureDescriptor; 2] = [
BuiltinSignatureDescriptor {
label: "enabled = hold()",
inputs: &HOLD_INPUTS_NONE,
outputs: &HOLD_OUTPUT_STATUS,
},
BuiltinSignatureDescriptor {
label: "enabled = hold(mode)",
inputs: &HOLD_INPUTS_MODE,
outputs: &HOLD_OUTPUT_STATUS,
},
];
const HOLD_ERROR_INVALID_ARGUMENT: BuiltinErrorDescriptor = BuiltinErrorDescriptor {
code: "RM.HOLD.INVALID_ARGUMENT",
identifier: Some("RunMat:hold:InvalidArgument"),
when: "Hold mode argument is unsupported.",
message: "hold: invalid argument",
};
const HOLD_ERRORS: [BuiltinErrorDescriptor; 1] = [HOLD_ERROR_INVALID_ARGUMENT];
pub const HOLD_DESCRIPTOR: BuiltinDescriptor = BuiltinDescriptor {
signatures: &HOLD_SIGNATURES,
output_mode: BuiltinOutputMode::Fixed,
completion_policy: BuiltinCompletionPolicy::Public,
errors: &HOLD_ERRORS,
};
#[runtime_builtin(
name = "hold",
category = "plotting",
summary = "Control plot replacement versus appending.",
keywords = "hold,plotting",
suppress_auto_output = true,
type_resolver(bool_type),
descriptor(crate::builtins::plotting::hold::HOLD_DESCRIPTOR),
builtin_path = "crate::builtins::plotting::hold"
)]
pub fn hold_builtin(rest: Vec<Value>) -> crate::BuiltinResult<bool> {
let mode = if rest.is_empty() {
HoldMode::Toggle
} else {
parse_hold_mode(&rest[0])?
};
let enabled = set_hold(mode);
Ok(enabled)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn hold_descriptor_signatures_cover_core_forms() {
let labels: Vec<&str> = HOLD_DESCRIPTOR
.signatures
.iter()
.map(|sig| sig.label)
.collect();
assert!(labels.contains(&"enabled = hold()"));
assert!(labels.contains(&"enabled = hold(mode)"));
}
#[test]
fn hold_toggle_and_explicit_modes_work() {
let _ = hold_builtin(Vec::new()).unwrap();
let on = hold_builtin(vec![Value::String("on".into())]).unwrap();
assert!(on);
let off = hold_builtin(vec![Value::String("off".into())]).unwrap();
assert!(!off);
}
}