pandocomatic 0.2.4.2 → 0.2.5.0.alpha

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5805486820ab39b17105f8734d5a8bb06cd4974b504a433bfb2a8fd7257f1292
4
- data.tar.gz: fac1b7cdaf0b6bde56c14b27cf69a8314a9cb8d61570ee0b9bae8fa24bc119a5
3
+ metadata.gz: e0830abb917ca87c8d072ee5a4f88fee1f2f2d8da6359f14e74f9160614b23f9
4
+ data.tar.gz: 68f2dbf9325b3ccaeeeae4c2c99b3de4486ff00a2e6c1951a6b14f3f4260232a
5
5
  SHA512:
6
- metadata.gz: c6af721ff587c11366cdec4bf08dea7d022d9e82b902f6ca4690864ebacdc463e8eed745158f8e1d716a98d755943cd8c0300b17d17b1145bc4940361648a4f0
7
- data.tar.gz: 400a4e734a7bb904dac926a6fee4a35ca1f0622ff37cb202f7b9b61e33b94e8704aae94e601975228eeab2a7f06c1e0f81cc44e24b429a3a5026c8a55b29b5fd
6
+ metadata.gz: e8c034acc735d84f56c95765a070a129bb522bfe2b6536d407dc067c86f954fad64c7679cb561551689f837d1c54186a9e6c69e7f9fa192eaf548dc948395a0b
7
+ data.tar.gz: a625b92f99fdccfc5786cb8e2e234b572f4157f4efc894bdc6ed2be39eaad54cb4d33895014e410abfc37e3e983fa9bb6b9de805fa693fa5e1bab54a1f0cebf0
@@ -20,9 +20,11 @@ module Pandocomatic
20
20
  require 'optimist'
21
21
 
22
22
  require_relative './error/cli_error.rb'
23
+ require_relative './configuration.rb'
24
+
23
25
 
24
26
  ##
25
- # Command line options parser for pandocomatic using trollop.
27
+ # Command line options parser for pandocomatic using optimist.
26
28
  #
27
29
  class CLI
28
30
 
@@ -32,15 +34,13 @@ module Pandocomatic
32
34
  #
33
35
  # @param args [String, Array] A command line invocation string or a list of strings like ARGV
34
36
  #
35
- # @return [Hash] The options to pandocomatic
36
- # the subcommand's options
37
- #
37
+ # @return [Configuration] The configuration for running pandocomatic given
38
+ # the command-line options.
38
39
  def self.parse(args)
39
40
  args = args.split if args.is_a? String
40
41
 
41
42
  begin
42
- options = parse_options args || {:help => true, :help_given => true}
43
- options
43
+ parse_options args || Configuration.new({:help => true, :help_given => true})
44
44
  rescue Optimist::CommandlineError => e
45
45
  raise CLIError.new(:problematic_invocation, e, args)
46
46
  end
@@ -49,6 +49,8 @@ module Pandocomatic
49
49
  private
50
50
 
51
51
  # Parse pandocomatic's global options.
52
+ #
53
+ # @return [Configuration]
52
54
  def self.parse_options(args)
53
55
  parser = Optimist::Parser.new do
54
56
  # General options
@@ -63,7 +65,7 @@ module Pandocomatic
63
65
 
64
66
  # What to convert and where to put it
65
67
  opt :output, 'Output', :short => '-o', :type => String
66
- opt :input, 'Input', :short => '-i', :type => String
68
+ opt :input, 'Input', :short => '-i', :type => String, :multi => true
67
69
 
68
70
  # Version and help
69
71
  opt :show_version, 'Version', :short => '-v', :long => 'version'
@@ -79,29 +81,38 @@ module Pandocomatic
79
81
 
80
82
  options = use_custom_version options
81
83
  options = use_custom_help options
82
-
84
+
83
85
  if options_need_to_be_validated? options
84
- # if no input option is specified, it should follow as the last item
86
+ # if no input option is specified, all items following the last option
87
+ # are treated as input files.
85
88
  if not options[:input_given]
86
- options[:input] = args.shift
89
+ options[:input] = args
87
90
  options[:input_given] = true
91
+ elsif not args.empty?
92
+ raise CLIError.new(:no_mixed_inputs)
88
93
  end
89
94
 
90
- # There should be no other options left.
91
- raise CLIError.new(:too_many_options, nil, args) if not args.empty?
92
-
93
95
  # There should be an input specified
94
96
  raise CLIError.new(:no_input_given) if options[:input].nil? or options[:input].empty?
95
97
 
96
- # The input file or directory should exist
97
- input = File.absolute_path options[:input]
98
- raise CLIError.new(:input_does_not_exist, nil, options[:input]) unless File.exist? input
99
- raise CLIError.new(:input_is_not_readable, nil, input) unless File.readable? input
98
+ # Support multiple input files for conversion
99
+ multiple_inputs = 1 < options[:input].size
100
+
101
+ # The input files or directories should exist
102
+ input = options[:input].map do |input_file|
103
+ raise CLIError.new(:input_does_not_exist, nil, input_file) unless File.exist? input_file
104
+ raise CLIError.new(:input_is_not_readable, nil, input_file) unless File.readable? input_file
105
+
106
+ # If there are multiple input files, these files cannot be directories
107
+ raise CLIError.new(:multiple_input_files_only, nil, input_file) if multiple_inputs and File.directory? input_file
108
+
109
+ File.absolute_path input_file
110
+ end
100
111
 
