1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
use crate::prelude::*;
use nu_engine::WholeStreamCommand;
use nu_errors::ShellError;
use nu_protocol::{Signature, SyntaxShape, UntaggedValue, Value};

pub struct SubCommand;

impl WholeStreamCommand for SubCommand {
    fn name(&self) -> &str {
        "config set"
    }

    fn signature(&self) -> Signature {
        Signature::build("config set")
            .required("key", SyntaxShape::ColumnPath, "variable name to set")
            .required("value", SyntaxShape::Any, "value to use")
    }

    fn usage(&self) -> &str {
        "Sets a value in the config"
    }

    fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
        set(args)
    }

    fn examples(&self) -> Vec<Example> {
        vec![
            Example {
                description: "Set auto pivoting",
                example: "config set pivot_mode always",
                result: None,
            },
            Example {
                description: "Set line editor options",
                example: "config set line_editor [[edit_mode, completion_type]; [emacs circular]]",
                result: None,
            },
            Example {
                description: "Set coloring options",
                example: "config set color_config [[header_align header_color]; [left white_bold]]",
                result: None,
            },
            Example {
                description: "Set nested options",
                example: "config set color_config.header_color white",
                result: None,
            },
        ]
    }
}

pub fn set(args: CommandArgs) -> Result<OutputStream, ShellError> {
    let name = args.call_info.name_tag.clone();
    let ctx = &args.context;

    let column_path = args.req(0)?;
    let mut value: Value = args.req(1)?;

    let result = if let Some(global_cfg) = &mut ctx.configs().lock().global_config {
        let configuration = UntaggedValue::row(global_cfg.vars.clone()).into_value(&name);

        if let UntaggedValue::Table(rows) = &value.value {
            if rows.len() == 1 && rows[0].is_row() {
                value = rows[0].clone();
            }
        }

        match configuration.forgiving_insert_data_at_column_path(&column_path, value) {
            Ok(Value {
                value: UntaggedValue::Row(changes),
                ..
            }) => {
                global_cfg.vars = changes.entries;
                global_cfg.write()?;
                ctx.reload_config(global_cfg)?;

                let value = UntaggedValue::row(global_cfg.vars.clone()).into_value(name);
                Ok(OutputStream::one(value))
            }
            Ok(_) => Ok(OutputStream::empty()),
            Err(reason) => Err(reason),
        }
    } else {
        let value = UntaggedValue::Error(crate::commands::config::err_no_global_cfg_present())
            .into_value(name);

        Ok(OutputStream::one(value))
    };

    result
}