1#![feature(let_chains)]
2
3use std::{
4 fs::File,
5 io::{BufRead, BufReader},
6 path::Path,
7};
8
9pub fn set(
10 path: impl AsRef<Path>,
11 key: impl AsRef<str>,
12 value: impl AsRef<str>,
13) -> std::io::Result<Vec<(String, String)>> {
14 let path = path.as_ref();
15 let value = value.as_ref();
16 let key = key.as_ref();
17 let mut result = vec![];
18 let mut readed = vec![];
19 let kv = (key.to_owned(), value.to_owned());
20 if path.exists() {
21 let mut changed = false;
22 let mut has_key = false;
23 let file = File::open(path)?;
24 let reader = BufReader::new(file);
25 for line in reader.lines().map_while(Result::ok) {
26 let line = line.trim();
27 readed.push(line.to_owned());
28 if line.starts_with("#") {
29 continue;
30 }
31 if let Some(p) = line.find(":")
32 && (p + 1) < line.len()
33 {
34 let k = line[0..p].trim();
35 let v = line[p + 1..].trim();
36 if k == key {
37 has_key = true;
38 result.push(kv.clone());
39 if value != v {
40 changed = true;
41 readed.pop();
42 readed.push(format!("{key}: {value}"));
43 }
44 } else {
45 result.push((k.to_owned(), v.to_owned()));
46 }
47 }
48 }
49 if !has_key {
50 result.insert(0, kv);
51 changed = true;
52 }
53 if changed {
54 ifs::wstr(path, readed.join("\n"))?;
55 }
56 } else {
57 result.push(kv);
58 ifs::wstr(path, format!("{key}: {value}"))?;
59 }
60 Ok(result)
61}