101
112
  if options[:output_given]
102
113
  output = File.absolute_path options[:output]
103
114
  # Input and output should be both files or directories
104
- match_file_types input, output
115
+ match_file_types input.first, output
105
116
 
106
117
  # The output, if it already exist, should be writable
107
118
  raise CLIError.new(:output_is_not_writable, nil, output) unless not File.exist? output or File.writable? output
@@ -109,7 +120,7 @@ module Pandocomatic
109
120
  # If the input is a directory, an output directory should be
110
121
  # specified as well. If the input is a file, the output could be
111
122
  # specified in the input file, or STDOUT could be used.
112
- raise CLIError.new(:no_output_given) if File.directory? input
123
+ raise CLIError.new(:no_output_given) if not multiple_inputs and File.directory? input.first
113
124
  end
114
125
 
115
126
  # Data dir, if specified, should be an existing and readable directory
@@ -130,9 +141,9 @@ module Pandocomatic
130
141
  raise CLIError.new(:config_file_is_not_a_file, nil, config) unless File.file? config
131
142
  end
132
143
 
133
- end
134
-
135
- options
144
+ end
145
+
146
+ Configuration.new options, input
136
147
  end
137
148
 
138
149
  def self.options_need_to_be_validated? options
@@ -140,7 +151,7 @@ module Pandocomatic
140
151
  end
141
152
 
142
153
  #--
143
- #Optimist has special behavior for the version and help options. To
154
+ # Optimist has special behavior for the version and help options. To
144
155
  # overcome, "show_version" and "show_help" options are introduced. When
145
156
  # set, these are put in the options as "version" and "help"
146
157
  # respectively.
@@ -50,18 +50,13 @@ module Pandocomatic
50
50
 
51
51
  # Reset all Commands
52
52
  #
53
- # @param src_root [String = "."] the root directory to convert
54
- # @param dry_run [Boolean = false] should Commands actually run or not?
55
- # @param quiet [Boolean = false] should Commands run silently?
56
- # @param debug [Boolean = false] should Commands be run in debug mode?
57
- # @param modified_only [Boolean = false] should only modified files be
58
- # converted?
59
- def self.reset(src_root = ".", dry_run = false, quiet = false, debug = false, modified_only = false)
60
- @@src_root = src_root
61
- @@dry_run = dry_run
62
- @@quiet = quiet
63
- @@debug = debug
64
- @@modified_only = modified_only
53
+ # @param configuration [Configuration] the configuration used to convert
54
+ def self.reset(configuration)
55
+ @@src_root = configuration.src_root
56
+ @@dry_run = configuration.dry_run?
57
+ @@quiet = configuration.quiet?
58
+ @@debug = configuration.debug?
59
+ @@modified_only = configuration.modified_only?
65
60
  @@total = 0
66
61
  end
67
62
 
@@ -142,7 +142,7 @@ module Pandocomatic
142
142
  # If the source directory contains a configuration file, use it to
143
143
  # reconfigure the converter. Otherwise, use the current configuration
144
144
  def reconfigure(current_config, src_dir)
145
- config_file = File.join src_dir, Pandocomatic::CONFIG_FILE
145
+ config_file = File.join src_dir, Configuration::CONFIG_FILE
146
146
  if File.exist? config_file then
147
147
  config = current_config.reconfigure config_file
148
148
  else
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright 2014, 2015, 2016, 2017, Huub de Beer <Huub@heerdebeer.org>
2
+ # Copyright 2014—2019 Huub de Beer <Huub@heerdebeer.org>
3
3
  #
4
4
  # This file is part of pandocomatic.
5
5
  #
@@ -20,6 +20,11 @@ module Pandocomatic
20
20
 
21
21
  require 'yaml'
22
22
  require 'paru/pandoc'
23
+
24
+ require_relative './error/configuration_error.rb'
25
+ require_relative './command/command.rb'
26
+ require_relative './input.rb'
27
+ require_relative './multiple_files_input.rb'
23
28
 
24
29
  # The default configuration for pandocomatic is read from
25
30
  # default_configuration.yaml.
@@ -56,12 +61,38 @@ module Pandocomatic
56
61
  # A Configuration object models a pandocomatic configuration.
57
62
  class Configuration
58
63
 
59
- # Create a new Configuration instance based on the command-line
60
- # options, a data_dir, and a configuration file.
61
- def initialize options, data_dir, configuration_file
62
- @data_dir = data_dir
64
+ # Pandocomatic's default configuration file
65
+ CONFIG_FILE = 'pandocomatic.yaml'
63
66
 
