format.rs 3.1 KB

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