nu_experimental/options/mod.rs
1#![allow(
2 private_interfaces,
3 reason = "The marker structs don't need to be exposed, only the static values."
4)]
5
6use crate::*;
7
8mod example;
9mod reorder_cell_paths;
10
11/// Marker trait for defining experimental options.
12///
13/// Implement this trait to mark a struct as metadata for an [`ExperimentalOption`].
14/// It provides all necessary information about an experimental feature directly in code,
15/// without needing external documentation.
16///
17/// The `STATUS` field is especially important as it controls whether the feature is enabled
18/// by default and how users should interpret its reliability.
19pub(crate) trait ExperimentalOptionMarker {
20 /// Unique identifier for this experimental option.
21 ///
22 /// Must be a valid Rust identifier.
23 /// Used when parsing to toggle specific experimental options,
24 /// and may also serve as a user-facing label.
25 const IDENTIFIER: &'static str;
26
27 /// Brief description explaining what this option changes.
28 ///
29 /// Displayed to users in help messages or summaries without needing to visit external docs.
30 const DESCRIPTION: &'static str;
31
32 /// Indicates the status of an experimental status.
33 ///
34 /// Options marked [`Status::OptIn`] are disabled by default while options marked with
35 /// [`Status::OptOut`] are enabled by default.
36 /// Experimental options that stabilize should be marked as [`Status::DeprecatedDefault`] while
37 /// options that will be removed should be [`Status::DeprecatedDiscard`].
38 const STATUS: Status;
39}
40
41// Export only the static values.
42// The marker structs are not relevant and needlessly clutter the generated docs.
43pub use example::EXAMPLE;
44pub use reorder_cell_paths::REORDER_CELL_PATHS;
45
46// Include all experimental option statics in here.
47// This will test them and add them to the parsing list.
48
49/// A list of all available experimental options.
50///
51/// Use this to show users every experimental option, including their descriptions,
52/// identifiers, and current state.
53pub static ALL: &[&ExperimentalOption] = &[&EXAMPLE, &REORDER_CELL_PATHS];
54
55#[cfg(test)]
56mod tests {
57 use std::collections::HashSet;
58
59 use super::*;
60
61 #[test]
62 fn assert_identifiers_are_unique() {
63 let list: Vec<_> = ALL.iter().map(|opt| opt.identifier()).collect();
64 let set: HashSet<_> = HashSet::from_iter(&list);
65 assert_eq!(list.len(), set.len());
66 }
67
68 #[test]
69 fn assert_identifiers_are_valid() {
70 for option in ALL {
71 let identifier = option.identifier();
72 assert!(!identifier.is_empty());
73
74 let mut chars = identifier.chars();
75 let first = chars.next().expect("not empty");
76 assert!(first.is_alphabetic());
77 assert!(first.is_lowercase());
78
79 for char in chars {
80 assert!(char.is_alphanumeric() || char == '-');
81 if char.is_alphabetic() {
82 assert!(char.is_lowercase());
83 }
84 }
85 }
86 }
87
88 #[test]
89 fn assert_description_not_empty() {
90 for option in ALL {
91 assert!(!option.description().is_empty());
92 }
93 }
94}