64
- load configuration_file
67
+ # Create a new Configuration instance based on the command-line options
68
+ def initialize options, input
69
+ @options = options
70
+ @data_dir = determine_data_dir options
71
+ config_file = determine_config_file(options, @data_dir)
72
+
73
+ load config_file unless config_file.nil? or config_file.empty?
74
+
75
+ @input = if input.nil? or input.empty? then
76
+ nil
77
+ elsif 1 < input.size then
78
+ MultipleFilesInput.new(input)
79
+ else
80
+ Input.new(input)
81
+ end
82
+
83
+ @output = if output? then
84
+ options[:output]
85
+ elsif @input.is_a? Input then
86
+ @input.base
87
+ else
88
+ nil
89
+ end
90
+
91
+ # Extend the command classes by setting the source tree root
92
+ # directory, and the options quiet and dry-run, which are used when
93
+ # executing a command: if dry-run the command is not actually
94
+ # executed and if quiet the command is not printed to STDOUT
95
+ Command.reset(self)
65
96
  end
66
97
 
67
98
  # Read a configuration file and create a pandocomatic configuration object
@@ -149,6 +180,116 @@ module Pandocomatic
149
180
  marshal_dump
150
181
  end
151
182
 
183
+ # Is the dry run CLI option given?
184
+ #
185
+ # @return [Boolean]
186
+ def dry_run?()
187
+ @options[:dry_run_given] and @options[:dry_run]
188
+ end
189
+
190
+ # Is the quiet CLI option given?
191
+ #
192
+ # @return [Boolean]
193
+ def quiet?()
194
+ @options[:quiet_given] and @options[:quiet]
195
+ end
196
+
197
+ # Is the debug CLI option given?
198
+ #
199
+ # @return [Boolean]
200
+ def debug?()
201
+ @options[:debug_given] and @options[:debug]
202
+ end
203
+
204
+ # Is the modified only CLI option given?
205
+ #
206
+ # @return [Boolean]
207
+ def modified_only?()
208
+ @options[:modified_only_given] and @options[:modified_only]
209
+ end
210
+
211
+ # Is the version CLI option given?
212
+ #
213
+ # @return [Boolean]
214
+ def show_version?()
215
+ @options[:version_given]
216
+ end
217
+
218
+ # Is the help CLI option given?
219
+ #
220
+ # @return [Boolean]
221
+ def show_help?()
222
+ @options[:help_given]
223
+ end
224
+
225
+ # Is the data dir CLI option given?
226
+ #
227
+ # @return [Boolean]
228
+ def data_dir?()
229
+ @options[:data_dir_given]
230
+ end
231
+
232
+ # Is the config CLI option given?
233
+ #
234
+ # @return [Boolean]
235
+ def config?()
236
+ @options[:config_given]
237
+ end
238
+
239
+ # Is the output CLI option given and can that output be used?
240
+ #
241
+ # @return [Boolean]
242
+ def output?()
243
+ @options[:output_given] and @options[:output]
244
+ end
245
+
246
+ # Get the output file name
247
+ #
248
+ # @return [String]
249
+ def output()
250
+ @output
251
+ end
252
+
253
+ # Get the source root directory
254
+ #
255
+ # @return [String]
256
+ def src_root()
257
+ if @input.nil? then nil else @input.absolute_path end
258
+ end
259
+
260
+ # Have input CLI options be given?
261
+ def input?()
262
+ @options[:input_given]
263
+ end
264
+
265
+ # Get the input file name
266
+ #
267
+ # @return [String]
268
+ def input()
269
+ if @input.nil? then
270
+ nil
271
+ else
272
+ @input.name
273
+ end
274
+ end
275
+
276
+ # Is this Configuration for converting directories?
277
+ #
278
+ # @return [Boolean]
279
+ def directory?()
280
+ not @input.nil? and @input.directory?
281
+ end
282
+
283
+ # Clean up this configuration. This will remove temporary files
284
+ # created for the conversion process guided by this Configuration.
285
+ def clean_up!()
286
+ # If a temporary file has been created while concatenating
287
+ # multiple input files, ensure it is removed.
288
+ if @input.is_a? MultipleFilesInput then
289
+ @input.destroy!
290
+ end
291
+ end
292
+
152
293
  # Should the source file be skipped given this Configuration?
153
294
  #
154
295
  # @param src [String] path to a source file
@@ -245,13 +386,22 @@ module Pandocomatic
245
386
  end
246
387
  end
247
388
 
248
- # Output options in pandoc property have precedence
249
- destination = determine_output_in_pandoc.call metadata.pandoc_options
250
- rename_script = metadata.pandoc_options["rename"]
389
+ destination = nil
390
+ rename_script = nil
391
+
392
+ # Output option in pandoc property has precedence
393
+ if metadata.has_pandocomatic?
394
+ pandocomatic = metadata.pandocomatic
395
+ if pandocomatic.has_key? "pandoc"
396
+ pandoc = pandocomatic["pandoc"]
397
+ destination = determine_output_in_pandoc.call pandoc
398
+ rename_script = pandoc["rename"]
399
+ end
400
+ end
251
401
 
252
402
  # Output option in template's pandoc property is next
