aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crates/atuin-client/src/lib.rs1
-rw-r--r--crates/atuin-client/src/plugin.rs97
-rw-r--r--crates/atuin/src/command/external.rs24
3 files changed, 120 insertions, 2 deletions
diff --git a/crates/atuin-client/src/lib.rs b/crates/atuin-client/src/lib.rs
index 443ff3f8..78819548 100644
--- a/crates/atuin-client/src/lib.rs
+++ b/crates/atuin-client/src/lib.rs
@@ -15,6 +15,7 @@ pub mod import;
pub mod login;
pub mod logout;
pub mod ordering;
+pub mod plugin;
pub mod record;
pub mod register;
pub mod secrets;
diff --git a/crates/atuin-client/src/plugin.rs b/crates/atuin-client/src/plugin.rs
new file mode 100644
index 00000000..21a2bcef
--- /dev/null
+++ b/crates/atuin-client/src/plugin.rs
@@ -0,0 +1,97 @@
+use std::collections::HashMap;
+
+#[derive(Debug, Clone)]
+pub struct OfficialPlugin {
+ pub name: String,
+ pub description: String,
+ pub install_message: String,
+}
+
+impl OfficialPlugin {
+ pub fn new(name: &str, description: &str, install_message: &str) -> Self {
+ Self {
+ name: name.to_string(),
+ description: description.to_string(),
+ install_message: install_message.to_string(),
+ }
+ }
+}
+
+pub struct OfficialPluginRegistry {
+ plugins: HashMap<String, OfficialPlugin>,
+}
+
+impl OfficialPluginRegistry {
+ pub fn new() -> Self {
+ let mut registry = Self {
+ plugins: HashMap::new(),
+ };
+
+ // Register official plugins
+ registry.register_official_plugins();
+
+ registry
+ }
+
+ fn register_official_plugins(&mut self) {
+ // atuin-update plugin
+ self.plugins.insert(
+ "update".to_string(),
+ OfficialPlugin::new(
+ "update",
+ "Update atuin to the latest version",
+ "The 'atuin update' command is provided by the atuin-update plugin.\n\
+ It is only installed if you used the install script\n \
+ If you used a package manager (brew, apt, etc), please continue to use it for updates"
+ ),
+ );
+ }
+
+ pub fn get_plugin(&self, name: &str) -> Option<&OfficialPlugin> {
+ self.plugins.get(name)
+ }
+
+ pub fn is_official_plugin(&self, name: &str) -> bool {
+ self.plugins.contains_key(name)
+ }
+
+ pub fn get_install_message(&self, name: &str) -> Option<&str> {
+ self.plugins
+ .get(name)
+ .map(|plugin| plugin.install_message.as_str())
+ }
+}
+
+impl Default for OfficialPluginRegistry {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_registry_creation() {
+ let registry = OfficialPluginRegistry::new();
+ assert!(registry.is_official_plugin("update"));
+ assert!(!registry.is_official_plugin("nonexistent"));
+ }
+
+ #[test]
+ fn test_get_plugin() {
+ let registry = OfficialPluginRegistry::new();
+ let plugin = registry.get_plugin("update");
+ assert!(plugin.is_some());
+ assert_eq!(plugin.unwrap().name, "update");
+ }
+
+ #[test]
+ fn test_get_install_message() {
+ let registry = OfficialPluginRegistry::new();
+ let message = registry.get_install_message("update");
+ assert!(message.is_some());
+ assert!(message.unwrap().contains("atuin-update"));
+ }
+}
diff --git a/crates/atuin/src/command/external.rs b/crates/atuin/src/command/external.rs
index 03deacbf..657aea56 100644
--- a/crates/atuin/src/command/external.rs
+++ b/crates/atuin/src/command/external.rs
@@ -2,6 +2,8 @@ use std::fmt::Write as _;
use std::process::Command;
use std::{io, process};
+#[cfg(feature = "client")]
+use atuin_client::plugin::OfficialPluginRegistry;
use clap::CommandFactory;
use clap::builder::{StyledStr, Styles};
use eyre::Result;
@@ -44,13 +46,31 @@ pub fn run(args: &[String]) -> Result<()> {
fn render_not_found(subcommand: &str, bin: &str) -> StyledStr {
let mut output = StyledStr::new();
let styles = Styles::styled();
- let mut atuin_cmd = Atuin::command();
- let usage = atuin_cmd.render_usage();
let error = styles.get_error();
let invalid = styles.get_invalid();
let literal = styles.get_literal();
+ #[cfg(feature = "client")]
+ {
+ let registry = OfficialPluginRegistry::new();
+
+ // Check if this is an official plugin
+ if let Some(install_message) = registry.get_install_message(subcommand) {
+ let _ = write!(output, "{error}error:{error:#} ");
+ let _ = write!(
+ output,
+ "'{invalid}{subcommand}{invalid:#}' is an official atuin plugin, but it's not installed"
+ );
+ let _ = write!(output, "\n\n");
+ let _ = write!(output, "{install_message}");
+ return output;
+ }
+ }
+
+ let mut atuin_cmd = Atuin::command();
+ let usage = atuin_cmd.render_usage();
+
let _ = write!(output, "{error}error:{error:#} ");
let _ = write!(
output,