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
use lazy_static::lazy_static;
use std::path::{Path, PathBuf};
const TERMINFO_DIRS_DEBIAN: &str = "/etc/terminfo:/lib/terminfo:/usr/share/terminfo";
const TERMINFO_DIRS_REDHAT: &str = "/etc/terminfo:/usr/share/terminfo";
const TERMINFO_DIRS_MACOS: &str = "/usr/share/terminfo";
lazy_static! {
static ref TERMINFO_DIRS_COMMON: Vec<PathBuf> = {
vec![
PathBuf::from("/usr/local/etc/terminfo"),
PathBuf::from("/usr/local/lib/terminfo"),
PathBuf::from("/usr/local/share/terminfo"),
PathBuf::from("/etc/terminfo"),
PathBuf::from("/usr/lib/terminfo"),
PathBuf::from("/lib/terminfo"),
PathBuf::from("/usr/share/terminfo"),
]
};
}
#[derive(Clone)]
enum OsVariant {
Linux,
MacOs,
Windows,
Other,
}
enum LinuxDistroVariant {
Debian,
RedHat,
Unknown,
}
lazy_static! {
static ref TARGET_OS: OsVariant = {
if cfg!(target_os = "linux") {
OsVariant::Linux
} else if cfg!(target_os = "macos") {
OsVariant::MacOs
} else if cfg!(target_os = "windows") {
OsVariant::Windows
} else {
OsVariant::Other
}
};
}
struct OsInfo {
os: OsVariant,
linux_distro: Option<LinuxDistroVariant>,
}
fn resolve_linux_distro() -> LinuxDistroVariant {
let os_release = Path::new("/etc/os-release");
if let Ok(data) = std::fs::read_to_string(os_release) {
for line in data.split('\n') {
if line.starts_with("ID_LIKE=") {
if line.contains("debian") {
return LinuxDistroVariant::Debian;
} else if line.contains("rhel") || line.contains("fedora") {
return LinuxDistroVariant::RedHat;
}
} else if line.starts_with("ID=") && line.contains("fedora") {
return LinuxDistroVariant::RedHat;
}
}
}
LinuxDistroVariant::Unknown
}
fn resolve_os_info() -> OsInfo {
let os = TARGET_OS.clone();
let linux_distro = match os {
OsVariant::Linux => Some(resolve_linux_distro()),
_ => None,
};
OsInfo { os, linux_distro }
}
pub fn resolve_terminfo_dirs() -> Option<String> {
if std::env::var("TERMINFO_DIRS").is_ok() {
return None;
}
let os_info = resolve_os_info();
match os_info.os {
OsVariant::Linux => match os_info.linux_distro.unwrap() {
LinuxDistroVariant::Debian => Some(TERMINFO_DIRS_DEBIAN.to_string()),
LinuxDistroVariant::RedHat => Some(TERMINFO_DIRS_REDHAT.to_string()),
LinuxDistroVariant::Unknown => {
let paths = TERMINFO_DIRS_COMMON
.iter()
.filter_map(|p| {
if p.exists() {
Some(p.display().to_string())
} else {
None
}
})
.collect::<Vec<String>>()
.join(":");
Some(paths)
}
},
OsVariant::MacOs => Some(TERMINFO_DIRS_MACOS.to_string()),
OsVariant::Windows => None,
OsVariant::Other => None,
}
}