format.rs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. extern crate clap;
  2. extern crate rrecutils;
  3. extern crate rustache;
  4. use std::{fs,io};
  5. use std::convert::From;
  6. use std::string::FromUtf8Error;
  7. mod common;
  8. use rustache::Render;
  9. struct R {
  10. rec: rrecutils::Record
  11. }
  12. impl Render for R {
  13. fn render<W: io::Write>(
  14. &self,
  15. template: &str,
  16. writer: &mut W,
  17. ) -> Result<(), rustache::RustacheError>
  18. {
  19. use rustache::HashBuilder;
  20. let mut hb = HashBuilder::new();
  21. if let Some(ref t) = self.rec.rec_type {
  22. hb = hb.insert("%rec", t.clone());
  23. }
  24. for field in self.rec.fields.iter() {
  25. hb = hb.insert(&field.0, field.1.clone());
  26. }
  27. hb.render(template, writer)
  28. }
  29. }
  30. enum FormatErr {
  31. IOError(io::Error),
  32. Utf8Error(FromUtf8Error),
  33. Rustache(rustache::RustacheError),
  34. Generic(String),
  35. }
  36. impl From<io::Error> for FormatErr {
  37. fn from(err: io::Error) -> FormatErr {
  38. FormatErr::IOError(err)
  39. }
  40. }
  41. impl From<FromUtf8Error> for FormatErr {
  42. fn from(err: FromUtf8Error) -> FormatErr {
  43. FormatErr::Utf8Error(err)
  44. }
  45. }
  46. impl From<rustache::RustacheError> for FormatErr {
  47. fn from(err: rustache::RustacheError) -> FormatErr {
  48. FormatErr::Rustache(err)
  49. }
  50. }
  51. impl From<String> for FormatErr {
  52. fn from(err: String) -> FormatErr {
  53. FormatErr::Generic(err)
  54. }
  55. }
  56. fn rr_format_args() -> clap::ArgMatches<'static> {
  57. clap::App::new("rr-format")
  58. .version(common::VERSION)
  59. .author(common::AUTHOR)
  60. .about("Display the Rust AST for a Recutils file")
  61. .arg(clap::Arg::with_name("input")
  62. .short("i")
  63. .long("input")
  64. .value_name("FILE")
  65. .help("The input recfile (or - for stdin)"))
  66. .arg(clap::Arg::with_name("output")
  67. .short("o")
  68. .long("output")
  69. .value_name("FILE")
  70. .help("The desired output location (or - for stdout)"))
  71. .arg(clap::Arg::with_name("mustache")
  72. .short("m")
  73. .long("mustache")
  74. .value_name("FILE")
  75. .help("The mustache template to use"))
  76. .arg(clap::Arg::with_name("type")
  77. .short("t")
  78. .long("type")
  79. .value_name("TYPE")
  80. .takes_value(true)
  81. .help("The type of records to pass to the mustache file"))
  82. .arg(clap::Arg::with_name("joiner")
  83. .short("j")
  84. .long("joiner")
  85. .value_name("STRING")
  86. .help("The string used to separate each fragment"))
  87. .get_matches()
  88. }
  89. fn run() -> Result<(), FormatErr> {
  90. let matches = rr_format_args();
  91. let input = common::input_from_spec(
  92. matches.value_of("input"))?;
  93. let mut output = common::output_from_spec(
  94. matches.value_of("output"))?;
  95. let template: String = match matches.value_of("mustache") {
  96. Some(path) => {
  97. use io::Read;
  98. let mut buf = Vec::new();
  99. fs::File::open(path)?.read_to_end(&mut buf)?;
  100. String::from_utf8(buf)?
  101. },
  102. None => Err(format!("No template specified!"))?,
  103. };
  104. let mut recfile = rrecutils::Recfile::parse(input)?;
  105. if let Some(typ) = matches.value_of("type") {
  106. recfile.filter_by_type(typ);
  107. }
  108. let joiner = matches.value_of("joiner");
  109. let mut first = true;
  110. for r in recfile.records.into_iter() {
  111. if first {
  112. first = false;
  113. } else if let Some(j) = joiner {
  114. output.write(j.as_bytes())?;
  115. output.write(&['\n' as u8])?;
  116. }
  117. R { rec: r }.render(&template, &mut output.as_mut())?;
  118. }
  119. Ok(())
  120. }
  121. fn main() {
  122. use FormatErr::*;
  123. match run() {
  124. Ok(()) => (),
  125. Err(IOError(_)) => panic!("IO Error"),
  126. Err(Utf8Error(_)) => panic!("Cannot decode as UTF-8"),
  127. Err(Rustache(r)) => panic!("Rustache error: {:?}", r),
  128. Err(Generic(s)) => panic!("{}", s),
  129. }
  130. }