pandocomatic 0.1.2 → 0.1.3

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
  SHA1:
3
- metadata.gz: a4eb96b887676605773e3929aebac5709f2a70ff
4
- data.tar.gz: 2815789aeb3065e128606f3dedb338277251134f
3
+ metadata.gz: 54aa9b0867deb75ba7418c9fd508e5081d3aadc3
4
+ data.tar.gz: 86f74230480873d24004306c5c446b7ff6a2648e
5
5
  SHA512:
6
- metadata.gz: 439b66fabcd4f8c9af43c112f16495aa251a71a592ba22b8691fbdfb40ced84dd1abdb859a927be56ad2fd829aede581a4f811749bdb58bcc9e0839a41ce9623
7
- data.tar.gz: 982c94db04f6e51e0bce760e3028aa8256bd9315d3b7ffab6bfe0609810479a215f7cc5ccb27df428fd0daffb4dd19d0cac76587741b0fcf6dda5a7fef99f78b
6
+ metadata.gz: 43f04725a6eb099b3d545cc9ac7da7435d9d2de923b2a91e46b842c6c5c710acd43cc37d98c957c0a25ab34f6ed36939438b36a94237b497a6a2310aeadafec4
7
+ data.tar.gz: d0c090612f6482cf293a29636f9bd8520504b063a6c01b03f0c08cb866a89e96d360ae09544a286c6df7f71d074b1862d06cb143c86bb8ef524df9fda742e09b
@@ -96,6 +96,10 @@ module Pandocomatic
96
96
  false
97
97
  end
98
98
 
99
+ def multiple?()
100
+ false
101
+ end
102
+
99
103
  def skip?()
100
104
  false
101
105
  end
@@ -23,12 +23,14 @@ module Pandocomatic
23
23
  require_relative 'command.rb'
24
24
  require_relative 'create_link_command.rb'
25
25
  require_relative 'convert_file_command.rb'
26
+ require_relative 'convert_list_command.rb'
27
+ require_relative 'convert_file_multiple_command.rb'
26
28
  require_relative 'copy_file_command.rb'
27
29
  require_relative 'skip_command.rb'
28
30
 
29
- class ConvertDirCommand < Command
31
+ class ConvertDirCommand < ConvertListCommand
30
32
 
31
- attr_reader :config, :src_dir, :dst_dir, :subcommands
33
+ attr_reader :config, :src_dir, :dst_dir
32
34
 
33
35
  def initialize(current_config, src_dir, dst_dir)
34
36
  super()
@@ -49,8 +51,6 @@ module Pandocomatic
49
51
  @errors.push IOError.new(:directory_is_not_a_directory, nil, @dst_dir) unless File.directory? @dst_dir
50
52
  end
51
53
 
52
- @subcommands = []
53
-
54
54
  Dir.foreach @src_dir do |filename|
55
55
  src = File.join @src_dir, filename
56
56
 
@@ -70,10 +70,7 @@ module Pandocomatic
70
70
  end
71
71
  elsif File.file? src
72
72
  if config.convert? src then
73
- dst = config.set_extension dst
74
- if not modified_only? or file_modified? src, dst then
75
- subcommand = ConvertFileCommand.new(config, src, dst)
76
- end
73
+ subcommand = ConvertFileMultipleCommand.new(config, src, dst)
77
74
  else
78
75
  if not modified_only? or file_modified? src, dst then
79
76
  subcommand = CopyFileCommand.new(src, dst)
@@ -83,7 +80,7 @@ module Pandocomatic
83
80
  subcommand = SkipCommand.new(src, :unclear_what_to_do)
84
81
  end
85
82
 
86
- @subcommands.push subcommand unless subcommand.nil? or subcommand.skip?
83
+ push subcommand unless subcommand.nil? or subcommand.skip?
87
84
  end
88
85
 
89
86
  # Empty commands do not count to the total amount of commands to execute
@@ -94,18 +91,6 @@ module Pandocomatic
94
91
  @subcommands.empty?
95
92
  end
96
93
 
97
- def count()
98
- @subcommands.reduce(if skip? then 0 else 1 end) do |total, subcommand|
99
- total += subcommand.count
100
- end
101
- end
102
-
103
- def all_errors()
104
- @subcommands.reduce(@errors) do |total, subcommand|
105
- total += subcommand.all_errors
106
- end
107
- end
108
-
109
94
  def directory?()
