term/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
15use std::env;
16use std::fs;
17use std::path::PathBuf;
18
19/// Return path to database entry for `term`
20pub fn get_dbpath_for_term(term: &str) -> Option<PathBuf> {
21    let mut dirs_to_search = Vec::new();
22    let first_char = match term.chars().next() {
23        Some(c) => c,
24        None => return None,
25    };
26
27    // Find search directory
28    // The terminfo manual says:
29    //
30    // > If  the  environment  variable  TERMINFO is set, it is interpreted
31    // > as the pathname of a directory containing the compiled description
32    // > you are working on.  Only that directory is searched.
33    //
34    // However, the ncurses manual says:
35    //
36    // > If the environment variable TERMINFO is defined, any program using
37    // > curses checks for a local terminal definition  before  checking in
38    // > the standard place.
39    //
40    // Given that ncurses is the defacto standard, we follow the ncurses manual.
41    if let Some(dir) = env::var_os("TERMINFO") {
42        dirs_to_search.push(PathBuf::from(dir));
43    }
44
45    if let Ok(dirs) = env::var("TERMINFO_DIRS") {
46        for i in dirs.split(':') {
47            if i == "" {
48                dirs_to_search.push(PathBuf::from("/usr/share/terminfo"));
49            } else {
50                dirs_to_search.push(PathBuf::from(i));
51            }
52        }
53    } else {
54        // Found nothing in TERMINFO_DIRS, use the default paths:
55        // According to  /etc/terminfo/README, after looking at
56        // ~/.terminfo, ncurses will search /etc/terminfo, then
57        // /lib/terminfo, and eventually /usr/share/terminfo.
58        // On Haiku the database can be found at /boot/system/data/terminfo
59        if let Some(mut homedir) = env::home_dir() {
60            homedir.push(".terminfo");
61            dirs_to_search.push(homedir)
62        }
63
64        dirs_to_search.push(PathBuf::from("/etc/terminfo"));
65        dirs_to_search.push(PathBuf::from("/lib/terminfo"));
66        dirs_to_search.push(PathBuf::from("/usr/share/terminfo"));
67        dirs_to_search.push(PathBuf::from("/boot/system/data/terminfo"));
68    }
69
70    // Look for the terminal in all of the search directories
71    for mut p in dirs_to_search {
72        if fs::metadata(&p).is_ok() {
73            p.push(&first_char.to_string());
74            p.push(&term);
75            if fs::metadata(&p).is_ok() {
76                return Some(p);
77            }
78            p.pop();
79            p.pop();
80
81            // on some installations the dir is named after the hex of the char
82            // (e.g. OS X)
83            p.push(&format!("{:x}", first_char as usize));
84            p.push(term);
85            if fs::metadata(&p).is_ok() {
86                return Some(p);
87            }
88        }
89    }
90    None
91}