main.rs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. // Copyright (C) 2015, Alberto Corona <alberto@0x1a.us>
  2. // All rights reserved. This file is part of core-utils, distributed under the
  3. // GPL v3 license. For full terms please see the LICENSE file.
  4. #![crate_type = "bin"]
  5. #![crate_name = "ls"]
  6. #![feature(path_ext)]
  7. static VERS: &'static str = "0.1.0";
  8. static PROG: &'static str = "ls";
  9. extern crate getopts;
  10. extern crate util;
  11. use getopts::{Options};
  12. use util::{Status};
  13. use std::fs;
  14. use std::env;
  15. use std::io;
  16. use std::fs::{PathExt};
  17. use std::path::{PathBuf};
  18. enum Format {
  19. Long,
  20. Short,
  21. }
  22. fn is_dot(dir: &PathBuf) -> bool {
  23. let dir_str = match dir.to_str() {
  24. Some(s) => { s },
  25. None => { panic!() },
  26. };
  27. if dir_str.starts_with(".") {
  28. return true;
  29. } else {
  30. return false;
  31. }
  32. }
  33. fn format_print(rel_path: &PathBuf, path: &PathBuf, format: &Format) {
  34. match format {
  35. &Format::Short => {
  36. if path.is_dir() {
  37. print!("{}/ ", rel_path.display());
  38. } else {
  39. print!("{} ", rel_path.display());
  40. }
  41. }
  42. &Format::Long => {
  43. if path.is_dir() {
  44. println!("{}/ ", rel_path.display());
  45. } else {
  46. println!("{} ", rel_path.display());
  47. }
  48. }
  49. };
  50. }
  51. fn print(path: &Vec<String>, format: Format, all: bool) -> io::Result<()> {
  52. for item in path.iter() {
  53. let fpath = PathBuf::from(item);
  54. if fpath.is_dir() {
  55. for entry in try!(fs::read_dir(&fpath)) {
  56. let entry = try!(entry);
  57. let rel_path = util::to_rel(&entry.path(), &fpath);
  58. match format {
  59. Format::Short => {
  60. if all {
  61. format_print(&rel_path, &entry.path(), &format);
  62. } else {
  63. if !is_dot(&rel_path) {
  64. format_print(&rel_path, &entry.path(), &format);
  65. }
  66. }
  67. }
  68. Format::Long => {
  69. if all {
  70. format_print(&rel_path, &entry.path(), &format);
  71. } else {
  72. if !is_dot(&rel_path) {
  73. format_print(&rel_path, &entry.path(), &format);
  74. }
  75. }
  76. }
  77. }
  78. }
  79. }
  80. }
  81. return Ok(());
  82. }
  83. fn print_usage(prog: &str, opts: Options) {
  84. let brief = format!("Usage: {} [OPTION]", prog);
  85. print!("{}", opts.usage(&brief));
  86. util::exit(Status::Ok);
  87. }
  88. fn main() {
  89. let args: Vec<String> = env::args().collect();
  90. let mut opts = Options::new();
  91. opts.optflag("h", "help", "Print the help menu");
  92. opts.optflag("", "version", "Print the version of ls");
  93. opts.optflag("a", "all", "Display hidden files");
  94. opts.optflag("l", "long", "Use the long listing option");
  95. let matches = match opts.parse(&args[1..]) {
  96. Ok(m) => { m }
  97. Err(f) => {
  98. util::err(PROG, Status::Error, f.to_string());
  99. panic!(f.to_string())
  100. }
  101. };
  102. let mut current = Vec::new();
  103. current.push(String::from(env::current_dir().unwrap().to_str().unwrap()));
  104. let all = matches.opt_present("a");
  105. if matches.opt_present("h") {
  106. print_usage(PROG, opts);
  107. } else if matches.opt_present("version") {
  108. util::copyright(PROG, VERS, "2015", vec!["Alberto Corona"]);
  109. } else if matches.opt_present("l") {
  110. if !matches.free.is_empty() {
  111. print(&matches.free, Format::Long, all).ok();
  112. } else {
  113. print(&current, Format::Long, all).ok();
  114. }
  115. } else {
  116. if matches.free.is_empty() {
  117. print(&current, Format::Short, all).ok();
  118. } else {
  119. print(&matches.free, Format::Short, all).ok();
  120. }
  121. }
  122. }