Skip to main content

test/term/terminfo/
searcher.rs

1//! ncurses-compatible database discovery.
2//!
3//! Does not support hashed database, only filesystem!
4
5use std::path::PathBuf;
6use std::{env, fs};
7
8#[cfg(test)]
9mod tests;
10
11/// Returns path to database entry for `term`
12pub(crate) fn get_dbpath_for_term(term: &str) -> Option<PathBuf> {
13    let mut dirs_to_search = Vec::new();
14    let first_char = term.chars().next()?;
15
16    // Find search directory
17    if let Some(dir) = env::var_os("TERMINFO") {
18        dirs_to_search.push(PathBuf::from(dir));
19    }
20
21    if let Ok(dirs) = env::var("TERMINFO_DIRS") {
22        for i in dirs.split(':') {
23            if i.is_empty() {
24                dirs_to_search.push(PathBuf::from("/usr/share/terminfo"));
25            } else {
26                dirs_to_search.push(PathBuf::from(i));
27            }
28        }
29    } else {
30        // Found nothing in TERMINFO_DIRS, use the default paths:
31        // According to /etc/terminfo/README, after looking at
32        // ~/.terminfo, ncurses will search /etc/terminfo, then
33        // /lib/terminfo, and eventually /usr/share/terminfo.
34        // On Haiku the database can be found at /boot/system/data/terminfo
35        if let Some(mut homedir) = env::home_dir() {
36            homedir.push(".terminfo");
37            dirs_to_search.push(homedir)
38        }
39
40        dirs_to_search.push(PathBuf::from("/etc/terminfo"));
41        dirs_to_search.push(PathBuf::from("/lib/terminfo"));
42        dirs_to_search.push(PathBuf::from("/usr/share/terminfo"));
43        dirs_to_search.push(PathBuf::from("/boot/system/data/terminfo"));
44    }
45
46    // Look for the terminal in all of the search directories
47    for mut p in dirs_to_search {
48        if fs::metadata(&p).is_ok() {
49            p.push(&first_char.to_string());
50            p.push(term);
51            if fs::metadata(&p).is_ok() {
52                return Some(p);
53            }
54            p.pop();
55            p.pop();
56
57            // on some installations the dir is named after the hex of the char
58            // (e.g., macOS)
59            p.push(&format!("{:x}", first_char as usize));
60            p.push(term);
61            if fs::metadata(&p).is_ok() {
62                return Some(p);
63            }
64        }
65    }
66    None
67}