110
95
  true
111
96
  end
@@ -122,17 +107,6 @@ module Pandocomatic
122
107
  end
123
108
  end
124
109
 
125
- def execute()
126
- if not @subcommands.empty?
127
- CommandPrinter.new(self).print unless quiet?
128
- run if not dry_run? and runnable?
129
-
130
- @subcommands.each do |subcommand|
131
- subcommand.execute
132
- end
133
- end
134
- end
135
-
136
110
  private
137
111
 
138
112
  def create_directory?()
@@ -24,22 +24,32 @@ module Pandocomatic
24
24
  require_relative '../processor.rb'
25
25
  require_relative '../fileinfo_preprocessor'
26
26
 
27
+ require_relative '../configuration.rb'
28
+
27
29
  require_relative '../error/io_error.rb'
28
30
  require_relative '../error/configuration_error.rb'
29
31
  require_relative '../error/processor_error.rb'
30
32
 
31
33
  require_relative 'command.rb'
32
34
 
35
+ OUTPUT_FORMATS = ["docx", "odt", "pdf", "beamer"]
36
+
33
37
  class ConvertFileCommand < Command
34
38
 
35
39
  attr_reader :config, :src, :dst
36
40
 
37
- def initialize(config, src, dst)
41
+ def initialize(config, src, dst, template_name = nil)
38
42
  super()
39
43
  @config = config
40
44
  @src = src
41
45
  @dst = dst
42
46
 
47
+ if template_name.nil? or template_name.empty?
48
+ @template_name = @config.determine_template @src
49
+ else
50
+ @template_name = template_name
51
+ end
52
+
43
53
  @errors.push IOError.new(:file_does_not_exist, nil, @src) unless File.exist? @src
44
54
  @errors.push IOError.new(:file_is_not_a_file, nil, @src) unless File.file? @src
45
55
  @errors.push IOError.new(:file_is_not_readable, nil, @src) unless File.readable? @src
@@ -60,16 +70,9 @@ module Pandocomatic
60
70
  pandoc_options = metadata.pandoc_options || {}
61
71
  template = {}
62
72
 
63
- if metadata.has_template? then
64
- template_name = metadata.template_name
65
- else
66
- template_name = @config.determine_template @src
67
- end
68
-
69
- if not template_name.nil? and not template_name.empty?
70
- raise ConfigurationError.new(:no_such_template, nil, template_name) unless @config.has_template? template_name
71
-
72
- template = @config.get_template template_name
73
+ if not @template_name.nil? and not @template_name.empty?
74
+ raise ConfigurationError.new(:no_such_template, nil, @template_name) unless @config.has_template? @template_name
75
+ template = @config.get_template @template_name
73
76
 
74
77
  pandoc_options = (template['pandoc'] || {}).merge(pandoc_options) do |key, oldval, newval|
75
78
  # Options that can occur more than once, such as 'filter' or
@@ -94,11 +97,13 @@ module Pandocomatic
94
97
  end
95
98
 
96
99
  begin
97
- File.open(@dst, 'w') do |file|
98
- raise IOError.new(:file_is_not_a_file, nil, @dst) unless File.file? @dst
99
- raise IOError.new(:file_is_not_writable, nil, @dst) unless File.writable? @dst
100
- file << output
101
- end
100
+ unless OUTPUT_FORMATS.include? pandoc_options["to"] then
101
+ File.open(@dst, 'w') do |file|
102
+ raise IOError.new(:file_is_not_a_file, nil, @dst) unless File.file? @dst
103
+ raise IOError.new(:file_is_not_writable, nil, @dst) unless File.writable? @dst
104
+ file << output
105
+ end
106
+ end
102
107
  rescue StandardError => e
103
108
  raise IOError.new(:error_writing_file, e, @dst)
104
109
  end
@@ -125,18 +130,28 @@ module Pandocomatic
125
130
  def pandoc(input, options, src_dir)
126
131
  converter = Paru::Pandoc.new
127
132
  options.each do |option, value|
133
+ # Pandoc multi-word options can have the multiple words separated by
134
+ # both underscore (_) and dash (-).
135
+ option= option.gsub "-", "_"
136
+
128
137
  if PANDOC_OPTIONS_WITH_PATH.include? option
129
138
  if value.is_a? Array
