pslm 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: fcfdfd901e4bdd0796aa7d85ca0037cb8c0b2e1e
4
+ data.tar.gz: 99ab169ac0873ce40653ebfb91f1a599f3fd1775
5
+ SHA512:
6
+ metadata.gz: 141897655cd0db39adb3b32822cbd2ac9f77884e383297bfa1d7caf06c1cf11b1ac51452d6292fbfc5e15f424bfcdf5d3d53a5ccc71f74af6bd57ad017947899
7
+ data.tar.gz: 3c777f32f4dc5f914afcc0cf57799dff9b82f00963f2abf8f489cbf73af0de0f2943211626a1b13add3354e74c3ca0780a14bdea7f594d8896be146a0204abb9
@@ -0,0 +1,150 @@
1
+ #!/usr/bin/env/ruby
2
+ # -*- coding: utf-8 -*-
3
+ # pslm - psalm processing utility
4
+
5
+ require 'pslm'
6
+ require 'optparse'
7
+
8
+ require 'pslm/structuredsetup'
9
+
10
+ DEFAULT_SETUP = {
11
+ :general => {
12
+ :format => 'latex', # latex|pslm
13
+ },
14
+ :input => {
15
+ :has_title => true,
16
+ :title => nil, # to overwrite the title loaded from the input file
17
+ :join => false,
18
+ },
19
+ :output => Pslm::Outputter::DEFAULT_SETUP.dup
20
+ }
21
+
22
+ setup = StructuredSetup.new DEFAULT_SETUP
23
+ [:accents, :preparatory].each do |o|
24
+ setup[:output][:pointing].delete o
25
+ end
26
+
27
+ # TODO the setup below doesn't yet respect the structure of the options above
28
+ # TODO many of the options aren't implemented yet, some will never be
29
+ optparse = OptionParser.new do |opts|
30
+
31
+ opts.separator "== General options"
32
+
33
+ opts.on "-o", "--output FILE", "Save output to given path." do |out|
34
+ setup[:general][:output_file] = out
35
+ end
36
+
37
+ opts.on "-f", "--format F", "Select output format." do |f|
38
+ setup[:general][:format] = f
39
+ end
40
+
41
+ opts.separator "== Input interpretation"
42
+
43
+ opts.on "--no-title", "Don't consider the first line to contain a psalm title" do
44
+ setup[:input][:has_title] = false
45
+ end
46
+ opts.on "--set-title TITLE", "Manually set title" do |t|
47
+ setup[:input][:title] = t
48
+ end
49
+ opts.on "--append TEXT", "Text to be appended at the end (before processing)." do |t|
50
+ setup[:input][:append] = t
51
+ end
52
+ opts.on "-j", "--join", "Join all given input files" do
53
+ setup[:input][:join] = true
54
+ end
55
+
56
+ opts.separator "== Output formatting"
57
+
58
+ opts.on "--skip-title", "Don't set the title" do
59
+ setup[:output][:title][:template] = :no
60
+ end
61
+ opts.on "--title-template [TEMPLATE]", "Use a specified template instead of the default one." do |p|
62
+ setup[:output][:title][:template] = p
63
+ end
64
+ opts.on "-k", "--skip-verses NUM", Integer, "Skip initial verses" do |i|
65
+ setup[:output][:skip_verses] = i
66
+ end
67
+
68
+ opts.on "-a", "--accents NUMS", "a:b - Numbers of accents to be pointed in each half-verse" do |str|
69
+ a1, a2 = str.split ':'
70
+ if a1 && a1 != "" then
71
+ setup.get_dv(:output, :pointing, :accents, [])[0] = a1.to_i
72
+ end
73
+ if a2 && a2 != "" then
74
+ setup.get_dv(:output, :pointing, :accents, [])[1] = a2.to_i
75
+ end
76
+ end
77
+ # TODO merge with the previous option to a1[,p1]:a2[,p2]
78
+ opts.on "-p", "--preparatory-syllables NUMS", "a:b - How many preparatory syllables in each half-verse" do |str|
79
+ a1, a2 = str.split ':'
80
+ if a1 && a1 != "" then
81
+ setup.get_dv(:output, :pointing, :preparatory, [])[0] = a1.to_i
82
+ end
83
+ if a2 && a2 != "" then
84
+ setup.get_dv(:output, :pointing, :preparatory, [])[1] = a2.to_i
85
+ end
86
+ end
87
+ opts.on "-t", "--tone TONE", "point accents and preparatory syllables for a given psalm tone (like I.f or VIII.G)" do |str|
88
+ setup[:output][:pointing][:tone] = str
89
+ end
90
+
91
+ opts.on "-s", "--accents-style SYM", "underline (default) | bold" do |s|
92
+ sym = s.to_sym
93
+ setup[:output][:pointing][:accent_style] = sym
94
+ end
95
+ # Needs LaTeX package lettrine!
96
+ # TODO
97
+ opts.on "--lettrine", "Large first character of the psalm." do
98
+ setup[:output][:lettrine] = {}
99
+ end
100
+ opts.on "--split-verses", "Each verse part on it's own line" do
101
+ setup[:output][:parts][:novydvur_newlines] = true # like in the psalter of the Novy Dvur Trappist abbey
102
+ end
103
+ # TODO
104
+ opts.on "--pretitle TEXT", "Text to be printed as beginning of the title." do |t|
105
+ setup[:output][:prepend_text] = t
106
+ end
107
+ opts.on "--output-append TEXT", "Text to be appended at the end (of the last line after processing)." do |t|
108
+ setup[:output][:final_add_content] = {:append => t}
109
+ end
110
+ # This is useful when we want to append a doxology after the psalm
111
+ # as a separate paragraph
112
+ # TODO
113
+ opts.on "--linebreak-at-the-end", "Make a line-break after the last line" do
114
+ setup[:output][:line_break_last_line] = true
115
+ end
116
+ opts.on "--dashes", "Dash at the end of each psalm paragraph" do
117
+ setup[:output][:strophes][:end_marks] = :semantic
118
+ end
119
+ # TODO
120
+ opts.on "--no-paragraph", "No empty line after each psalm paragraph." do
121
+ setup[:output][:paragraph_space] = false
122
+ end
123
+ opts.on "--guillemets", "Convert american quotes to french ones (guillemets)." do
124
+ setup[:output][:quote] = :guillemets
125
+ end
126
+ # TODO
127
+ opts.on "-m", "--mark-short-verses", "Insert warning marks in verses that are too short" do
128
+ setup[:output][:mark_short_verses] = true
129
+ end
130
+ opts.on "--wrapper NAME", "Wrap output in a wrapper with the given name" do |n|
131
+ setup[:output][:wrapper][:environment_name] = n
132
+ end
133
+ end
134
+
135
+ optparse.parse!
136
+
137
+ # use default pointing setup if necessary
138
+ unless setup[:output][:pointing].has_key? :tone
139
+ [:accents, :preparatory].each do |o|
140
+ unless setup[:output][:pointing].has_key? o
141
+ setup[:output][:pointing][o] = DEFAULT_SETUP[:output][:pointing][o].dup
142
+ end
143
+ end
144
+ end
145
+
146
+ if ARGV.empty? then
147
+ raise "Program expects filenames as arguments."
148
+ end
149
+
150
+ Pslm::PsalmPointer.new(setup).process(ARGV, setup[:general][:output_file])
@@ -0,0 +1,17 @@
1
+ # main file of the pslm library
2
+
3
+ module Pslm
4
+ end
5
+
6
+ require_relative 'pslm/pslmreader'
7
+ require_relative 'pslm/psalm'
8
+ require_relative 'pslm/psalmpointer'
9
+ require_relative 'pslm/psalmpatterns'
10
+
11
+ require_relative 'pslm/outputter'
12
+ require_relative 'pslm/latexoutputter'
13
+ require_relative 'pslm/pslmoutputter'
14
+ require_relative 'pslm/consoleoutputter'
15
+
16
+ require_relative 'pslm/structuredsetup'
17
+ require_relative 'pslm/joinedinput'
@@ -0,0 +1,281 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'colorize'
4
+
5
+ module Pslm
6
+
7
+ # formats a psalm for console output
8
+ class ConsoleOutputter < Outputter
9
+
10
+ FORMATTER_ORDER = [
11
+ :pointing,
12
+ :parts,
13
+ :verses,
14
+ :skip_verses,
15
+ :title,
16
+ :strophes,
17
+ :prepend_text,
18
+ :output_append_text,
19
+ :line_break_last_line,
20
+ :mark_short_verses
21
+ ]
22
+
23
+ # takes a Psalm, returns a String with the psalm formatted
24
+ def process_psalm(psalm, opts={})
25
+ formatters = get_formatters(opts)
26
+
27
+ # build the output; on each step apply the appropriate method
28
+ # of each formatter in the given order
29
+ psalm_assembled = psalm.verses.collect do |verse|
30
+ process_verse(verse, opts, psalm, formatters)
31
+ end.delete_if {|v| v == '' }.join "\n"
32
+
33
+ return Formatter.format(formatters, :psalm,
34
+ psalm_assembled,
35
+ psalm)
36
+ end
37
+
38
+ alias :process :process_psalm
39
+
40
+ def process_verse(verse, opts, psalm=nil, formatters=nil)
41
+ formatters = formatters || get_formatters(opts)
42
+
43
+ verse_assembled = verse.parts.collect do |part|
44
+
45
+ part_assembled = part.words.reverse.collect do |word|
46
+
47
+ word_assembled = word.syllables.reverse.collect do |syll|
48
+ Formatter.format(formatters, :syllable,
49
+ syll, part, word, syll)
50
+ end.reverse.join ''
51
+
52
+ Formatter.format(formatters, :word,
53
+ word_assembled, word)
54
+ end.reverse.join ' '
55
+
56
+ Formatter.format(formatters, :part,
57
+ part_assembled, part)
58
+ end.join ''
59
+
60
+ return Formatter.format(formatters, :verse,
61
+ verse_assembled, psalm, verse)
62
+ end
63
+
64
+ # takes a Hash of options,
65
+ # returns a list of accordingly initialized Formatter instances
66
+ def get_formatters(options)
67
+ return FORMATTER_ORDER.collect do |f|
68
+ next unless options.include? f
69
+
70
+ get_formatter(f, options[f])
71
+ end.compact!
72
+ end
73
+
74
+ # takes a Symbol - name of a configuration option, and option/s value;
75
+ # returns an instance of a corresponding Formatter class or nil
76
+ def get_formatter(sym, options)
77
+ cls_name = sym.to_s.gsub(/_(\w)/) {|m| m[1].upcase }
78
+ cls_name[0] = cls_name[0].upcase
79
+ cls_name += 'Formatter'
80
+
81
+ if self.class.const_defined? cls_name then
82
+ return self.class.const_get(cls_name).new(options)
83
+ else
84
+ return nil
85
+ end
86
+ end
87
+
88
+ # abstract superclass of the formatters providing dumb implementation
89
+ # of all formatting methods
90
+ class Formatter
91
+
92
+ class << self
93
+ # lets all the :formatters: subsequently format :text: assembled from :obj: on the assembly :level:
94
+ def format(formatters, level, text, *args)
95
+ formatters.each do |f|
96
+ text = f.send("#{level}_format", text, *args)
97
+ end
98
+ return text
99
+ end
100
+ end
101
+
102
+ def initialize(options)
103
+ @options = options
104
+ @syll_counter = 0
105
+ @word_counter = 0
106
+ @part_counter = 0
107
+ @verse_counter = 0
108
+ end
109
+
110
+ def psalm_format(text, psalm)
111
+ @syll_counter = 0
112
+ @word_counter = 0
113
+ @part_counter = 0
114
+ @verse_counter = 0
115
+ text
116
+ end
117
+
118
+ def verse_format(text, psalm, verse)
119
+ @verse_counter += 1
120
+ @syll_counter = 0
121
+ @word_counter = 0
122
+ @part_counter = 0
123
+ text
124
+ end
125
+
126
+ def part_format(text, part)
127
+ @part_counter += 1
128
+ @syll_counter = 0
129
+ @word_counter = 0
130
+ text
131
+ end
132
+
133
+ def word_format(text, word)
134
+ @word_counter += 1
135
+ text
136
+ end
137
+
138
+ def syllable_format(text, part, word, syll)
139
+ @syll_counter += 1
140
+ text
141
+ end
142
+ end
143
+
144
+ # marks accentuated and preparatory syllables
145
+ class PointingFormatter < Formatter
146
+ def initialize(options)
147
+ super(options)
148
+ @accent_counter = 0
149
+ @preparatories_counter = 0
150
+
151
+ # validate options
152
+ if @options.has_key? :tone and
153
+ (@options.has_key? :accents or @options.has_key? :preparatory) then
154
+ raise RuntimeError.new('Overconfigured: both accents/preparatories number and psalm tone specified.')
155
+ elsif @options.has_key? :accents then
156
+ # ok, nothing to do
157
+ elsif @options.has_key? :tone
158
+ # convert psalm tone identifier to numbers
159
+ tone = PsalmPatterns.default.tone_data_str(@options[:tone])
160
+ @options[:accents] = tone.collect {|part| part[0] }
161
+ @options[:preparatory] = tone.collect {|part| part[1] }
162
+ end
163
+
164
+ if @options[:accent_style] != nil then
165
+ if MARKS.has_key? @options[:accent_style] then
166
+ @accent_style = MARKS[@options[:accent_style]]
167
+ else
168
+ # user_defined style
169
+ @accent_style = @options[:accent_style].to_sym
170
+ end
171
+ else
172
+ @accent_style = :blue
173
+ end
174
+
175
+ @preparatory_style = :magenta
176
+ end
177
+
178
+ def part_format(text, part)
179
+ super(text, part)
180
+ @accent_counter = 0
181
+ @preparatories_counter = 0
182
+ text
183
+ end
184
+
185
+ MARKS = {
186
+ :underline => {:color => :blue, :mode => :underline},
187
+ :bold => {:color => :blue, :mode => :bold},
188
+ :semantic => {:color => :blue, :mode => :bold}
189
+ }
190
+
191
+ def syllable_format(text, part, word, syll)
192
+ super(text, part, word, syll)
193
+ r = text
194
+ if syll.accent? then
195
+ @accent_counter += 1
196
+ if @accent_counter <= num_accents_for(part) then
197
+ r = r.colorize @accent_style
198
+ end
199
+ end
200
+
201
+
202
+ if num_preparatory_syllables_for(part) > 0 and
203
+ @accent_counter >= num_accents_for(part) then
204
+
205
+ if @preparatories_counter >= 1 and
206
+ @preparatories_counter <= num_preparatory_syllables_for(part) then
207
+ r = r.colorize @preparatory_style
208
+ end
209
+
210
+ @preparatories_counter += 1
211
+ end
212
+
213
+ return r
214
+ end
215
+
216
+ private
217
+
218
+ # how many accents to mark in this verse-part?
219
+ def num_accents_for(part)
220
+ case part.pos
221
+ when :flex
222
+ 1
223
+ when :first
224
+ @options[:accents][0]
225
+ when :second
226
+ @options[:accents][1]
227
+ end
228
+ end
229
+
230
+ # how many preparatory syllables to mark in this verse-part?
231
+ def num_preparatory_syllables_for(part)
232
+ case part.pos
233
+ when :flex
234
+ 0
235
+ when :first
236
+ @options[:preparatory][0]
237
+ when :second
238
+ @options[:preparatory][1]
239
+ end
240
+ end
241
+ end
242
+
243
+ # formatting of verse parts -
244
+ # adds part dividing marks (flex, asterisk),
245
+ # eventually inserts newlines
246
+ class PartsFormatter < Formatter
247
+
248
+ MARKS = { :flex => ' + ', :first => ' * ', :second => ' ' }
249
+
250
+ def part_format(text, part)
251
+ text + MARKS[part.pos].colorize(:color => :light_blue) +
252
+ ((@options[:novydvur_newlines] && part.pos != :second) ? "\n" : '')
253
+ end
254
+ end
255
+
256
+ # skips verses at the beginning
257
+ class SkipVersesFormatter < Formatter
258
+ def initialize(options)
259
+ super(options)
260
+ @skip_verses = @options # takes just one number as a parameter
261
+ end
262
+
263
+ def verse_format(text, psalm, verse)
264
+ #super(text, psalm, verse)
265
+ @verse_counter += 1
266
+ if @verse_counter <= @skip_verses then
267
+ return ""
268
+ end
269
+
270
+ return text
271
+ end
272
+ end
273
+
274
+ # formats title
275
+ class TitleFormatter < Formatter
276
+ def psalm_format(text, psalm)
277
+ psalm.header.title.colorize(:mode => :bold) + "\n\n" + text
278
+ end
279
+ end
280
+ end
281
+ end