rust/src/libterm/terminfo/searcher.rs
Bryce Van Dyk 0ee230a094 libterm: bring across changes from term
This brings across changes made to the term library to libterm. This
includes removing instances or unwrap, fixing format string handling, and
removing a TODO.

This fix does not bring all changes across, as term now relies on cargo
deps that cannot be brought into the rust build at this stage, but has
attempted as best to cross port changes not relying on this. This notably
limits extra functionality since implemented int he Terminal trait in
Term.

This is in partly in response to rust issue #29992.
2015-12-03 19:27:59 +13:00

99 lines
3.5 KiB
Rust

// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! ncurses-compatible database discovery
//!
//! Does not support hashed database, only filesystem!
use std::env;
use std::fs;
use std::path::PathBuf;
/// Return path to database entry for `term`
#[allow(deprecated)]
pub fn get_dbpath_for_term(term: &str) -> Option<PathBuf> {
let mut dirs_to_search = Vec::new();
let first_char = match term.chars().next() {
Some(c) => c,
None => return None,
};
// Find search directory
match env::var_os("TERMINFO") {
Some(dir) => dirs_to_search.push(PathBuf::from(dir)),
None => {
if let Some(mut homedir) = env::home_dir() {
// ncurses compatibility;
homedir.push(".terminfo");
dirs_to_search.push(homedir)
}
match env::var("TERMINFO_DIRS") {
Ok(dirs) => {
for i in dirs.split(':') {
if i == "" {
dirs_to_search.push(PathBuf::from("/usr/share/terminfo"));
} else {
dirs_to_search.push(PathBuf::from(i));
}
}
}
// Found nothing in TERMINFO_DIRS, use the default paths:
// According to /etc/terminfo/README, after looking at
// ~/.terminfo, ncurses will search /etc/terminfo, then
// /lib/terminfo, and eventually /usr/share/terminfo.
Err(..) => {
dirs_to_search.push(PathBuf::from("/etc/terminfo"));
dirs_to_search.push(PathBuf::from("/lib/terminfo"));
dirs_to_search.push(PathBuf::from("/usr/share/terminfo"));
}
}
}
};
// Look for the terminal in all of the search directories
for mut p in dirs_to_search {
if fs::metadata(&p).is_ok() {
p.push(&first_char.to_string());
p.push(&term);
if fs::metadata(&p).is_ok() {
return Some(p);
}
p.pop();
p.pop();
// on some installations the dir is named after the hex of the char
// (e.g. OS X)
p.push(&format!("{:x}", first_char as usize));
p.push(term);
if fs::metadata(&p).is_ok() {
return Some(p);
}
}
}
None
}
#[test]
#[ignore(reason = "buildbots don't have ncurses installed and I can't mock everything I need")]
fn test_get_dbpath_for_term() {
// woefully inadequate test coverage
// note: current tests won't work with non-standard terminfo hierarchies (e.g. OS X's)
use std::env;
// FIXME (#9639): This needs to handle non-utf8 paths
fn x(t: &str) -> String {
let p = get_dbpath_for_term(t).expect("no terminfo entry found");
p.to_str().unwrap().to_string()
}
assert!(x("screen") == "/usr/share/terminfo/s/screen");
assert!(get_dbpath_for_term("") == None);
env::set_var("TERMINFO_DIRS", ":");
assert!(x("screen") == "/usr/share/terminfo/s/screen");
env::remove_var("TERMINFO_DIRS");
}