summaryrefslogtreecommitdiff
path: root/src/systems/comp
diff options
context:
space:
mode:
author魏曹先生 <1992414357@qq.com>2026-03-26 15:55:10 +0800
committer魏曹先生 <1992414357@qq.com>2026-03-26 15:55:10 +0800
commitfb2ffa849a2cf9251cc274ebea5daa9898579787 (patch)
tree53b87ee60ba7c6ee7b001221855a6f3bff7e8526 /src/systems/comp
parent4cb7c2e91d7dbde32de31e6ab48683d60212ec1d (diff)
Add shell completion system with descriptions and i18n support
Diffstat (limited to 'src/systems/comp')
-rw-r--r--src/systems/comp/result.rs205
1 files changed, 205 insertions, 0 deletions
diff --git a/src/systems/comp/result.rs b/src/systems/comp/result.rs
new file mode 100644
index 0000000..e64021d
--- /dev/null
+++ b/src/systems/comp/result.rs
@@ -0,0 +1,205 @@
+pub enum CompletionResult {
+ FileCompletion,
+ Suggestions(Vec<CompletionSuggestion>),
+}
+
+impl CompletionResult {
+ /// Creates a `CompletionResult` representing file completion.
+ pub fn file_comp() -> Self {
+ CompletionResult::FileCompletion
+ }
+
+ /// Creates a `CompletionResult` with an empty suggestions list.
+ pub fn empty_comp() -> CompletionSuggestInsert {
+ CompletionSuggestInsert {
+ suggestions: Vec::new(),
+ }
+ }
+
+ /// Returns `true` if this is a `FileCompletion` variant.
+ pub fn is_file(&self) -> bool {
+ matches!(self, Self::FileCompletion)
+ }
+
+ /// Returns `true` if this is a `Suggestions` variant.
+ pub fn is_suggestion(&self) -> bool {
+ matches!(self, Self::Suggestions(_))
+ }
+
+ /// Returns a reference to the suggestions vector if this is a `Suggestions` variant,
+ /// otherwise returns `None`.
+ pub fn suggestion(&self) -> Option<&Vec<CompletionSuggestion>> {
+ match self {
+ Self::FileCompletion => None,
+ Self::Suggestions(v) => Some(v),
+ }
+ }
+
+ /// Returns the unit value if this is a `FileCompletion` variant, otherwise panics.
+ pub fn unwrap_file(&self) {
+ match self {
+ Self::FileCompletion => (),
+ Self::Suggestions(_) => {
+ panic!("called `CompletionResult::unwrap_file()` on a `Suggestions` value")
+ }
+ }
+ }
+
+ /// Returns a reference to the suggestions vector if this is a `Suggestions` variant,
+ /// otherwise panics.
+ pub fn unwrap_suggestion(&self) -> &Vec<CompletionSuggestion> {
+ match self {
+ Self::FileCompletion => {
+ panic!("called `CompletionResult::unwrap_suggestion()` on a `FileCompletion` value")
+ }
+ Self::Suggestions(v) => v,
+ }
+ }
+
+ /// Returns the unit value if this is a `FileCompletion` variant, otherwise returns `default`.
+ pub fn unwrap_file_or(&self, default: ()) {
+ match self {
+ Self::FileCompletion => (),
+ Self::Suggestions(_) => default,
+ }
+ }
+
+ /// Returns a reference to the suggestions vector if this is a `Suggestions` variant,
+ /// otherwise returns `default`.
+ pub fn unwrap_suggestion_or<'a>(
+ &'a self,
+ default: &'a Vec<CompletionSuggestion>,
+ ) -> &'a Vec<CompletionSuggestion> {
+ match self {
+ Self::FileCompletion => default,
+ Self::Suggestions(v) => v,
+ }
+ }
+
+ /// Returns the unit value if this is a `FileCompletion` variant, otherwise calls `f`.
+ pub fn unwrap_file_or_else<F>(&self, f: F)
+ where
+ F: FnOnce(),
+ {
+ match self {
+ Self::FileCompletion => (),
+ Self::Suggestions(_) => f(),
+ }
+ }
+
+ /// Returns a reference to the suggestions vector if this is a `Suggestions` variant,
+ /// otherwise calls `f`.
+ pub fn unwrap_suggestion_or_else<'a, F>(&'a self, f: F) -> &'a Vec<CompletionSuggestion>
+ where
+ F: FnOnce() -> &'a Vec<CompletionSuggestion>,
+ {
+ match self {
+ Self::FileCompletion => f(),
+ Self::Suggestions(v) => v,
+ }
+ }
+}
+
+pub struct CompletionSuggestInsert {
+ suggestions: Vec<CompletionSuggestion>,
+}
+
+impl CompletionSuggestInsert {
+ /// Adds a suggestion with the given text and no description.
+ pub fn with_suggest<S: Into<String>>(mut self, suggest: S) -> Self {
+ self.suggestions.push(CompletionSuggestion {
+ suggest: suggest.into(),
+ description: None,
+ });
+ self
+ }
+
+ /// Adds a suggestion with the given text and description.
+ pub fn with_suggest_desc<S: Into<String>, D: Into<String>>(
+ mut self,
+ suggest: S,
+ description: D,
+ ) -> Self {
+ self.suggestions.push(CompletionSuggestion {
+ suggest: suggest.into(),
+ description: Some(description.into()),
+ });
+ self
+ }
+}
+
+impl From<CompletionSuggestInsert> for CompletionResult {
+ fn from(insert: CompletionSuggestInsert) -> Self {
+ CompletionResult::Suggestions(insert.suggestions)
+ }
+}
+
+impl From<Vec<String>> for CompletionResult {
+ fn from(strings: Vec<String>) -> Self {
+ CompletionResult::Suggestions(
+ strings
+ .into_iter()
+ .map(|s| CompletionSuggestion {
+ suggest: s,
+ description: None,
+ })
+ .collect(),
+ )
+ }
+}
+
+impl std::fmt::Display for CompletionResult {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ match self {
+ CompletionResult::FileCompletion => write!(f, "_file_"),
+ CompletionResult::Suggestions(suggestions) => {
+ let suggestions_str: Vec<String> =
+ suggestions.iter().map(|s| s.suggest.clone()).collect();
+ write!(f, "{}", suggestions_str.join(", "))
+ }
+ }
+ }
+}
+
+#[derive(Debug, Default, Clone, PartialEq, Eq)]
+pub struct CompletionSuggestion {
+ pub suggest: String,
+ pub description: Option<String>,
+}
+
+impl std::ops::Deref for CompletionSuggestion {
+ type Target = String;
+
+ fn deref(&self) -> &Self::Target {
+ &self.suggest
+ }
+}
+
+impl std::ops::DerefMut for CompletionSuggestion {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ &mut self.suggest
+ }
+}
+
+impl AsRef<str> for CompletionSuggestion {
+ fn as_ref(&self) -> &str {
+ &self.suggest
+ }
+}
+
+impl PartialOrd for CompletionSuggestion {
+ fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
+ Some(self.cmp(other))
+ }
+}
+
+impl Ord for CompletionSuggestion {
+ fn cmp(&self, other: &Self) -> std::cmp::Ordering {
+ match (&self.description, &other.description) {
+ (None, None) => self.suggest.cmp(&other.suggest),
+ (Some(_), None) => std::cmp::Ordering::Less,
+ (None, Some(_)) => std::cmp::Ordering::Greater,
+ (Some(_), Some(_)) => self.suggest.cmp(&other.suggest),
+ }
+ }
+}