253
403
  if destination.nil? and not template_name.nil? and not template_name.empty? then
254
- if @templates[template_name].has_key? "pandoc" and not @templates[template_name]["pandoc"].nil?
404
+ if @templates[template_name].has_key? "pandoc"
255
405
  pandoc = @templates[template_name]["pandoc"]
256
406
  destination = determine_output_in_pandoc.call pandoc
257
407
  rename_script ||= pandoc["rename"]
@@ -295,14 +445,21 @@ module Pandocomatic
295
445
  end
296
446
 
297
447
  if template_name.nil? or template_name.empty? then
298
- ext = use_extension.call metadata.pandoc_options
299
- if not ext.nil?
300
- extension = ext
301
- elsif metadata.pandoc_options.has_key? "to"
302
- extension = strip_extensions.call(metadata.pandoc_options["to"])
303
- end
448
+ if metadata.has_pandocomatic?
449
+ pandocomatic = metadata.pandocomatic
450
+ if pandocomatic.has_key? "pandoc"
451
+ pandoc = pandocomatic["pandoc"]
452
+
453
+ ext = use_extension.call pandoc
454
+ if not ext.nil?
455
+ extension = ext
456
+ elsif pandoc.has_key? "to"
457
+ extension = strip_extensions.call(pandoc["to"])
458
+ end
459
+ end
460
+ end
304
461
  else
305
- if @templates[template_name].has_key? "pandoc" and not @templates[template_name]["pandoc"].nil?
462
+ if @templates[template_name].has_key? "pandoc"
306
463
  pandoc = @templates[template_name]["pandoc"]
307
464
  ext = use_extension.call pandoc
308
465
 
@@ -669,5 +826,65 @@ module Pandocomatic
669
826
  path.start_with? "/"
670
827
  end
671
828
  end
829
+
830
+ def determine_config_file(options, data_dir = Dir.pwd)
831
+ config_file = ''
832
+
833
+ if options[:config_given]
834
+ config_file = options[:config]
835
+ elsif Dir.entries(data_dir).include? CONFIG_FILE
836
+ config_file = File.join(data_dir, CONFIG_FILE)
837
+ elsif Dir.entries(Dir.pwd()).include? CONFIG_FILE
838
+ config_file = File.join(Dir.pwd(), CONFIG_FILE)
839
+ else
840
+ # Fall back to default configuration file distributed with
841
+ # pandocomatic
842
+ config_file = File.join(__dir__, 'default_configuration.yaml')
843
+ end
844
+
845
+ path = File.absolute_path config_file
846
+
847
+ raise ConfigurationError.new(:config_file_does_not_exist, nil, path) unless File.exist? path
848
+ raise ConfigurationError.new(:config_file_is_not_a_file, nil, path) unless File.file? path
849
+ raise ConfigurationError.new(:config_file_is_not_readable, nil, path) unless File.readable? path
850
+
851
+ path
852
+ end
853
+
854
+ def determine_data_dir(options)
855
+ data_dir = ''
856
+
857
+ if options[:data_dir_given]
858
+ data_dir = options[:data_dir]
859
+ else
860
+ # No data-dir option given: try to find the default one from pandoc
861
+ begin
862
+ data_dir = Paru::Pandoc.info()[:data_dir]
863
+
864
+ # If pandoc's data dir does not exist, however, fall back
865
+ # to the current directory
866
+ unless File.exist? File.absolute_path(data_dir)
867
+ data_dir = Dir.pwd
868
+ end
869
+ rescue Paru::Error => e
870
+ # If pandoc cannot be run, continuing probably does not work out
871
+ # anyway, so raise pandoc error
872
+ raise PandocError.new(:error_running_pandoc, e, data_dir)
873
+ rescue StandardError => e
874
+ # Ignore error and use the current working directory as default working directory
875
+ data_dir = Dir.pwd
876
+ end
877
+ end
878
+
879
+ # check if data directory does exist and is readable
880
+ path = File.absolute_path data_dir
881
+
882
+ raise ConfigurationError.new(:data_dir_does_not_exist, nil, path) unless File.exist? path
883
+ raise ConfigurationError.new(:data_dir_is_not_a_directory, nil, path) unless File.directory? path
884
+ raise ConfigurationError.new(:data_dir_is_not_readable, nil, path) unless File.readable? path
885
+
886
+ path
887
+ end
888
+
672
889
  end
673
890
  end
@@ -30,6 +30,8 @@ module Pandocomatic
30
30
  # :no_input_given,
31
31
  # :input_does_not_exist,
32
32
  # :input_is_not_readable,
33
+ # :multiple_input_files_only,
34
+ # :no_mixed_inputs
33
35
 
34
36
  # :no_output_given,
35
37
  # :output_is_not_a_directory,
@@ -37,7 +39,6 @@ module Pandocomatic
37
39
  # :output_it_not_writable,
38
40
 
39
41
  # :unknown_option,
40
- # :too_many_options,
41
42
  # :problematic_invocation,
42
43
 
43
44
  # :data_dir_does_not_exist,
