Class: Pandocomatic::Configuration

Inherits:
Object
  • Object
show all
Defined in:
lib/pandocomatic/configuration.rb

Overview

Configuration models a pandocomatic configuration.

Constant Summary collapse

CONFIG_FILE =

Pandocomatic’s default configuration file

'pandocomatic.yaml'

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options, input) ⇒ Configuration

Create a new Configuration instance based on the command-line options



191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
# File 'lib/pandocomatic/configuration.rb', line 191

def initialize(options, input)
  data_dirs = determine_data_dirs options
  @options = options
  @data_dir = data_dirs.first
  @settings = DEFAULT_SETTINGS
  @templates = {}
  @convert_patterns = {}

  load_configuration_hierarchy options, data_dirs

  # Check if template selected via CLI option exists
  if use_templates?
    non_existing_templates = selected_templates.reject { |t| template? t }

    unless non_existing_templates.empty?
      raise ConfigurationError.new(:templates_do_not_exist, nil, non_existing_templates)
    end
  end

  @input = if input.nil? || input.empty?
             nil
           elsif input.size > 1
             MultipleFilesInput.new(input, self)
           else
             Input.new(input)
           end

  @output = if output?
              options[:output]
            elsif to_stdout? options
              Tempfile.new(@input.base) unless @input.nil?
            elsif @input.is_a? Input
              @input.base
            end

  @root_path = Path.determine_root_path options

  # Extend the command classes by setting the source tree root
  # directory, and the options quiet and dry-run, which are used when
  # executing a command: if dry-run the command is not actually
  # executed and if quiet the command is not printed to STDOUT
  Command.reset(self)
end

Instance Attribute Details

#config_filesObject (readonly)

Returns the value of attribute config_files.



185
186
187
# File 'lib/pandocomatic/configuration.rb', line 185

def config_files
  @config_files
end

#data_dirObject (readonly)

Returns the value of attribute data_dir.



185
186
187
# File 'lib/pandocomatic/configuration.rb', line 185

def data_dir
  @data_dir
end

#inputObject (readonly)

Returns the value of attribute input.



185
186
187
# File 'lib/pandocomatic/configuration.rb', line 185

def input
  @input
end

#outputString (readonly)

Get the output file name

Returns:

  • (String)


411
412
413
# File 'lib/pandocomatic/configuration.rb', line 411

def output
  @output
end

#root_pathObject (readonly)

Returns the value of attribute root_path.



185
186
187
# File 'lib/pandocomatic/configuration.rb', line 185

def root_path
  @root_path
end

Instance Method Details

#clean_up!Object

Clean up this configuration. This will remove temporary files created for the conversion process guided by this Configuration.



445
446
447
448
449
# File 'lib/pandocomatic/configuration.rb', line 445

def clean_up!
  # If a temporary file has been created while concatenating
  # multiple input files, ensure it is removed.
  @input.destroy! if @input.is_a? MultipleFilesInput
end

#cloneObject

Create a copy of this configuration

@return [Configuration] copy


277
278
279
# File 'lib/pandocomatic/configuration.rb', line 277

def clone
  Marshal.load(Marshal.dump(self))
end

#config?Boolean

Is the config CLI option given?

Returns:

  • (Boolean)


371
372
373
# File 'lib/pandocomatic/configuration.rb', line 371

def config?
  @options[:config_given]
end

#configure(settings, path, recursive: false) ⇒ Object

Configure pandocomatic based on a settings Hash

Configuration. recursively? I.e., when running on a directory?

Parameters:

  • settings (Hash)

    a settings Hash to mixin in this

  • path (String)

    the configuration’s path or filename

  • recursive (Boolean) (defaults to: false)

    should this configuration be configured



288
289
290
291
292
293
294
295
296
# File 'lib/pandocomatic/configuration.rb', line 288

