limp/
files.rs

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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
use std::{
    fs::{self, File},
    io::Write,
    path::{Path, PathBuf},
    process::Stdio,
};

use crate::error::LimpError;

const MAIN_SNIP: &str = r#"
fn main() {
    println!("Hello, limp!");
}"#;
const NAME: &str = "limp";
const CRATE_INFO_FILE: &str = "dependencies.db";
const SNIPPETS_DIR: &str = "snippets";

// bool - is windows
// pub struct FileManager {
//     is_windows: bool,
//     pub del: &'static str,
// }
// impl Default for FileManager {
//     fn default() -> Self {
//         let is_windows = std::env::consts::OS == "windows";
//         Self {
//             is_windows,
//             del: if is_windows { "\\" } else { "/" },
//         }
//     }
// }
//
// impl FileManager {
//     pub fn get_username(&self) -> String {
//         std::env::var("USER")
//             .unwrap_or(std::env::var("USERNAME").unwrap_or(String::from("unknown")))
//     }
//     pub fn config_dir(&self) -> String {
//         let username = self.get_username();
//         if self.is_windows {
//             format!("C:\\Users\\{}\\AppData\\Roaming\\{}", &username, NAME)
//         } else {
//             format!("/home/{}/.config/{}", &username, NAME)
//         }
//     }
//     pub fn config_file(&self) -> String {
//         let dir_path = self.config_dir();
//         format!("{}{}{}", &dir_path, self.del, CRATE_INFO_FILE)
//     }
//     pub fn storage_dir(&self) -> String {
//         let dir_path = self.config_dir();
//         format!("{}{}{}", &dir_path, self.del, SNIPPETS_DIR)
//     }
//
//     pub fn create_project(&self, name: &str) -> std::io::Result<()> {
//         // path is a relative path or an absolute path
//         let src = format!("{}{}src", name, self.del);
//         let main = format!("{}{}main.rs", &src, self.del);
//         let cargo = format!("{}{}Cargo.toml", name, self.del);
//
//         std::fs::create_dir_all(src)?;
//         let mut main = std::fs::File::create(&main)?;
//         main.write_all(MAIN_SNIP.as_bytes())?;
//         std::fs::File::create(&cargo)?;
//
//         if !std::process::Command::new("git")
//             .args(["init", name])
//             .spawn()?
//             .wait()?
//             .success()
//         {
//             eprintln!("ERROR: cannot create git repo in project {name}");
//             std::process::exit(1);
//         }
//         let gitignore = format!("{}{}.gitignore", name, self.del);
//         let mut file = self.copen(&gitignore);
//         file.write_all(b"/target")?;
//
//         Ok(())
//     }
//     pub fn copen(&self, path: &str) -> std::fs::File {
//         let path = std::path::Path::new(path);
//         if path.exists() {
//             std::fs::File::options()
//                 .read(true)
//                 .write(true)
//                 t
//                 .open(path)
//                 .unwrap()
//         } else {
//             std::fs::File::create(path).unwrap_or_else(|_| {
//                 if let Some(parent) = path.parent() {
//                     std::fs::create_dir_all(parent).unwrap();
//                     std::fs::File::create(path).unwrap()
//                 } else {
//                     panic!("Not reachable")
//                 }
//             })
//         }
//     }
// }

pub fn username() -> String {
    std::env::var("USER").unwrap_or(std::env::var("USERNAME").unwrap_or("unknown".to_string()))
}

pub fn storage_path() -> PathBuf {
    let uname = username();

    match std::env::consts::OS {
        "windows" => PathBuf::from(format!("C:\\Users\\{}\\AppData\\Roaming\\limp", &uname)),
        _ => PathBuf::from(format!("/home/{}/.config/limp/", &uname)),
    }
}

pub fn config_path() -> PathBuf {
    storage_path().join("dependencies.json")
}

pub fn snippets_dir() -> PathBuf {
    storage_path().join("snippets")
}

pub fn find_toml() -> Option<PathBuf> {
    if let Ok(mut path) = std::env::current_dir() {
        let pre_toml = path.join("Cargo.toml");
        if pre_toml.exists() {
            return Some(pre_toml);
        }
        while path.pop() {
            let pre_toml = path.join("Cargo.toml");
            if pre_toml.exists() {
                return Some(pre_toml);
            }
        }
        return None;
    }
    None
}

pub fn open<P: AsRef<Path>>(path: P) -> Result<File, LimpError> {
    let path = path.as_ref();
    fs::create_dir_all(path.parent().unwrap_or(Path::new("./")))?;
    let file = File::options()
        .read(true)
        .append(true)
        .create(true)
        .open(path)?;
    Ok(file)
}

pub fn create_project(name: &str, deps: Option<&[String]>) -> Result<(), LimpError> {
    let project = PathBuf::from(format!("./{}", name));
    if project.exists() && project.read_dir()?.count() > 0 {
        return Err(LimpError::CrateExistsNotEmpty(name.to_string()));
    }

    let mut toml = open(project.join("Cargo.toml"))?;
    writeln!(toml, "[package]")?;
    writeln!(toml, "name = \"{}\"", name)?;
    writeln!(toml, "version = \"0.1.0\"")?;
    writeln!(toml, "edition = \"2021\"")?;
    writeln!(toml)?;
    writeln!(toml, "[dependencies]")?;
    if let Some(deps) = deps {
        for dep in deps.iter() {
            writeln!(toml, "{}", dep)?
        }
    }

    let mut main = open(project.join("src").join("main.rs"))?;
    main.write_all(MAIN_SNIP.as_bytes())?;

    if !std::process::Command::new("git")
        .args(["init", name])
        .stdout(Stdio::null())
        .stderr(Stdio::null())
        .spawn()?
        .wait()?
        .success()
    {
        return Err(LimpError::GitError(name.to_string()));
    }
    let mut gitignore = open(project.join(".gitignore"))?;
    gitignore.write_all(b"/target")?;

    Ok(())
}