@@ -0,0 +1,69 @@
1
+ #--
2
+ # Copyright 2019 Huub de Beer <Huub@heerdebeer.org>
3
+ #
4
+ # This file is part of pandocomatic.
5
+ #
6
+ # Pandocomatic is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by the
8
+ # Free Software Foundation, either version 3 of the License, or (at your
9
+ # option) any later version.
10
+ #
11
+ # Pandocomatic is distributed in the hope that it will be useful, but
12
+ # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13
+ # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
+ # for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License along
17
+ # with pandocomatic. If not, see <http://www.gnu.org/licenses/>.
18
+ #++
19
+ module Pandocomatic
20
+
21
+ require_relative './configuration.rb'
22
+
23
+ # Generic class to handle input files and directories in a general manner.
24
+ class Input
25
+
26
+ # Create a new Input
27
+ #
28
+ # @param input [String[]] a list of input files
29
+ def initialize(input)
30
+ @input_files = input
31
+ end
32
+
33
+ # The absolute path to this Input
34
+ #
35
+ # @return String
36
+ def absolute_path()
37
+ File.absolute_path @input_files.first
38
+ end
39
+
40
+ # The base name of this Input
41
+ #
42
+ # @return String
43
+ def base()
44
+ File.basename @input_files.first
45
+ end
46
+
47
+ # The name of this input
48
+ #
49
+ # @return String
50
+ def name()
51
+ @input_files.first
52
+ end
53
+
54
+ # Is this input a directory?
55
+ #
56
+ # @return Boolean
57
+ def directory?()
58
+ File.directory? @input_files.first
59
+ end
60
+
61
+ # A string representation of this Input
62
+ #
63
+ # @return String
64
+ def to_s()
65
+ self.name
66
+ end
67
+
68
+ end
69
+ end
@@ -0,0 +1,82 @@
1
+ #--
2
+ # Copyright 2019 Huub de Beer <Huub@heerdebeer.org>
3
+ #
4
+ # This file is part of pandocomatic.
5
+ #
6
+ # Pandocomatic is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by the
8
+ # Free Software Foundation, either version 3 of the License, or (at your
9
+ # option) any later version.
10
+ #
11
+ # Pandocomatic is distributed in the hope that it will be useful, but
12
+ # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13
+ # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
+ # for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License along
17
+ # with pandocomatic. If not, see <http://www.gnu.org/licenses/>.
18
+ #++
19
+ module Pandocomatic
20
+
21
+ require 'tempfile'
22
+ require_relative './input.rb'
23
+
24
+ # A specific Input class to handle multiple input files
25
+ class MultipleFilesInput < Input
26
+
27
+ # Create a new MultipleFilesInput. As a side-effect a temporary file
28
+ # is created as well containing the content of all the files in input.
29
+ #
30
+ # @param input [String[]] a list with input files
31
+ def initialize(input)
32
+ super(input)
33
+ create_temp_file
34
+ end
35
+
36
+ # The name of this input
37
+ #
38
+ # @return String
39
+ def name()
40
+ @tmp_file
41
+ end
42
+
43
+ # Is this input a directory? A MultipleFilesInput cannot be a
44
+ # directory
45
+ #
46
+ # @return Boolean
47
+ def directory?()
48
+ false
49
+ end
50
+
51
+ # Destroy the temporary file created for this MultipleFilesInput
52
+ def destroy!()
53
+ if not @tmp_file.nil?
54
+ @tmp_file.close
55
+ @tmp_file.unlink
56
+ end
57
+ end
58
+
59
+ # A string representation of this Input
60
+ #
61
+ # @return String
62
+ def to_s()
63
+ @input_files.join(" + ")
64
+ end
65
+
66
+ private
67
+
68
+ def create_temp_file()
69
+ # Concatenate all input files into one (temporary) input file
70
+ # created in the same directory as the first input file
71
+ @tmp_file = Tempfile.new(@input_files.first, File.dirname(self.absolute_path))
72
+
73
+ @input_files.each_with_index do |filename, index|
74
+ input = File.read File.absolute_path(filename)
75
+ input = if 0 === index then input else PandocMetadata.remove_metadata(input) end
76
+ @tmp_file.write input
77
+ end
78
+
79
+ @tmp_file.rewind
80
+ end
81
+ end
82
+ end
@@ -24,6 +24,9 @@ module Pandocomatic
24
24
 
25
25
  require_relative './error/pandoc_error.rb'
26
26
  require_relative './error/io_error.rb'
27
+
28
+ # Regular expression to find metadata blocks in a string.
29
+ METADATA_BLOCK = /^---[ \t]*(\r\n|\r|\n)(.+?)^(?:---|\.\.\.)[ \t]*(\r\n|\r|\n)/m
27
30
 
28
31
  # PandocMetadata represents the metadata with pandoc options set in
29
32
  # templates and input files.
@@ -41,12 +44,20 @@ module Pandocomatic
41
44
  end
42
45
  end
43
46
 