def configure(settings, path, recursive: false)
  reset_settings settings['settings'] if settings.key? 'settings'

  return unless settings.key? 'templates'

  settings['templates'].each do |name, template|
    reset_template Template.new(name, template, path), recursive:
  end
end

#convert?(src) ⇒ Boolean

Should the source file be converted given this Configuration?

Parameters:

  • src (String)

    True if this source file matches the ‘glob’ patterns in a template, false otherwise.

Returns:

  • (Boolean)


503
504
505
# File 'lib/pandocomatic/configuration.rb', line 503

def convert?(src)
  @convert_patterns.values.flatten.any? { |glob| File.fnmatch glob, File.basename(src) }
end

#data_dir?Boolean

Is the data dir CLI option given?

Returns:

  • (Boolean)


357
358
359
# File 'lib/pandocomatic/configuration.rb', line 357

def data_dir?
  @options[:data_dir_given]
end

#determine_template(src) ⇒ String

Determine the template to use with this source document given this Configuration.

Parameters:

  • src (String)

    path to the source document

Returns:

  • (String)

    the template’s name to use



683
684
685
686
687
# File 'lib/pandocomatic/configuration.rb', line 683

def determine_template(src)
  @convert_patterns.select do |_, globs|
    globs.any? { |glob| File.fnmatch glob, File.basename(src) }
  end.keys.first
end

#determine_templates(src) ⇒ Array[String]

Determine the templates to use with this source document given this Configuration.

Parameters:

  • src (String)

    path to the source document

Returns:

  • (Array[String])

    the template’s name to use



694
695
696
697
698
699
700
701
702
703
704
705
706
# File 'lib/pandocomatic/configuration.rb', line 694

def determine_templates(src)
  matches = @convert_patterns.select do |_, globs|
    globs.any? { |glob| File.fnmatch glob, File.basename(src) }
  end.keys

  if matches.empty?
    []
  elsif match_all_templates?
    matches
  else
    [matches.first]
  end
end

#directory?Boolean

Is this Configuration for converting directories?

Returns:

  • (Boolean)


439
440
441
# File 'lib/pandocomatic/configuration.rb', line 439

def directory?
  !@input.nil? and @input.directory?
end

#dry_run?Boolean

Is the dry run CLI option given?

Returns:

  • (Boolean)


308
309
310
# File 'lib/pandocomatic/configuration.rb', line 308

def dry_run?
  @options[:dry_run_given] and @options[:dry_run]
end

#feature_enabled?(feature) ⇒ Boolean

Should given feature be enabled?

Parameters:

  • feature (Symbol)

    feature toggle to check

Returns:

  • (Boolean)


379
380
381
# File 'lib/pandocomatic/configuration.rb', line 379

def feature_enabled?(feature)
  @options[:enable_given] and Pandocomatic::FEATURES.include?(feature) and @options[:enable].include?(feature)
end

#find_extension(template_name, metadata) ⇒ String

Find the extension of the destination file given this Confguration, template, and metadata

Parameters:

  • template_name (String)

    the name of the template used to convert to destination

  • metadata (PandocMetadata)

    the metadata in the source file

Returns:

  • (String)

    the extension to use for the destination file



615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
# File 'lib/pandocomatic/configuration.rb', line 615

def find_extension(template_name, )
  extension = 'html'

  # Pandoc supports enabling / disabling extensions
  # using +EXTENSION and -EXTENSION
  strip_extensions = ->(format) { format.split(/[+-]/).first }
  use_extension = lambda do |pandoc|
    pandoc['use-extension'] if pandoc.key? 'use-extension'
  end

  if template_name.nil? || template_name.empty?
    ext = use_extension.call .pandoc_options
    if !ext.nil?
      extension = ext
    elsif .pandoc_options.key? 'to'
      extension = strip_extensions.call(.pandoc_options['to'])
    end
  elsif @templates[template_name].pandoc?
    pandoc = @templates[template_name].pandoc
    ext = use_extension.call pandoc

    if !ext.nil?
      extension = ext
    elsif pandoc.key? 'to'
      extension = strip_extensions.call(pandoc['to'])
    end
  end

  DEFAULT_EXTENSION[extension] || extension
