kx/
lib.rs

1use std::{cell::RefCell, error::Error};
2
3mod parser;
4
5#[derive(Debug)]
6pub struct Config<'a> {
7    contents: RefCell<Vec<&'a str>>,
8}
9
10impl<'a> Config<'a> {
11    pub fn load(contents: Vec<&'a str>) -> Config {
12        Config {
13            contents: RefCell::new(contents),
14        }
15    }
16
17    pub fn get_config(&self) -> String {
18        self.contents
19            .borrow()
20            .iter()
21            .map(|c| c.to_string())
22            .collect::<Vec<String>>()
23            .join("\n")
24    }
25
26    pub fn list_contexts(&self) -> Result<String, Box<dyn Error>> {
27        Ok(self
28            .get_contexts()?
29            .iter()
30            .map(|c| c.to_string())
31            .collect::<Vec<String>>()
32            .join("\n"))
33    }
34
35    pub fn check_context(&self, context: &str) -> Result<bool, &'static str> {
36        let contexts = self.get_contexts()?;
37
38        Ok(contexts.iter().any(|c| *c == context))
39    }
40
41    pub fn get_current_context(&self) -> Result<&str, &'static str> {
42        let contents = self.contents.borrow();
43        let iter = contents.iter();
44
45        for line in iter {
46            if let Some(current_context) = parser::match_literal(line, "current-context: ") {
47                return Ok(current_context);
48            }
49        }
50
51        Err("current-context is not set")
52    }
53
54    pub fn set_current_context(&'a self, new_context: &'a str) -> Result<(), &'static str> {
55        let mut contents = self.contents.borrow_mut();
56        let iter = contents.iter();
57
58        for (index, line) in iter.enumerate() {
59            if parser::match_literal(line, "current-context:").is_some() {
60                contents.push(new_context);
61                contents.swap_remove(index);
62                return Ok(());
63            }
64        }
65
66        contents.push(new_context);
67
68        Ok(())
69    }
70
71    pub fn unset_current_context(&'a self) -> Result<(), &'static str> {
72        let mut contents = self.contents.borrow_mut();
73        let iter = contents.iter();
74
75        for (index, line) in iter.enumerate() {
76            if parser::match_literal(line, "current-context:").is_some() {
77                contents.remove(index);
78                return Ok(());
79            }
80        }
81
82        Ok(())
83    }
84
85    fn get_contexts(&self) -> Result<Vec<&str>, &'static str> {
86        let mut contexts = Vec::<&str>::new();
87        let contents = self.contents.borrow();
88        let mut input = contents.iter().peekable();
89
90        while let Some(line) = input.next() {
91            if parser::match_literal(line, "contexts:").is_some() {
92                while parser::is_in_mapping(input.peek().ok_or("Reached the end of contexts.")?)
93                    .is_ok()
94                {
95                    if let Some(line) = input.next() {
96                        if let Some(name) = parser::match_literal(line, "  name: ") {
97                            contexts.push(name);
98                        }
99                    }
100                }
101
102                break;
103            }
104        }
105
106        if contexts.is_empty() {
107            return Err("Cannot get contexts!");
108        }
109
110        Ok(contexts)
111    }
112}