47
+ # Remove all metadata from an input string
48
+ #
49
+ # @param input [String] the input to remove all metadata from
50
+ # @return [String] the input with all metadata blocks removed
51
+ def self.remove_metadata(input)
52
+ input.gsub(METADATA_BLOCK, "\n");
53
+ end
54
+
44
55
  # Extract the YAML metadata from an input string
45
56
  #
46
57
  # @param input [String] the input string
47
58
  # @return [String] the YAML data embedded in the input string
48
59
  def self.pandoc2yaml(input)
49
- mined_metadata = input.scan(/^---[ \t]*(\r\n|\r|\n)(.+?)^(?:---|\.\.\.)[ \t]*(\r\n|\r|\n)/m)
60
+ mined_metadata = input.scan(METADATA_BLOCK)
50
61
 
51
62
  mined_metadata
52
63
  .flatten
@@ -159,7 +170,7 @@ module Pandocomatic
159
170
  # @return [Boolean] True if there is a pandoc options property in this
160
171
  # PandocMetadata object. False otherwise.
161
172
  def has_pandoc_options?()
162
- has_pandocomatic? and pandocomatic.has_key? 'pandoc' and not pandocomatic['pandoc'].nil?
173
+ has_pandocomatic? and pandocomatic.has_key? 'pandoc'
163
174
  end
164
175
 
165
176
  end
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright 2014, 2015, 2016, 2017, Huub de Beer <Huub@heerdebeer.org>
2
+ # Copyright 2014—2019, Huub de Beer <Huub@heerdebeer.org>
3
3
  #
4
4
  # This file is part of pandocomatic.
5
5
  #
@@ -21,15 +21,13 @@ module Pandocomatic
21
21
  Encoding.default_internal = Encoding::UTF_8
22
22
 
23
23
  require 'paru'
24
+ require 'tempfile'
24
25
 
25
26
  require_relative './error/pandocomatic_error.rb'
26
27
  require_relative './error/pandoc_error.rb'
27
- require_relative './error/configuration_error.rb'
28
28
 
29
29
  require_relative './cli.rb'
30
30
 
31
- require_relative './configuration.rb'
32
-
33
31
  require_relative './printer/help_printer.rb'
34
32
  require_relative './printer/version_printer.rb'
35
33
  require_relative './printer/error_printer.rb'
@@ -37,7 +35,6 @@ module Pandocomatic
37
35
  require_relative './printer/finish_printer.rb'
38
36
  require_relative './printer/summary_printer.rb'
39
37
 
40
- require_relative './command/command.rb'
41
38
  require_relative './command/convert_dir_command.rb'
42
39
  require_relative './command/convert_list_command.rb'
43
40
  require_relative './command/convert_file_command.rb'
@@ -50,54 +47,34 @@ module Pandocomatic
50
47
  ERROR_STATUS = 1266 # This is the sum of the ascii values of the characters in 'pandocomatic'
51
48
 
52
49
  # Pandocomatic's current version
53
- VERSION = [0, 2, 4, 2]
54
-
55
- # Pandocomatic's default configuration file
56
- CONFIG_FILE = 'pandocomatic.yaml'
57
-
50
+ VERSION = [0, 2, 5, 0, "α"]
51
+
58
52
  # Run pandocomatic given options
59
53
  #
60
54
  # @param args [String[]] list of options to configure pandocomatic
61
55
  def self.run(args)
62
56
  begin
63
57
  start_time = Time.now
64
- options = CLI.parse args
58
+ configuration = CLI.parse args
65
59
 
66
- if options[:version_given]
60
+ if configuration.show_version?
67
61
  # The version option has precedence over all other options; if
68
62
  # given, the version is printed
69
63
  VersionPrinter.new(VERSION).print
70
- elsif options[:help_given]
64
+ elsif configuration.show_help?
71
65
  # The help option has precedence over all other options except the
72
66
  # version option. If given, the help is printed.
73
67
  HelpPrinter.new().print
74
68
  else
75
69
  # Run the pandocomatic converter configured according to the options
76
70
  # given.
77
- input = options[:input]
78
- output = options[:output]
79
- configuration = configure options
80
-
81
- # Extend the command classes by setting the source tree root
82
- # directory, and the options quiet and dry-run, which are used when
83
- # executing a command: if dry-run the command is not actually
84
- # executed and if quiet the command is not printed to STDOUT
85
- src_root = File.absolute_path input
86
- dry_run = if options[:dry_run_given] then options[:dry_run] else false end
87
- quiet = if options[:quiet_given] then options[:quiet] else false end
88
- debug = if options[:debug_given] and not quiet then options[:debug] else false end
89
- modified_only = if options[:modified_only_given] then options[:modified_only_given] else false end
90
-
91
- Command.reset(src_root, dry_run, quiet, debug, modified_only)
92
-
71
+ #
93
72
  # Pandocomatic has two modes: converting a directory tree or
94
73
  # converting a single file. The mode is selected by the input.
95
- if File.directory? input
96
- command = ConvertDirCommand.new(configuration, input, output)
74
+ if configuration.directory?
75
+ command = ConvertDirCommand.new(configuration, configuration.input, configuration.output)
97
76
  else
98
- destination = if output.nil? or output.empty? then File.basename input else output end
99
-
100
- command = ConvertFileMultipleCommand.new(configuration, input, destination)
77
+ command = ConvertFileMultipleCommand.new(configuration, configuration.input, configuration.output)
101
78
  command.make_quiet unless command.subcommands.size > 1
102
79
  end
103
80
 
@@ -112,14 +89,14 @@ module Pandocomatic
112
89
  # Pandocomatic is successfully configured: running the
113
90
  # actual conversion now. But first a short summary of the
114
91
  # process to execute is printed.
115
- SummaryPrinter.new(command, input, output).print unless quiet or not command.directory?
92
+ SummaryPrinter.new(command, configuration).print unless configuration.quiet? or not command.directory?
116
93
 
117
94
  # Depending on the options dry-run and quiet, the command.execute
118
95
  # method will actually performing the commands (dry-run = false) and
119
96
  # print the command to STDOUT (quiet = false)
120
97
  command.execute()
121
98
 
122
- FinishPrinter.new(command, input, output, start_time).print unless quiet
99
+ FinishPrinter.new(command, configuration, start_time).print unless configuration.quiet?
123
100
  end
124
101
  rescue PandocomaticError => e
125
102
  # Report the error and break off the conversion process.
@@ -130,75 +107,9 @@ module Pandocomatic
130
107
  # for now. This is likely a bug: ask the user to report it.
131
108
  warn "An unexpected error has occurred. You can report this bug via https://github.com/htdebeer/pandocomatic/issues/new."
132
109
  raise e
110
+ ensure
111
+ configuration.clean_up!
133
112
  end
134
113
  end
135
-
136
- private
137
-
138
- def self.determine_config_file(options, data_dir = Dir.pwd)
139
- config_file = ''
140
-
141
- if options[:config_given]
142
- config_file = options[:config]
143
- elsif Dir.entries(data_dir).include? CONFIG_FILE
144
- config_file = File.join(data_dir, CONFIG_FILE)
145
- elsif Dir.entries(Dir.pwd()).include? CONFIG_FILE
146
- config_file = File.join(Dir.pwd(), CONFIG_FILE)
147
- else
148
- # Fall back to default configuration file distributed with
149
- # pandocomatic
150
- config_file = File.join(__dir__, 'default_configuration.yaml')
151
- end
152
-
153
- path = File.absolute_path config_file
154
-
155
- raise ConfigurationError.new(:config_file_does_not_exist, nil, path) unless File.exist? path
156
- raise ConfigurationError.new(:config_file_is_not_a_file, nil, path) unless File.file? path
157
- raise ConfigurationError.new(:config_file_is_not_readable, nil, path) unless File.readable? path
158
-
159
- path
160
- end
161
-
162
- def self.determine_data_dir(options)
163
- data_dir = ''
164
-
165
- if options[:data_dir_given]
166
- data_dir = options[:data_dir]
167
- else
168
- # No data-dir option given: try to find the default one from pandoc
169
- begin
170
- data_dir = Paru::Pandoc.info()[:data_dir]
171
-
172
- # If pandoc's data dir does not exist, however, fall back
173
- # to the current directory
174
- unless File.exist? File.absolute_path(data_dir)
175
- data_dir = Dir.pwd
176
- end
177
- rescue Paru::Error => e
178
- # If pandoc cannot be run, continuing probably does not work out
179
- # anyway, so raise pandoc error
180
- raise PandocError.new(:error_running_pandoc, e, data_dir)
181
- rescue StandardError => e
182
- # Ignore error and use the current working directory as default working directory
183
- data_dir = Dir.pwd
184
- end
185
- end
186
-
187
- # check if data directory does exist and is readable
188
- path = File.absolute_path data_dir
189
-
190
- raise ConfigurationError.new(:data_dir_does_not_exist, nil, path) unless File.exist? path
191
- raise ConfigurationError.new(:data_dir_is_not_a_directory, nil, path) unless File.directory? path
192
- raise ConfigurationError.new(:data_dir_is_not_readable, nil, path) unless File.readable? path
193
-
194
- path
195
- end
196
-
197
- def self.configure(options)
198
- data_dir = determine_data_dir options
199
- config_file = determine_config_file options, data_dir
200
- Configuration.new options, data_dir, config_file
201
- end
202
-
203
114
  end
204
115
  end
@@ -25,8 +25,13 @@ module Pandocomatic
25
25
  MINUTE = 60
26
26
 
27
27
  # Create a new FinishPrinter
28
- def initialize(command, input, output, start_time)
29
- super command, input, output
28
+ #
29
+ # @param command [Command] the command to finish
30
+ # @param configuration [Configuration] the configuration of the
31
+ # pandocomatic invokation
32
+ # @param start_time [Time] the time the command was started
33
+ def initialize(command, configuration, start_time)
34
+ super command, configuration
30
35
  set_template 'finish.txt'
31
36
 
32
37
  @start_time = start_time
@@ -34,6 +39,8 @@ module Pandocomatic
34
39
  end
35
40
 
