aboutsummaryrefslogtreecommitdiff
path: root/mingling_core/src/comp/shell_ctx.rs
diff options
context:
space:
mode:
Diffstat (limited to 'mingling_core/src/comp/shell_ctx.rs')
-rw-r--r--mingling_core/src/comp/shell_ctx.rs132
1 files changed, 118 insertions, 14 deletions
diff --git a/mingling_core/src/comp/shell_ctx.rs b/mingling_core/src/comp/shell_ctx.rs
index 78ccb87..552e514 100644
--- a/mingling_core/src/comp/shell_ctx.rs
+++ b/mingling_core/src/comp/shell_ctx.rs
@@ -1,38 +1,142 @@
-// Doc Not Optimize
#![allow(deprecated)]
-use std::collections::HashSet;
-
use crate::{Flag, ShellFlag, Suggest, special_argument};
+use std::collections::HashSet;
-/// Context passed from the shell to the completion system,
-/// providing information about the current command line state
-/// to guide how completions should be generated.
+/// The shell context description for the current user.
+///
+/// It records the state of the command line input when the user is using the
+/// completion feature, allowing smart completion suggestions to be provided
+/// to the user based on this state.
+///
+/// # Note on `^` and `-` characters
+///
+/// The completion scripts auto-generated by `mingling` replace any `-`
+/// characters in the user's input with `^` when passing arguments to the
+/// completion engine. This is an intentional tradeoff to avoid parsing
+/// conflicts: since `-` is used both as a flag prefix (e.g., `-f`, `--help`)
+/// and as a value separator in the command-line arguments consumed by
+/// [`TryFrom`](std::convert::TryFrom), differentiating between them would
+/// otherwise be ambiguous. By substituting `-` with `^`, the completion
+/// engine can cleanly parse user-input values without confusing them for
+/// flags.
+///
+/// When reading fields like [`command_line`](ShellContext::command_line),
+/// [`current_word`](ShellContext::current_word),
+/// [`previous_word`](ShellContext::previous_word), or
+/// [`command_name`](ShellContext::command_name), the `^` characters are
+/// converted back to `-` so that the resulting context faithfully represents
+/// what the user originally typed.
+///
+/// # Behavior under `structural_renderer` feature
+///
+/// When the `structural_renderer` feature is enabled, this struct derives
+/// [`serde::Serialize`](https://docs.rs/serde/latest/serde/trait.Serialize.html).
+/// This allows the shell context to be serialized and transmitted over
+/// serialization boundaries (e.g., JSON, YAML) as a structured representation
+/// of the current shell input state. Each public field is serialized under
+/// its own key, enabling consumers to reconstruct the exact command-line
+/// state for rendering purposes.
+///
+/// # Usage
+///
+/// A [`ShellContext`] can be constructed from a vector of command-line
+/// argument strings using [`TryFrom`](std::convert::TryFrom):
+///
+/// ```
+/// # #[cfg(feature = "comp")] {
+/// # use mingling_core::ShellContext;
+/// let args = vec![
+/// "-f".to_string(), // --command-line
+/// "git commit ^m 'test'".to_string(),
+/// "-C".to_string(), // --cursor-position
+/// "12".to_string(),
+/// "-w".to_string(), // --current-word
+/// "commit".to_string(),
+/// "-p".to_string(), // --previous-word
+/// "git".to_string(),
+/// "-c".to_string(), // --command-name
+/// "git".to_string(),
+/// "-i".to_string(), // --word-index
+/// "1".to_string(),
+/// "-F".to_string(), // --shell-flag
+/// "bash".to_string(),
+/// ];
+///
+/// let context = ShellContext::try_from(args).unwrap();
+/// assert_eq!(context.command_line, "git commit -m 'test'");
+/// assert_eq!(context.cursor_position, 12);
+/// assert_eq!(context.current_word, "commit");
+/// assert_eq!(context.previous_word, "git");
+/// assert_eq!(context.command_name, "git");
+/// assert_eq!(context.word_index, 1);
+/// assert_eq!(context.all_words, vec!["git", "commit", "-m", "'test'"]);
+/// # }
+/// ```
+///
+/// When only partial information is available, the remaining fields default
+/// to empty values:
+///
+/// ```
+/// # #[cfg(feature = "comp")] {
+/// # use mingling_core::ShellContext;
+/// let args = vec![
+/// "-f".to_string(),
+/// "ls ^la".to_string(),
+/// "-C".to_string(),
+/// "5".to_string(),
+/// ];
+///
+/// let context = ShellContext::try_from(args).unwrap();
+/// assert_eq!(context.command_line, "ls -la");
+/// assert_eq!(context.cursor_position, 5);
+/// # }
+/// ```
+///
+/// If the `-F` flag is present without a value, `shell_flag` becomes
+/// `ShellFlag::Other(String::new())`. If `-F` is absent, it defaults to
+/// `ShellFlag::Other("unknown".to_string())`.
#[derive(Default, Debug)]
#[cfg_attr(feature = "structural_renderer", derive(serde::Serialize))]
pub struct ShellContext {
- /// The full command line (-f / --command-line)
+ /// The full command line
+ ///
+ /// Flag: [`-f`, `--command-line`]
pub command_line: String,
- /// Cursor position (-C / --cursor-position)
+ /// Cursor position
+ ///
+ /// Flag: [`-C`, `--cursor-position`]
pub cursor_position: usize,
- /// Current word (-w / --current-word)
+ /// Current word
+ ///
+ /// Flag: [`-w`, `--current-word`]
pub current_word: String,
- /// Previous word (-p / --previous-word)
+ /// Previous word
+ ///
+ /// Flag: [`-p`, `--previous-word`]
pub previous_word: String,
- /// Command name (-c / --command-name)
+ /// Command name
+ ///
+ /// Flag: [`-c`, `--command-name`]
pub command_name: String,
- /// Word index (-i / --word-index)
+ /// Word index
+ ///
+ /// Flag: [`-i`, `--word-index`]
pub word_index: usize,
- /// All words (-a / --all-words)
+ /// All words
+ ///
+ /// Flag: [`-a`, `--all-words`]
pub all_words: Vec<String>,
- /// Flag to indicate completion context (-F / --shell-flag)
+ /// Flag to indicate completion context
+ ///
+ /// Flag: [`-F`, `--shell-flag`]
pub shell_flag: ShellFlag,
}