end

#follow_links?Boolean

Should pandocomatic follow symbolic links given this Configuration?

Returns:

  • (Boolean)

    True if the setting ‘follow_links’ is true, false otherwise



519
520
521
# File 'lib/pandocomatic/configuration.rb', line 519

def follow_links?
  @settings.key? 'follow_links' and @settings['follow_links']
end

#get_metadata(src, template_name = nil) ⇒ PandocMetadata

Get a pandoc metadata object for given source file and template.

Parameters:

  • src (String)

    path to source file

  • template_name (String) (defaults to: nil)

    template used; optional parameter

Returns:

  • (PandocMetadata)

    Pandoc’s metadata for given file and template.



469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
# File 'lib/pandocomatic/configuration.rb', line 469

def (src, template_name = nil)
  if (src)
    PandocMetadata.load_file src, ignore_pandocomatic: use_templates?
  else
    src_format = nil

    # Determine source format based on template
    if template_name && @templates.key?(template_name) && @templates[template_name].pandoc?
      pandoc = @templates[template_name].pandoc
      src_format = pandoc['from'] if pandoc.key? 'from'
    end

    if src_format.nil?
      # Determine source format based on extension like pandoc does.
      # See https://github.com/jgm/pandoc/blob/main/src/Text/Pandoc/Format.hs
      # for that mapping
      src_extension = File.extname src
      src_format = PANDOCS_EXTENSION_TO_FORMAT_MAPPING[src_extension]
    end

    if !src_format || src_format.match?(/markdown(((\+|-).+)|$)/)
      # Behave like pandoc: If no source format can be determined, assume markdown.
      # If format is markdown, ignore any extensions.
      PandocMetadata.load_file src, ignore_pandocomatic: use_templates?
    else
      PandocMetadata.empty src_format, ignore_pandocomatic: use_templates?
    end
  end
end

#get_template(template_name) ⇒ Template

Get the template with template_name from this Configuration

Parameters:

  • template_name (String)

    a template’s name

Returns:

  • (Template)

    The template with template_name.



674
675
676
# File 'lib/pandocomatic/configuration.rb', line 674

def get_template(template_name)
  @templates[template_name]
end

#input?Boolean

Have input CLI options be given?

Returns:

  • (Boolean)


421
422
423
# File 'lib/pandocomatic/configuration.rb', line 421

def input?
  @options[:input_given]
end

#input_fileString

Get the input file name

Returns:

  • (String)


428
429
430
431
432
433
434
# File 'lib/pandocomatic/configuration.rb', line 428

def input_file
  if @input.nil?
    nil
  else
    @input.name
  end
end

#load(filename) ⇒ Configuration

Read a configuration file and create a pandocomatic configuration object

Parameters:

  • filename (String)

    Path to the configuration yaml file

Returns:



239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
# File 'lib/pandocomatic/configuration.rb', line 239

def load(filename)
  begin
    path = File.absolute_path filename
    settings = PandocomaticYAML.load_file path
    if settings['settings'] && settings['settings']['data-dir']
      data_dir = settings['settings']['data-dir']
      src_dir = File.dirname filename
      @data_dir = if data_dir.start_with? '.'
                    File.absolute_path data_dir, src_dir
                  else
                    data_dir
                  end
    end
  rescue StandardError => e
    raise ConfigurationError.new(:unable_to_load_config_file, e, filename)
  end

  configure settings, filename
end

#markdown_file?(filename) ⇒ Boolean

Is filename a markdown file according to its extension?

Parameters:

  • filename (String)

    the filename to check

Returns:

  • (Boolean)

    True if filename has a markdown extension.



650
651
652
653
654
655
656
657
# File 'lib/pandocomatic/configuration.rb', line 650