36
41
  # Calculate the duration of the whole conversion process
42
+ #
43
+ # @erturn [Number]
37
44
  def duration()
38
45
  seconds = @end_time - @start_time
39
46
  if seconds > MINUTE
@@ -25,13 +25,13 @@ module Pandocomatic
25
25
  # Create a new SummaryPrinter
26
26
  #
27
27
  # @param command [Command] the command to summarize
28
- # @param input [String] the filename of the input file
29
- # @param output [String] the filename of the output file
30
- def initialize(command, input, output)
28
+ # @param configuration [Configuration] the configuration of the
29
+ # pandocomatic invokation
30
+ def initialize(command, configuration)
31
31
  super 'summary.txt'
32
32
  @command = command
33
- @input = input
34
- @output = output
33
+ @input = configuration.input.to_s
34
+ @output = configuration.output
35
35
  end
36
36
 
37
37
  # A string representation of the commands being executed
@@ -1,6 +1,11 @@
1
1
  <%=@error.message%>: <% case @error.type
2
2
  when :no_input_given%>
3
3
  Specify the input file or directory with the option `--input PATH`.
4
+ <% when :no_mixed_inputs%>
5
+ Using both the `--input/-i` options and extra input parameters is not allowed.
6
+ Use either only `--input/-i` options or only input parameters.
7
+ <% when :multiple_input_files_only %>
8
+ When specifying multiple inputs, only files are allowed. '<%= @error.data %>' is a directory.
4
9
  <% when :unknown_option %>
5
10
  See `pandocomatic --help` which options are allowed.
6
11
  <% when :too_many_options %>
@@ -59,8 +59,15 @@ OPTIONS
59
59
  TRUE
60
60
 
61
61
  - templates:
62
+ - cleanup: [SCRIPTS] paths to scripts to run after a
63
+ conversion is finished, i.e. after the last
64
+ postprocessor is run.
62
65
  - glob: [GLOB PATTERNS] files to convert using this
63
66
  template.
67
+ - setup: [SCRIPTS] paths to scripts to run before a
68
+ conversion is started, i.e. before any preprocessor is
69
+ run.
70
+ - metadata: [YAML properties] metadata properties
64
71
  - preprocessors: [SCRIPTS] paths to scripts to run before
65
72
  converting with pandoc.
66
73
  - postprocessors: [SCRIPTS] paths to scripts to run after
@@ -111,11 +118,11 @@ SEE ALSO
111
118
  - Pandocomatic's documentation
112
119
  https://heerdebeer.org/Software/markdown/pandocomatic/
113
120
 
114
- - Pandoc's manual
115
- http://pandoc.org/MANUAL.html
121
+ - Pandoc's user guide
122
+ https://pandoc.org/MANUAL.html
116
123
 
117
124
  - YAML website
118
- http://yaml.org/
125
+ https://yaml.org/
119
126
 
120
127
  AUTHOR
121
128
 
@@ -123,7 +130,7 @@ AUTHOR
123
130
 
124
131
  LICENSE
125
132
 
126
- Copyright 2014, 2015, 2016, 2017, Huub de Beer <Huub@heerdebeer.org>
133
+ Copyright 2014—2019 Huub de Beer <Huub@heerdebeer.org>
127
134
 
128
135
  Pandocomatic is free software: you can redistribute it and/or modify
129
136
  it under the terms of the GNU General Public License as published by the
@@ -1,5 +1,6 @@
1
1
  Pandocomatic version <%=@version.join('.')%>
2
- © 2014, 2015, 2016, 2017, 2018 Huub de Beer <Huub@heerdebeer.org>
2
+
3
+ © 2014—2019 Huub de Beer <Huub@heerdebeer.org>
3
4
 
4
5
  Pandocomatic is free software; pandocomatic is released under the GPLv3.
5
6
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pandocomatic
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.4.2
4
+ version: 0.2.5.0.alpha
5
5
  platform: ruby
6
6
  authors:
7
7
  - Huub de Beer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-03-13 00:00:00.000000000 Z
11
+ date: 2019-03-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: paru
@@ -105,6 +105,8 @@ files:
105
105
  - lib/pandocomatic/error/pandoc_error.rb
106
106
  - lib/pandocomatic/error/pandocomatic_error.rb
107
107
  - lib/pandocomatic/error/processor_error.rb
108
+ - lib/pandocomatic/input.rb
109
+ - lib/pandocomatic/multiple_files_input.rb
108
110
  - lib/pandocomatic/pandoc_metadata.rb
109
111
  - lib/pandocomatic/pandocomatic.rb
110
112
  - lib/pandocomatic/printer/command_printer.rb
@@ -148,9 +150,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
148
150
  version: '0'
149
151
  required_rubygems_version: !ruby/object:Gem::Requirement
150
152
  requirements:
151
- - - ">="
153
+ - - ">"
152
154
  - !ruby/object:Gem::Version
153
- version: '0'
155
+ version: 1.3.1
154
156
  requirements:
155
157
  - pandoc, a universal document converer <http://pandoc.org>
156
158
  rubyforge_project: