pandocomatic 0.2.4.2 → 0.2.5.0.alpha

Sign up to get free protection for your applications and to get access to all the features.
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: