main.rs 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  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 = "cat"]
  6. #![feature(path_ext)]
  7. static VERS: &'static str = "0.1.0";
  8. static PROG: &'static str = "cat";
  9. extern crate getopts;
  10. extern crate util;
  11. use getopts::{Options};
  12. use util::{Status};
  13. use std::env;
  14. use std::io::Read;
  15. use std::path::{PathBuf};
  16. use std::fs::{File,PathExt};
  17. fn files_to_string(file: Vec<String>) -> String {
  18. let mut return_string = String::new();
  19. for item in file {
  20. let mut fstring = String::new();
  21. let fpath = PathBuf::from(&item);
  22. if fpath.is_dir() {
  23. util::path_err(Status::Error, String::from("cat: file is a directory"), fpath);
  24. }
  25. let mut ffile = match File::open(PathBuf::from(&item)) {
  26. Ok(f) => { f },
  27. Err(e) => {
  28. util::err(PROG, Status::Error, e.to_string());
  29. panic!();
  30. }
  31. };
  32. match ffile.read_to_string(&mut fstring) {
  33. Ok(_) => { return_string.push_str(&fstring) },
  34. Err(e) => {
  35. util::err(PROG, Status::Error, e.to_string());
  36. panic!();
  37. }
  38. };
  39. }
  40. return return_string;
  41. }
  42. fn print_lines(file: String, new: bool, tabs: bool, num: bool) {
  43. let mut lineno: i32 = 1;
  44. let num_lines: u32 = file.lines().count() as u32;
  45. if num {
  46. print!("{} ", lineno);
  47. }
  48. for i in file.chars() {
  49. if num && new && i == '\n' {
  50. if lineno < num_lines as i32 {
  51. lineno += 1;
  52. print!("$\n{} ", lineno);
  53. }
  54. } else if num && i == '\n' {
  55. if lineno < num_lines as i32 {
  56. lineno += 1;
  57. print!("{}{} ", i, lineno);
  58. }
  59. } else if i == '\n' && new {
  60. print!("$\n");
  61. } else if i == '\t' && tabs {
  62. print!("^I");
  63. } else {
  64. print!("{}", i);
  65. }
  66. }
  67. }
  68. fn print_usage(prog: &str, opts: Options) {
  69. let brief = format!("Usage: {} [OPTION]", prog);
  70. print!("{}", opts.usage(&brief));
  71. util::exit(Status::Ok);
  72. }
  73. fn main() {
  74. let args: Vec<String> = env::args().collect();
  75. let mut opts = Options::new();
  76. opts.optflag("h", "help", "Print the help menu");
  77. opts.optflag("", "version", "Print the version");
  78. opts.optflag("a", "all", "Show all characters");
  79. opts.optflag("n", "numbered", "Show numbered lines");
  80. opts.optflag("E", "ends", "Show newline characters as '$'");
  81. opts.optflag("t", "tabs", "Show tab characters as '^I'");
  82. let matches = match opts.parse(&args[1..]) {
  83. Ok(m) => { m }
  84. Err(f) => {
  85. util::err(PROG, Status::OptError, f.to_string());
  86. panic!(f)
  87. }
  88. };
  89. let tabs = matches.opt_present("t");
  90. let new = matches.opt_present("E");
  91. let num = matches.opt_present("n");
  92. if matches.opt_present("h") {
  93. print_usage(PROG, opts);
  94. } else if matches.opt_present("version") {
  95. util::copyright(PROG, VERS, "2015", vec!["Alberto Corona"]);
  96. } else if matches.opt_present("a") {
  97. print_lines(files_to_string(matches.free), true, true, num);
  98. } else {
  99. print_lines(files_to_string(matches.free), new, tabs, num);
  100. }
  101. }