nu_cmd_plugin/commands/plugin/
rm.rs1use nu_engine::command_prelude::*;
2use nu_protocol::shell_error::generic::GenericError;
3
4use crate::util::{canonicalize_possible_filename_arg, modify_plugin_file};
5
6#[derive(Clone)]
7pub struct PluginRm;
8
9impl Command for PluginRm {
10 fn name(&self) -> &str {
11 "plugin rm"
12 }
13
14 fn signature(&self) -> Signature {
15 Signature::build(self.name())
16 .input_output_type(Type::Nothing, Type::Nothing)
17 .named(
19 "plugin-config",
20 SyntaxShape::Filepath,
21 "Use a plugin registry file other than the one set in `$nu.plugin-path`.",
22 None,
23 )
24 .switch(
25 "force",
26 "Don't cause an error if the plugin name wasn't found in the file.",
27 Some('f'),
28 )
29 .required(
30 "name",
31 SyntaxShape::String,
32 "The name, or filename, of the plugin to remove.",
33 )
34 .category(Category::Plugin)
35 }
36
37 fn description(&self) -> &str {
38 "Remove a plugin from the plugin registry file."
39 }
40
41 fn extra_description(&self) -> &str {
42 "
43This does not remove the plugin commands from the current scope or from `plugin
44list` in the current shell. It instead removes the plugin from the plugin
45registry file (by default, `$nu.plugin-path`). The changes will be apparent the
46next time `nu` is launched with that plugin registry file.
47
48This can be useful for removing an invalid plugin signature, if it can't be
49fixed with `plugin add`.
50"
51 .trim()
52 }
53
54 fn search_terms(&self) -> Vec<&str> {
55 vec!["remove", "delete", "signature"]
56 }
57
58 fn examples(&self) -> Vec<Example<'_>> {
59 vec![
60 Example {
61 example: "plugin rm inc",
62 description: "Remove the installed signatures for the `inc` plugin.",
63 result: None,
64 },
65 Example {
66 example: "plugin rm ~/.cargo/bin/nu_plugin_inc",
67 description: "Remove the installed signatures for the plugin with the filename `~/.cargo/bin/nu_plugin_inc`.",
68 result: None,
69 },
70 Example {
71 example: "plugin rm --plugin-config polars.msgpackz polars",
72 description: "Remove the installed signatures for the `polars` plugin from the \"polars.msgpackz\" plugin registry file.",
73 result: None,
74 },
75 ]
76 }
77
78 fn run(
79 &self,
80 engine_state: &EngineState,
81 stack: &mut Stack,
82 call: &Call,
83 _input: PipelineData,
84 ) -> Result<PipelineData, ShellError> {
85 let name: Spanned<String> = call.req(engine_state, stack, 0)?;
86 let custom_path = call.get_flag(engine_state, stack, "plugin-config")?;
87 let force = call.has_flag(engine_state, stack, "force")?;
88
89 let filename = canonicalize_possible_filename_arg(engine_state, stack, &name.item);
90
91 modify_plugin_file(engine_state, stack, call.head, &custom_path, |contents| {
92 if let Some(index) = contents
93 .plugins
94 .iter()
95 .position(|p| p.name == name.item || p.filename == filename)
96 {
97 contents.plugins.remove(index);
98 Ok(())
99 } else if force {
100 Ok(())
101 } else {
102 Err(ShellError::Generic(GenericError::new(
103 format!("Failed to remove the `{}` plugin", name.item),
104 "couldn't find a plugin with this name in the registry file",
105 name.span,
106 )))
107 }
108 })?;
109
110 Ok(Value::nothing(call.head).into_pipeline_data())
111 }
112}