#!/usr/bin/env ruby require 'yaml' # guess output_format from ARGV def get_output_format() output_file = nil ARGV.each_with_index do |a, i| if a == "-o" || a == "--output" output_file = ARGV[i+1] elsif a.start_with? "--output=" output_file = a[9..-1] end end output_format = nil ARGV.each_with_index do |a, i| if a == "-t" || a == "--to" output_format = ARGV[i+1] elsif a.start_with? "--to=" output_format = a[5..-1] end end if output_format.nil? if !output_file.nil? && output_file.include?(".") output_format = output_file.split(".").last if ["pdf", "tex"].include? output_format output_format = "latex" end end end return output_format end def get_pandoc_opts() opts = %x(pandoc --bash-completion).scan(/opts\=\"([^"]*)/).first.first # strip the two preceding dashes and ignore one-letter variants opts.split(' ').map do |o| if o[0..1] == "--" o[2..-1] end end end # convert a meta-hash to an arguments-array def get_args(meta) pandoc_opts = get_pandoc_opts() args = [] meta.each do |key, val| # check whether `key` is an option that can be # used with the installed pandoc version if pandoc_opts.include? key opt = key else # since RMarkdown YAML uses e.g. `toc_depth` instead of `toc-depth` # try that as well: key = key.gsub('_', '-') if pandoc_opts.include? key opt = key end end if opt && val != false if val.is_a? Hash val.each do |k, v| args.push "--" ++ opt args.push k ++ "=" ++ v end elsif val.is_a? Array val.each do |v| args.push "--" ++ opt args.push v end else args.push "--" ++ opt if not (val.nil? || val.is_a?(TrueClass)) # try to only include a value for an option that takes one args.push val.to_s end end end end if more_args = meta['pandoc_args'] args.concat more_args end return args end def output_key_name() "output" end def data_dir_name() if ENV['APPDATA'] # Windows File.join ENV['APPDATA'], "panrun" else # POSIX File.join Dir.home, ".panrun" end end def load_yaml(file_name) begin # try ruby v3 arguments YAML.load_file(file_name, permitted_classes:["Date"]) rescue ArgumentError # fallback to ruby v2 arguments YAML.load_file(file_name) end end # try to load default YAML from other files and merge it with local YAML def get_meta_from_other_file(meta, type=nil) if not type.is_a?(String) type = "default" end data_dir = data_dir_name() file_name = if [".", "..", "/", "\\"].include? type[0] if File.file? type type else abort "Could not find file #{type}" end else # look in ~/.panrun/ name = File.join(data_dir, type + ".yaml") if File.file? name name else nil end end file_meta, args = if file_name && m = load_yaml(file_name) [ m[output_key_name] || {}, ["--metadata-file", file_name] ] else [{}, []] end file_meta.each do |format, _| meta[format] = file_meta[format].merge( meta[format] || {} ) end return [meta, args] end # determine input file input_file = ARGV[0] if input_file.nil? || input_file[0] == "-" abort "Usage: panrun input.md [pandoc-options]\n\n"\ "Looking for default.yaml etc. in #{data_dir_name}\n"\ "For more info, see https://github.com/mb21/panrun" end # load and merge various metadata yaml = load_yaml(input_file) || {} doc_meta = yaml[output_key_name] || {} meta, file_arg = get_meta_from_other_file doc_meta, yaml["type"] # determine output format output_format = get_output_format() if output_format.nil? if meta.is_a?(Hash) && meta.first # fallback to the first output key (hashes are ordered in ruby) output_format = meta.first[0] meta_val = meta.first[1] if not meta_val["to"] || meta_val["output"] STDERR.puts "panrun: [WARNING] defaulting to the YAML for output format '#{output_format}',\n"\ " but pandoc may not default to the same format.\n"\ " It is recommended to add a `to:` or `output:` field to your YAML." end else abort "Could not find any output format in YAML." end end # lookup format in meta, else try various rmarkdown formats meta_out = if meta[output_format] meta[output_format] elsif meta[output_format + "_document"] meta[output_format + "_document"] elsif output_format == "latex" && meta["pdf_document"] meta["pdf_document"] elsif meta[output_format + "_presentation"] meta[output_format + "_presentation"] else abort "Could not find YAML key for detected output format '#{output_format}'." end args = get_args(meta_out) args = ["pandoc", input_file] + args + file_arg + ARGV[1..-1] STDERR.puts "panrun calling: " + args.join(' ') exec *args