130
- value = value.map {|v| @config.update_path v, src_dir}
139
+ value = value.map {|v| @config.update_path(v, src_dir, option == "filter")}
131
140
  else
132
- value = @config.update_path value, src_dir
141
+ value = @config.update_path(value, src_dir, option == "filter")
133
142
  end
134
143
  end
135
144
 
145
+ # There is no "pdf" output format; change it to latex but keep the
146
+ # extension.
147
+ value = "latex" if option == "to" and value == "pdf"
148
+
136
149
  converter.send option, value unless option == 'output'
137
150
  # don't let pandoc write the output to enable postprocessing
138
151
  end
139
152
 
153
+ converter.send "output", @dst if OUTPUT_FORMATS.include? options["to"]
154
+
140
155
  begin
141
156
  converter << input
142
157
  rescue Paru::Error => e
@@ -160,8 +175,13 @@ module Pandocomatic
160
175
  output = input
161
176
  processors.each do |processor|
162
177
  script = @config.update_path(processor, File.dirname(@src))
163
-
164
- raise ProcessorError.new(:script_does_not_exist, nil, script) unless File.exist? script
178
+
179
+ if not File.exists? script
180
+ script = Configuration.which(script)
181
+
182
+ raise ProcessorError.new(:script_does_not_exist, nil, script) if script.nil?
183
+ end
184
+
165
185
  raise ProcessorError.new(:script_is_not_executable, nil, script) unless File.executable? script
166
186
 
167
187
  begin
@@ -175,6 +195,5 @@ module Pandocomatic
175
195
  input
176
196
  end
177
197
  end
178
-
179
198
  end
180
199
  end
@@ -0,0 +1,87 @@
1
+ #--
2
+ # Copyright 2017, 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 '../error/io_error.rb'
22
+
23
+ require_relative 'command.rb'
24
+ require_relative 'create_link_command.rb'
25
+ require_relative 'convert_file_command.rb'
26
+ require_relative 'convert_list_command.rb'
27
+ require_relative 'copy_file_command.rb'
28
+ require_relative 'skip_command.rb'
29
+
30
+ class ConvertFileMultipleCommand < ConvertListCommand
31
+
32
+ attr_reader :subcommands
33
+
34
+ def initialize(config, src, dst)
35
+ super()
36
+ @config = config
37
+ @src = src
38
+
39
+ metadata = PandocMetadata.load_file @src
40
+ metadata.templates.each do |template_name|
41
+ raise ConfigurationError.new(:no_such_template, nil, template_name) unless template_name.empty? or config.has_template? template_name
42
+
43
+ dst = config.set_extension dst, template_name, metadata
44
+ if not modified_only? or file_modified? @src, dst then
45
+ subcommand = ConvertFileCommand.new(@config, @src, dst, template_name)
46
+ push subcommand unless subcommand.nil? or subcommand.skip?
47
+ end
48
+ end
49
+ end
50
+
51
+ def push(command)
52
+ @subcommands.push command
53
+ end
54
+
55
+ def skip?()
56
+ @subcommands.empty?
57
+ end
58
+
59
+ def count()
60
+ @subcommands.reduce(if skip? then 0 else 1 end) do |total, subcommand|
61
+ total += subcommand.count
62
+ end
63
+ end
64
+
65
+ def all_errors()
66
+ @subcommands.reduce(@errors) do |total, subcommand|
67
+ total += subcommand.all_errors
68
+ end
69
+ end
70
+
71
+ def to_s()
72
+ "converting #{@src} #{@subcommands.size} time#{'s' if @subcommands.size != 1}:"
73
+ end
74
+
75
+ def execute()
76
+ if not @subcommands.empty?
77
+ CommandPrinter.new(self).print unless quiet? or @subcommands.size == 1
78
+ run if not dry_run? and runnable?
79
+
80
+ @subcommands.each do |subcommand|
81
+ subcommand.execute
82
+ end
83
+ end
84
+ end
85
+
86
+ end
87
+ end
@@ -0,0 +1,78 @@
1
+ #--
2
+ # Copyright 2017, 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 '../error/io_error.rb'
22
+
23
+ require_relative 'command.rb'
24
+ require_relative 'create_link_command.rb'
25
+ require_relative 'convert_file_command.rb'
26
+ require_relative 'copy_file_command.rb'
27
+ require_relative 'skip_command.rb'
28
+
29
+ class ConvertListCommand < Command
30
+
31
+ attr_reader :subcommands
32
+
33
+ def initialize()
34
+ super()
35
+ @subcommands = []
36
+ end
37
+
38
+ def push(command)
39
+ @subcommands.push command
40
+ end
41
+
42
+ def skip?()
43
+ @subcommands.empty?
44
+ end
45
+
46
+ def count()
47
+ @subcommands.reduce(if skip? then 0 else 1 end) do |total, subcommand|
48
+ total += subcommand.count
49
+ end
50
+ end
51
+
52
+ def all_errors()
53
+ @subcommands.reduce(@errors) do |total, subcommand|
54
+ total += subcommand.all_errors
55
+ end
56
+ end
57
+
58
+ def to_s()
59
+ "converting #{@subcommands.size} items:"
60
+ end
61
+
62
+ def multiple?
63
+ true
64
+ end
65
+
66
+ def execute()
67
+ if not @subcommands.empty?
68
+ CommandPrinter.new(self).print unless quiet?
69
+ run if not dry_run? and runnable?
70
+
71
+ @subcommands.each do |subcommand|
72
+ subcommand.execute
73
+ end
74
+ end
75
+ end
76
+
77
+ end
78
+ end
@@ -139,22 +139,38 @@ module Pandocomatic
139
139
  @settings['follow_links']