def markdown_file?(filename)
  if filename.nil?
    false
  else
    ext = File.extname(filename).delete_prefix('.')
    DEFAULT_EXTENSION.key(ext) == 'markdown'
  end
end

#match_all_templates?Boolean

Should pandocomatic convert a file with all matching templates or only with the first matching template? Note. A ‘use-template’ statement in a document will overrule this setting.

otherwise.

Returns:

  • (Boolean)

    True if the setting ‘match-files’ is ‘all’, false



529
530
531
# File 'lib/pandocomatic/configuration.rb', line 529

def match_all_templates?
  @settings.key? 'match-files' and @settings['match-files'] == 'all'
end

#match_first_template?Boolean

Should pandocomatic convert a file with the first matching templates or with all matching templates? Note. Multiple ‘use-template’ statements in a document will overrule this setting.

otherwise.

Returns:

  • (Boolean)

    True if the setting ‘match-files’ is ‘first’, false



539
540
541
# File 'lib/pandocomatic/configuration.rb', line 539

def match_first_template?
  @settings.key? 'match-files' and @settings['match-files'] == 'first'
end

#modified_only?Boolean

Is the modified only CLI option given?

Returns:

  • (Boolean)


336
337
338
# File 'lib/pandocomatic/configuration.rb', line 336

def modified_only?
  @options[:modified_only_given] and @options[:modified_only]
end

#output?Boolean

Is the output CLI option given and can that output be used?

Returns:

  • (Boolean)


386
387
388
# File 'lib/pandocomatic/configuration.rb', line 386

def output?
  !@options.nil? and @options[:output_given] and @options[:output]
end

#quiet?Boolean

Run pandocomatic in quiet mode?

Returns:

  • (Boolean)


329
330
331
# File 'lib/pandocomatic/configuration.rb', line 329

def quiet?
  [verbose?, dry_run?].none?
end

#reconfigure(filename) ⇒ Configuration

Update this configuration with a configuration file and return a new configuration

Parameters:

  • filename (String)

    path to the configuration file

Returns:



265
266
267
268
269
270
271
272
# File 'lib/pandocomatic/configuration.rb', line 265

def reconfigure(filename)
  settings = PandocomaticYAML.load_file filename
  new_config = Marshal.load(Marshal.dump(self))
  new_config.configure settings, filename, recursive: true
  new_config
rescue StandardError => e
  raise ConfigurationError.new(:unable_to_load_config_file, e, filename)
end

#recursive?Boolean

Should pandocomatic be run recursively given this Configuration?

Returns:

  • (Boolean)

    True if the setting ‘recursive’ is true, false otherwise



511
512
513
# File 'lib/pandocomatic/configuration.rb', line 511

def recursive?
  @settings.key? 'recursive' and @settings['recursive']
end

#root_path?Boolean

Is the root path CLI option given?

Returns:

  • (Boolean)


364
365
366
# File 'lib/pandocomatic/configuration.rb', line 364

def root_path?
  @options[:root_path_given]
end

#selected_templatesString[]

Get the selected templates

Returns:

  • (String[])


400
401
402
403
404
405
406
# File 'lib/pandocomatic/configuration.rb', line 400

def selected_templates
  if use_templates?
    @options[:template]
  else
    []
  end
end

#set_destination(dst, template_name, metadata) ⇒ Object

Set the destination file given this Confguration, template, and metadata

Parameters:

  • dst (String)

    path to a destination file

  • template_name (String)

    the name of the template used to convert to destination

  • metadata (PandocMetadata)

    the metadata in the source file



564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
# File 'lib/pandocomatic/configuration.rb', line 564

