main.rs 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. #![feature(iter_arith)]
  2. #![feature(convert, fs_mode)]
  3. #![feature(slice_splits, vec_resize)]
  4. extern crate ansi_term;
  5. extern crate datetime;
  6. extern crate getopts;
  7. extern crate libc;
  8. extern crate locale;
  9. extern crate natord;
  10. extern crate num_cpus;
  11. extern crate number_prefix;
  12. extern crate pad;
  13. extern crate scoped_threadpool;
  14. extern crate term_grid;
  15. extern crate unicode_width;
  16. extern crate users;
  17. #[cfg(feature="git")]
  18. extern crate git2;
  19. use std::env;
  20. use std::path::{Component, Path};
  21. use std::process;
  22. use dir::Dir;
  23. use file::File;
  24. use options::{Options, View};
  25. mod colours;
  26. mod column;
  27. mod dir;
  28. mod feature;
  29. mod file;
  30. mod filetype;
  31. mod options;
  32. mod output;
  33. mod term;
  34. #[cfg(not(test))]
  35. struct Exa {
  36. options: Options,
  37. }
  38. #[cfg(not(test))]
  39. impl Exa {
  40. fn new(options: Options) -> Exa {
  41. Exa { options: options }
  42. }
  43. fn run(&mut self, args_file_names: &[String]) {
  44. let mut files = Vec::new();
  45. let mut dirs = Vec::new();
  46. for file_name in args_file_names.iter() {
  47. match File::from_path(Path::new(&file_name), None) {
  48. Err(e) => {
  49. println!("{}: {}", file_name, e);
  50. },
  51. Ok(f) => {
  52. if f.is_directory() && !self.options.dir_action.treat_dirs_as_files() {
  53. match f.to_dir(self.options.should_scan_for_git()) {
  54. Ok(d) => dirs.push(d),
  55. Err(e) => println!("{}: {}", file_name, e),
  56. }
  57. }
  58. else {
  59. files.push(f);
  60. }
  61. },
  62. }
  63. }
  64. let any_files = files.is_empty();
  65. self.print_files(None, files);
  66. let is_only_dir = dirs.len() == 1;
  67. self.print_dirs(dirs, any_files, is_only_dir);
  68. }
  69. fn print_dirs(&self, dir_files: Vec<Dir>, mut first: bool, is_only_dir: bool) {
  70. for dir in dir_files {
  71. // Put a gap between directories, or between the list of files and the
  72. // first directory.
  73. if first {
  74. first = false;
  75. }
  76. else {
  77. print!("\n");
  78. }
  79. if !is_only_dir {
  80. println!("{}:", dir.path.display());
  81. }
  82. let mut children = Vec::new();
  83. for file in dir.files() {
  84. match file {
  85. Ok(file) => children.push(file),
  86. Err((path, e)) => println!("[{}: {}]", path.display(), e),
  87. }
  88. };
  89. self.options.filter_files(&mut children);
  90. self.options.sort_files(&mut children);
  91. if let Some(recurse_opts) = self.options.dir_action.recurse_options() {
  92. let depth = dir.path.components().filter(|&c| c != Component::CurDir).count() + 1;
  93. if !recurse_opts.tree && !recurse_opts.is_too_deep(depth) {
  94. let mut child_dirs = Vec::new();
  95. for child_dir in children.iter().filter(|f| f.is_directory()) {
  96. match child_dir.to_dir(false) {
  97. Ok(d) => child_dirs.push(d),
  98. Err(e) => println!("{}: {}", child_dir.path.display(), e),
  99. }
  100. }
  101. self.print_files(Some(&dir), children);
  102. if !child_dirs.is_empty() {
  103. self.print_dirs(child_dirs, false, false);
  104. }
  105. continue;
  106. }
  107. }
  108. self.print_files(Some(&dir), children);
  109. }
  110. }
  111. fn print_files(&self, dir: Option<&Dir>, files: Vec<File>) {
  112. match self.options.view {
  113. View::Grid(g) => g.view(&files),
  114. View::Details(d) => d.view(dir, files),
  115. View::GridDetails(gd) => gd.view(dir, &files),
  116. View::Lines(l) => l.view(&files),
  117. }
  118. }
  119. }
  120. #[cfg(not(test))]
  121. fn main() {
  122. let args: Vec<String> = env::args().skip(1).collect();
  123. match Options::getopts(&args) {
  124. Ok((options, paths)) => {
  125. let mut exa = Exa::new(options);
  126. exa.run(&paths);
  127. },
  128. Err(e) => {
  129. println!("{}", e);
  130. process::exit(e.error_code());
  131. },
  132. };
  133. }