140
140
  end
141
141
 
142
- def set_extension(dst)
142
+ def set_extension(dst, template_name, metadata)
143
143
  dir = File.dirname dst
144
144
  ext = File.extname dst
145
145
  basename = File.basename dst, ext
146
- File.join dir, "#{basename}.#{find_extension dst}"
146
+ File.join dir, "#{basename}.#{find_extension(dst, template_name, metadata)}"
147
147
  end
148
148
 
149
- def find_extension(dst)
150
- template = determine_template dst
151
- if template.nil? then
152
- extension = 'html'
149
+ def find_extension(dst, template_name, metadata)
150
+ extension = "html"
151
+ if template_name.nil? or template_name.empty? then
152
+ if metadata.has_pandocomatic?
153
+ pandocomatic = metadata.pandocomatic
154
+ if pandocomatic.has_key? "pandoc"
155
+ pandoc = pandocomatic["pandoc"]
156
+
157
+ if pandoc.has_key? "to"
158
+ extension = pandoc["to"]
159
+ end
160
+ end
161
+ end
153
162
  else
154
163
  # TODO: what if there is no pandoc.to?
155
- to = @templates[template]['pandoc']['to']
156
- extension = FORMAT_TO_EXT[to] || to
164
+ if @templates[template_name].has_key? "pandoc"
165
+ pandoc = @templates[template_name]["pandoc"]
166
+ if pandoc.has_key? "to"
167
+ extension = pandoc["to"]
168
+ end
169
+ end
157
170
  end
171
+
172
+ extension = FORMAT_TO_EXT[extension] || extension
173
+ return extension
158
174
  end
159
175
 
160
176
  def has_template?(template_name)
@@ -171,16 +187,23 @@ module Pandocomatic
171
187
  end.keys.first
172
188
  end
173
189
 
174
- def update_path(path, src_dir)
190
+ def update_path(path, src_dir, check_executable = false)
191
+ updated_path = path
175
192
  if path.start_with? './'
176
193
  # refers to a local (to file) dir
177
- File.join src_dir, path
178
- elsif path.start_with? '/' then
179
- path
194
+ updated_path = File.join src_dir, path
180
195
  else
181
- # refers to data-dir
182
- File.join @data_dir, path
196
+ if check_executable
197
+ updated_path = Configuration.which path
198
+ end
199
+
200
+ if not updated_path.start_with? '/' then
201
+ # refers to data-dir
202
+ updated_path = File.join @data_dir, updated_path
203
+ end
183
204
  end
205
+
206
+ updated_path
184
207
  end
185
208
 
186
209
  private
@@ -234,6 +257,24 @@ module Pandocomatic
234
257
  end
235
258
  end
236
259
 
260
+ # Cross-platform way of finding an executable in the $PATH.
261
+ #
262
+ # which('ruby') #=> /usr/bin/ruby
263
+ #
264
+ # Taken from:
265
+ # http://stackoverflow.com/questions/2108727/which-in-ruby-checking-if-program-exists-in-path-from-ruby#5471032
266
+ def self.which(cmd)
267
+ exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
268
+ ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
269
+ exts.each { |ext|
270
+ exe = File.join(path, "#{cmd}#{ext}")
271
+ return exe if File.executable?(exe) &&
272
+ !File.directory?(exe)
273
+ }
274
+ end
275
+ return nil
276
+ end
277
+
237
278
  end
