(index<- )        ./libterm/terminfo/searcher.rs

    git branch:    * master           5200215 auto merge of #14035 : alexcrichton/rust/experimental, r=huonw
    modified:    Fri May  9 13:02:28 2014
   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::io::File;
  16  use std::os::getenv;
  17  use std::{os, str};
  18  
  19  /// Return path to database entry for `term`
  20  pub fn get_dbpath_for_term(term: &str) -> Option<Box<Path>> {
  21      if term.len() == 0 {
  22          return None;
  23      }
  24  
  25      let homedir = os::homedir();
  26  
  27      let mut dirs_to_search = Vec::new();
  28      let first_char = term.char_at(0);
  29  
  30      // Find search directory
  31      match getenv("TERMINFO") {
  32          Some(dir) => dirs_to_search.push(Path::new(dir)),
  33          None => {
  34              if homedir.is_some() {
  35                  // ncurses compatability;
  36                  dirs_to_search.push(homedir.unwrap().join(".terminfo"))
  37              }
  38              match getenv("TERMINFO_DIRS") {
  39                  Some(dirs) => for i in dirs.split(':') {
  40                      if i == "" {
  41                          dirs_to_search.push(Path::new("/usr/share/terminfo"));
  42                      } else {
  43                          dirs_to_search.push(Path::new(i.to_owned()));
  44                      }
  45                  },
  46                  // Found nothing in TERMINFO_DIRS, use the default paths:
  47                  // According to  /etc/terminfo/README, after looking at
  48                  // ~/.terminfo, ncurses will search /etc/terminfo, then
  49                  // /lib/terminfo, and eventually /usr/share/terminfo.
  50                  None => {
  51                      dirs_to_search.push(Path::new("/etc/terminfo"));
  52                      dirs_to_search.push(Path::new("/lib/terminfo"));
  53                      dirs_to_search.push(Path::new("/usr/share/terminfo"));
  54                  }
  55              }
  56          }
  57      };
  58  
  59      // Look for the terminal in all of the search directories
  60      for p in dirs_to_search.iter() {
  61          if p.exists() {
  62              let f = str::from_char(first_char);
  63              let newp = p.join_many([f.as_slice(), term]);
  64              if newp.exists() {
  65                  return Some(box newp);
  66              }
  67              // on some installations the dir is named after the hex of the char (e.g. OS X)
  68              let f = format!("{:x}", first_char as uint);
  69              let newp = p.join_many([f.as_slice(), term]);
  70              if newp.exists() {
  71                  return Some(box newp);
  72              }
  73          }
  74      }
  75      None
  76  }
  77  
  78  /// Return open file for `term`
  79  pub fn open(term: &str) -> Result<File, ~str> {
  80      match get_dbpath_for_term(term) {
  81          Some(x) => {
  82              match File::open(x) {
  83                  Ok(file) => Ok(file),
  84                  Err(e) => Err(format!("error opening file: {}", e)),
  85              }
  86          }
  87          None => Err(format!("could not find terminfo entry for {}", term))
  88      }
  89  }
  90  
  91  #[test]
  92  #[ignore(reason = "buildbots don't have ncurses installed and I can't mock everything I need")]
  93  fn test_get_dbpath_for_term() {
  94      // woefully inadequate test coverage
  95      // note: current tests won't work with non-standard terminfo hierarchies (e.g. OS X's)
  96      use std::os::{setenv, unsetenv};
  97      // FIXME (#9639): This needs to handle non-utf8 paths
  98      fn x(t: &str) -> ~str {
  99          let p = get_dbpath_for_term(t).expect("no terminfo entry found");
 100          p.as_str().unwrap().to_owned()
 101      };
 102      assert!(x("screen") == "/usr/share/terminfo/s/screen".to_owned());
 103      assert!(get_dbpath_for_term("") == None);
 104      setenv("TERMINFO_DIRS", ":");
 105      assert!(x("screen") == "/usr/share/terminfo/s/screen".to_owned());
 106      unsetenv("TERMINFO_DIRS");
 107  }
 108  
 109  #[test]
 110  #[ignore(reason = "see test_get_dbpath_for_term")]
 111  fn test_open() {
 112      open("screen").unwrap();
 113      let t = open("nonexistent terminal that hopefully does not exist");
 114      assert!(t.is_err());
 115  }