1#![feature(exit_status_error)]
6
7use std::path::Path;
8use std::path::PathBuf;
9
10use owo_colors::OwoColorize;
11use ytil_sys::cli::Args;
12
13const BINS: &[&str] = &[
16 "idt", "catl", "fkr", "gch", "gcu", "ghl", "oe", "rmr", "strgci", "tec", "try", "vpg", "yghfl", "yhfp",
17];
18const LIBS: &[(&str, &str)] = &[("libnvrim.dylib", "nvrim.so")];
20const BINS_DEFAULT_PATH: &[&str] = &[".local", "bin"];
22const NVIM_LIBS_DEFAULT_PATH: &[&str] = &[".config", "nvim", "lua"];
24
25fn remove_last_n_dirs(path: &mut PathBuf, n: usize) {
27 for _ in 0..n {
28 if !path.pop() {
29 return;
30 }
31 }
32}
33
34fn drop_element<T, U: ?Sized>(vec: &mut Vec<T>, target: &U) -> bool
37where
38 T: PartialEq<U>,
39{
40 if let Some(idx) = vec.iter().position(|x| x == target) {
41 vec.swap_remove(idx);
42 return true;
43 }
44 false
45}
46
47fn cp(from: &Path, to: &Path) -> rootcause::Result<()> {
54 ytil_sys::file::atomic_cp(from, to)?;
55 println!("{} {} to {}", "Copied".green().bold(), from.display(), to.display());
56 Ok(())
57}
58
59#[ytil_sys::main]
61fn main() -> rootcause::Result<()> {
62 let mut args = ytil_sys::cli::get();
63
64 if args.has_help() {
65 println!("{}", include_str!("../help.txt"));
66 return Ok(());
67 }
68
69 let is_debug = drop_element(&mut args, "--debug");
70 let bins_path = args.first().cloned().map_or_else(
71 || ytil_sys::dir::build_home_path(BINS_DEFAULT_PATH),
72 |supplied_bins_path| Ok(PathBuf::from(supplied_bins_path)),
73 )?;
74 let cargo_target_path = args.get(1).cloned().map_or_else(
75 || {
76 std::env::var("CARGO_MANIFEST_DIR").map(|cargo_manifest_dir| {
77 let mut x = PathBuf::from(cargo_manifest_dir);
78 remove_last_n_dirs(&mut x, 2);
79 x.join("target")
80 })
81 },
82 |x| Ok(PathBuf::from(x)),
83 )?;
84 let nvim_libs_path = args.get(2).cloned().map_or_else(
85 || ytil_sys::dir::build_home_path(NVIM_LIBS_DEFAULT_PATH),
86 |supplied_nvim_libs_path| Ok(PathBuf::from(supplied_nvim_libs_path)),
87 )?;
88
89 let (cargo_target_location, build_profile) = if is_debug {
90 (cargo_target_path.join("debug"), None)
91 } else {
92 (cargo_target_path.join("release"), Some("--release"))
93 };
94
95 ytil_cmd::silent_cmd("cargo").args(["fmt"]).status()?.exit_ok()?;
96
97 if !is_debug {
99 ytil_cmd::silent_cmd("cargo")
100 .args(["clippy", "--all-targets", "--all-features", "--", "-D", "warnings"])
101 .status()?
102 .exit_ok()?;
103 }
104
105 ytil_cmd::silent_cmd("cargo")
106 .args([Some("build"), build_profile].into_iter().flatten())
107 .status()?
108 .exit_ok()?;
109
110 for bin in BINS {
111 cp(&cargo_target_location.join(bin), &bins_path.join(bin))?;
112 }
113
114 for (source_lib_name, target_lib_name) in LIBS {
115 cp(
116 &cargo_target_location.join(source_lib_name),
117 &nvim_libs_path.join(target_lib_name),
118 )?;
119 }
120
121 Ok(())
122}
123
124#[cfg(test)]
125mod tests {
126 use rstest::rstest;
127
128 use super::*;
129
130 #[test]
131 fn drop_element_returns_true_and_removes_the_element_from_the_vec() {
132 let mut input = vec![42, 7];
133 assert!(drop_element(&mut input, &7));
134 assert_eq!(input, vec![42]);
135 }
136
137 #[test]
138 fn drop_element_returns_false_and_does_nothing_to_a_non_empty_vec() {
139 let mut input = vec![42, 7];
140 assert!(!drop_element(&mut input, &3));
141 assert_eq!(input, vec![42, 7]);
142 }
143
144 #[test]
145 fn drop_element_returns_false_and_does_nothing_to_an_empty_vec() {
146 let mut input: Vec<usize> = vec![];
147 assert!(!drop_element(&mut input, &3));
148 assert!(input.is_empty());
149 }
150
151 #[rstest]
152 #[case::no_dirs_removed(PathBuf::from("/home/user/docs"), 0, PathBuf::from("/home/user/docs"))]
153 #[case::remove_one_dir(PathBuf::from("/home/user/docs"), 1, PathBuf::from("/home/user"))]
154 #[case::remove_more_than_exist(PathBuf::from("/home/user"), 5, PathBuf::from("/"))]
155 #[case::root_path(PathBuf::from("/"), 1, PathBuf::from("/"))]
156 #[case::empty_path(PathBuf::new(), 1, PathBuf::new())]
157 fn remove_last_n_dirs_works(#[case] mut initial: PathBuf, #[case] n: usize, #[case] expected: PathBuf) {
158 remove_last_n_dirs(&mut initial, n);
159 pretty_assertions::assert_eq!(initial, expected);
160 }
161}