def set_destination(dst, template_name, )
  return dst if dst.is_a? Tempfile

  dir = File.dirname dst

  # Use the output option when set.
  determine_output_in_pandoc = lambda do |pandoc|
    if pandoc.key? 'output'
      output = pandoc['output']
      unless output.start_with? '/'
        # Put it relative to the current directory
        output = File.join dir, output
      end
      output
    end
  end

  # Output options in pandoc property have precedence
  destination = determine_output_in_pandoc.call .pandoc_options
  rename_script = .pandoc_options['rename']

  # Output option in template's pandoc property is next
  if destination.nil? && !template_name.nil? && !template_name.empty? && @templates[template_name].pandoc?
    pandoc = @templates[template_name].pandoc
    destination = determine_output_in_pandoc.call pandoc
    rename_script ||= pandoc['rename']
  end

  # Else fall back to taking the input file as output file with the
  # extension updated to the output format
  if destination.nil?
    destination = set_extension dst, template_name, 

    destination = rename_destination(rename_script, destination) unless rename_script.nil?
  end

  # If there is a single file input without output specified, set
  # the output now that we know what the output filename is.
  @output = destination.delete_prefix './' unless output?

  destination
end

#set_extension(dst, template_name, metadata) ⇒ Object

Set the extension of the destination file given this Confguration, template, and metadata

Parameters:

  • dst (String)

    path to a destination file

  • template_name (String)

    the name of the template used to convert to destination

  • metadata (PandocMetadata)

    the metadata in the source file



550
551
552
553
554
555
# File 'lib/pandocomatic/configuration.rb', line 550

def set_extension(dst, template_name, )
  dir = File.dirname dst
  ext = File.extname dst
  basename = File.basename dst, ext
  File.join dir, "#{basename}.#{find_extension(template_name, )}"
end

#show_help?Boolean

Is the help CLI option given?

Returns:

  • (Boolean)


350
351
352
# File 'lib/pandocomatic/configuration.rb', line 350

def show_help?
  @options[:help_given]
end

#show_version?Boolean

Is the version CLI option given?

Returns:

  • (Boolean)


343
344
345
# File 'lib/pandocomatic/configuration.rb', line 343

def show_version?
  @options[:version_given]
end

#skip?(src) ⇒ Boolean

Should the source file be skipped given this Configuration?

Parameters:

  • src (String)

    path to a source file

Returns:

  • (Boolean)

    True if this source file matches the pattern in the ‘skip’ setting, false otherwise.



456
457
458
459
460
461
462
# File 'lib/pandocomatic/configuration.rb', line 456

def skip?(src)
  if @settings.key? 'skip'
    @settings['skip'].any? { |glob| File.fnmatch glob, File.basename(src) }
  else
    false
  end
end

#src_rootString

Get the source root directory

Returns:

  • (String)


416
417
418
# File 'lib/pandocomatic/configuration.rb', line 416

def src_root
  @input&.absolute_path
end

#stdout?Boolean

Is the stdout CLI option given?

Returns:

  • (Boolean)


315
316
317
# File 'lib/pandocomatic/configuration.rb', line 315

def stdout?
  !@options.nil? and @options[:stdout_given] and @options[:stdout]
end

#template?(template_name) ⇒ Boolean

Is there a template with template_name in this Configuration?

Parameters:

  • template_name (String)

    a template’s name

Returns:

  • (Boolean)

    True if there is a template with name equal to template_name in this Configuration



665
666
667
# File 'lib/pandocomatic/configuration.rb', line 665

def template?(template_name)
  @templates.key? template_name
end

#to_sString

Convert this Configuration to a String

Returns:

  • (String)


301
302
303
# File 'lib/pandocomatic/configuration.rb', line 301

def to_s
  marshal_dump
end

#use_templates?Boolean

Is the template CLI option given?

Returns:

  • (Boolean)


393
394
395
# File 'lib/pandocomatic/configuration.rb', line 393

def use_templates?
  !@options.nil? and @options[:template_given] and @options[:template] and !@options[:template].empty?
end

#verbose?Boolean

Is the verbose CLI option given?

Returns:

  • (Boolean)


322
323
324
# File 'lib/pandocomatic/configuration.rb', line 322

def verbose?
  @options[:verbose_given] and @options[:verbose]
end