238
279
 
239
280
  end
@@ -37,7 +37,7 @@ module Pandocomatic
37
37
 
38
38
  def self.pandoc2yaml(input)
39
39
  input
40
- .scan(/^---\n(.+?)^(?:---|\.\.\.)\n/m)
40
+ .scan(/^---[ \t]*\n(.+?)^(?:---|\.\.\.)[ \t]*\n/m)
41
41
  .flatten
42
42
  .map{|yaml| yaml.strip}
43
43
  .join("\n")
@@ -63,6 +63,18 @@ module Pandocomatic
63
63
  has_pandocomatic? and pandocomatic.has_key? 'use-template' and not pandocomatic['use-template'].empty?
64
64
  end
65
65
 
66
+ def templates()
67
+ if has_template?
68
+ if pandocomatic['use-template'].is_a? Array
69
+ pandocomatic['use-template']
70
+ else
71
+ [pandocomatic['use-template']]
72
+ end
73
+ else
74
+ [""]
75
+ end
76
+ end
77
+
66
78
  def template_name()
67
79
  if has_template? then
68
80
  pandocomatic['use-template']
@@ -87,7 +99,12 @@ module Pandocomatic
87
99
  end
88
100
 
89
101
  def has_pandocomatic?()
90
- has_key? 'pandocomatic' or has_key? 'pandocomatic_'
102
+ config = nil
103
+ if has_key? 'pandocomatic' or has_key? 'pandocomatic_'
104
+ config = self['pandocomatic'] if has_key? 'pandocomatic'
105
+ config = self['pandocomatic_'] if has_key? 'pandocomatic_'
106
+ end
107
+ config.is_a? Hash
91
108
  end
92
109
 
93
110
  def pandocomatic()
@@ -37,7 +37,9 @@ module Pandocomatic
37
37
 
38
38
  require_relative './command/command.rb'
39
39
  require_relative './command/convert_dir_command.rb'
40
+ require_relative './command/convert_list_command.rb'
40
41
  require_relative './command/convert_file_command.rb'
42
+ require_relative './command/convert_file_multiple_command.rb'
41
43
 
42
44
  class Pandocomatic
43
45
  VERSION = [0, 1, 2]
@@ -79,8 +81,10 @@ module Pandocomatic
79
81
  if File.directory? input
80
82
  command = ConvertDirCommand.new(configuration, input, output)
81
83
  else
82
- command = ConvertFileCommand.new(configuration, input, output)
83
- command.make_quiet
84
+ destination = if output.nil? or output.empty? then File.basename input else output end
85
+
86
+ command = ConvertFileMultipleCommand.new(configuration, input, destination)
87
+ command.make_quiet unless command.subcommands.size > 1
84
88
  end
85
89
 
86
90
  # Notify the user about all configuration errors collected when
@@ -1 +1 @@
1
- (<%=@command.index_to_s%>) <%=if @command.directory? then "+ " else " - " end%><%= @command.to_s%>
1
+ (<%=@command.index_to_s%>) <%=if @command.multiple? then "+ " else " - " end%><%= @command.to_s%>
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pandocomatic
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Huub de Beer
@@ -91,6 +91,8 @@ files:
91
91
  - lib/pandocomatic/command/command.rb
92
92
  - lib/pandocomatic/command/convert_dir_command.rb
93
93
  - lib/pandocomatic/command/convert_file_command.rb
94
+ - lib/pandocomatic/command/convert_file_multiple_command.rb
95
+ - lib/pandocomatic/command/convert_list_command.rb
94
96
  - lib/pandocomatic/command/copy_file_command.rb
95
97
  - lib/pandocomatic/command/create_link_command.rb
96
98
  - lib/pandocomatic/command/skip_command.rb
@@ -150,7 +152,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
150
152
  requirements:
151
153
  - pandoc, a universal document converer <http://pandoc.org>
152
154
  rubyforge_project:
153
- rubygems_version: 2.5.1
155
+ rubygems_version: 2.5.2
154
156
  signing_key:
155
157
  specification_version: 4
156
158
  summary: Automating the use of pandoc