Permalink
Cannot retrieve contributors at this time
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
executable file
185 lines (167 sloc)
4.94 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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 | |
| # 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 = YAML.load_file(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 = YAML.load_file(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 |