main.rs 4.2 KB

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