lib/common/
util.rs

1use crate::common::Platform;
2use lazy_static::lazy_static;
3use std::{
4    ffi::OsStr,
5    io,
6    path::{Path, PathBuf},
7    sync::atomic::{AtomicBool, Ordering},
8};
9
10lazy_static! {
11    static ref PLATFORM: Platform = {
12        use Platform::*;
13
14        if cfg!(target_os = "linux") {
15            if wsl::is_wsl() {
16                Wsl
17            } else {
18                Linux
19            }
20        } else if cfg!(target_os = "macos") {
21            Macos
22        } else if cfg!(target_os = "windows") {
23            Windows
24        } else {
25            eprintln!("Error: this platform is not supported");
26            std::process::exit(1);
27        }
28    };
29}
30
31pub fn platform() -> Platform {
32    *PLATFORM
33}
34
35/// Efficiently appends two `Vec`s together
36pub fn append_vecs<T>(x: Vec<T>, mut y: Vec<T>) -> Vec<T> {
37    let mut res = x;
38    res.append(&mut y);
39
40    res
41}
42
43lazy_static! {
44    static ref HOME_DIR: PathBuf = match dirs::home_dir() {
45        Some(home_dir) => home_dir,
46        None => {
47            eprintln!("Error: couldn't find home directory");
48            std::process::exit(1);
49        },
50    };
51}
52
53pub fn home_dir() -> &'static Path {
54    HOME_DIR.as_path()
55}
56
57/// Tries to replace absolute paths of the home directory
58/// with a tilde for readability. If that fails for any reason, just
59/// return `path`.
60pub fn home_to_tilde(path: &Path) -> PathBuf {
61    let relative_path = match path.strip_prefix(home_dir()) {
62        Ok(relative_path) => relative_path,
63        // The home directory isn't a prefix of `path` - just return `path` unchanged
64        Err(_) => return PathBuf::from(path),
65    };
66
67    PathBuf::from("~").join(relative_path)
68}
69
70/// Checks if a filename is prefixed by a '.' character.
71/// If the path cannot be read as UTF-8, assume it isn't hidden.
72pub fn is_hidden(filename: &OsStr) -> bool {
73    filename
74        .to_str()
75        .map(|s| s.starts_with('.'))
76        .unwrap_or(false)
77}
78
79#[derive(Debug, Clone, Copy)]
80pub enum FileType {
81    File,
82    Directory,
83    Symlink,
84}
85use FileType::*;
86
87pub fn file_type(path: impl AsRef<Path>) -> io::Result<FileType> {
88    let file_type = path.as_ref().symlink_metadata()?.file_type();
89
90    Ok(if file_type.is_file() {
91        File
92    } else if file_type.is_dir() {
93        Directory
94    } else if file_type.is_symlink() {
95        Symlink
96    } else {
97        unreachable!()
98    })
99}
100
101static VERBOSE: AtomicBool = AtomicBool::new(false);
102
103pub fn set_verbosity(verbosity: bool) {
104    VERBOSE.store(verbosity, Ordering::SeqCst);
105}
106
107pub fn get_verbosity() -> bool {
108    VERBOSE.load(Ordering::SeqCst)
109}
110
111#[macro_export]
112macro_rules! verbose_print {
113     ($($args:tt)*) => {
114         if crate::common::util::get_verbosity() {
115             print!($($args)*);
116         }
117     }
118}
119
120#[macro_export]
121macro_rules! verbose_println {
122     ($($args:tt)*) => {
123         if crate::common::util::get_verbosity() {
124             println!($($args)*);
125         }
126     }
127}