]> git.lizzy.rs Git - rust.git/blob - src/libterm/terminfo/searcher.rs
Various minor/cosmetic improvements to code
[rust.git] / src / libterm / terminfo / searcher.rs
1 // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! ncurses-compatible database discovery
12 //!
13 //! Does not support hashed database, only filesystem!
14
15 use std::env;
16 use std::fs;
17 use std::path::PathBuf;
18
19 /// Return path to database entry for `term`
20 #[allow(deprecated)]
21 pub fn get_dbpath_for_term(term: &str) -> Option<PathBuf> {
22     let mut dirs_to_search = Vec::new();
23     let first_char = term.chars().next()?;
24
25     // Find search directory
26     if let Some(dir) = env::var_os("TERMINFO") {
27         dirs_to_search.push(PathBuf::from(dir));
28     }
29
30     if let Ok(dirs) = env::var("TERMINFO_DIRS") {
31         for i in dirs.split(':') {
32             if i == "" {
33                 dirs_to_search.push(PathBuf::from("/usr/share/terminfo"));
34             } else {
35                 dirs_to_search.push(PathBuf::from(i));
36             }
37         }
38     } else {
39         // Found nothing in TERMINFO_DIRS, use the default paths:
40         // According to  /etc/terminfo/README, after looking at
41         // ~/.terminfo, ncurses will search /etc/terminfo, then
42         // /lib/terminfo, and eventually /usr/share/terminfo.
43         // On Haiku the database can be found at /boot/system/data/terminfo
44         if let Some(mut homedir) = env::home_dir() {
45             homedir.push(".terminfo");
46             dirs_to_search.push(homedir)
47         }
48
49         dirs_to_search.push(PathBuf::from("/etc/terminfo"));
50         dirs_to_search.push(PathBuf::from("/lib/terminfo"));
51         dirs_to_search.push(PathBuf::from("/usr/share/terminfo"));
52         dirs_to_search.push(PathBuf::from("/boot/system/data/terminfo"));
53     }
54
55     // Look for the terminal in all of the search directories
56     for mut p in dirs_to_search {
57         if fs::metadata(&p).is_ok() {
58             p.push(&first_char.to_string());
59             p.push(&term);
60             if fs::metadata(&p).is_ok() {
61                 return Some(p);
62             }
63             p.pop();
64             p.pop();
65
66             // on some installations the dir is named after the hex of the char
67             // (e.g., macOS)
68             p.push(&format!("{:x}", first_char as usize));
69             p.push(term);
70             if fs::metadata(&p).is_ok() {
71                 return Some(p);
72             }
73         }
74     }
75     None
76 }
77
78 #[test]
79 #[ignore(reason = "buildbots don't have ncurses installed and I can't mock everything I need")]
80 fn test_get_dbpath_for_term() {
81     // woefully inadequate test coverage
82     // note: current tests won't work with non-standard terminfo hierarchies (e.g., macOS's)
83     use std::env;
84     // FIXME (#9639): This needs to handle non-utf8 paths
85     fn x(t: &str) -> String {
86         let p = get_dbpath_for_term(t).expect("no terminfo entry found");
87         p.to_str().unwrap().to_string()
88     }
89     assert!(x("screen") == "/usr/share/terminfo/s/screen");
90     assert!(get_dbpath_for_term("") == None);
91     env::set_var("TERMINFO_DIRS", ":");
92     assert!(x("screen") == "/usr/share/terminfo/s/screen");
93     env::remove_var("TERMINFO_DIRS");
94 }