options.rs 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. extern crate getopts;
  2. use file::File;
  3. use std::cmp::lexical_ordering;
  4. use column::{Column, Permissions, FileName, FileSize, User, Group};
  5. use unix::get_current_user_id;
  6. pub enum SortField {
  7. Name, Extension, Size
  8. }
  9. pub struct Options {
  10. pub showInvisibles: bool,
  11. pub sortField: SortField,
  12. pub reverse: bool,
  13. pub dirs: Vec<String>,
  14. pub columns: Vec<Column>,
  15. }
  16. impl SortField {
  17. fn from_word(word: String) -> SortField {
  18. match word.as_slice() {
  19. "name" => Name,
  20. "size" => Size,
  21. "ext" => Extension,
  22. _ => fail!("Invalid sorting order"),
  23. }
  24. }
  25. }
  26. impl Options {
  27. pub fn getopts(args: Vec<String>) -> Result<Options, getopts::Fail_> {
  28. let opts = ~[
  29. getopts::optflag("a", "all", "show dot-files"),
  30. getopts::optflag("b", "binary", "use binary prefixes in file sizes"),
  31. getopts::optflag("g", "group", "show group as well as user"),
  32. getopts::optflag("r", "reverse", "reverse order of files"),
  33. getopts::optopt("s", "sort", "field to sort by", "WORD"),
  34. ];
  35. match getopts::getopts(args.tail(), opts) {
  36. Err(f) => Err(f),
  37. Ok(matches) => Ok(Options {
  38. showInvisibles: matches.opt_present("all"),
  39. reverse: matches.opt_present("reverse"),
  40. sortField: matches.opt_str("sort").map(|word| SortField::from_word(word)).unwrap_or(Name),
  41. dirs: matches.free.clone(),
  42. columns: Options::columns(matches),
  43. })
  44. }
  45. }
  46. fn columns(matches: getopts::Matches) -> Vec<Column> {
  47. let mut columns = vec![
  48. Permissions,
  49. FileSize(matches.opt_present("binary")),
  50. User(get_current_user_id()),
  51. ];
  52. if matches.opt_present("group") {
  53. columns.push(Group);
  54. }
  55. columns.push(FileName);
  56. return columns;
  57. }
  58. fn should_display(&self, f: &File) -> bool {
  59. if self.showInvisibles {
  60. true
  61. } else {
  62. !f.name.starts_with(".")
  63. }
  64. }
  65. pub fn transform_files<'a>(&self, unordered_files: &'a Vec<File<'a>>) -> Vec<&'a File<'a>> {
  66. let mut files: Vec<&'a File<'a>> = unordered_files.iter()
  67. .filter(|&f| self.should_display(f))
  68. .collect();
  69. match self.sortField {
  70. Name => files.sort_by(|a, b| a.name.cmp(&b.name)),
  71. Size => files.sort_by(|a, b| a.stat.size.cmp(&b.stat.size)),
  72. Extension => files.sort_by(|a, b| {
  73. let exts = a.ext.cmp(&b.ext);
  74. let names = a.name.cmp(&b.name);
  75. lexical_ordering(exts, names)
  76. }),
  77. }
  78. if self.reverse {
  79. files.reverse();
  80. }
  81. return files;
  82. }
  83. }