pslm 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/pslm.rb +150 -0
- data/lib/pslm.rb +17 -0
- data/lib/pslm/consoleoutputter.rb +281 -0
- data/lib/pslm/joinedinput.rb +42 -0
- data/lib/pslm/latexoutputter.rb +449 -0
- data/lib/pslm/outputter.rb +47 -0
- data/lib/pslm/psalm.rb +149 -0
- data/lib/pslm/psalmpatterns.rb +97 -0
- data/lib/pslm/psalmpointer.rb +89 -0
- data/lib/pslm/psalmtones/solesmes196x.yml +22 -0
- data/lib/pslm/pslmoutputter.rb +71 -0
- data/lib/pslm/pslmreader.rb +225 -0
- data/lib/pslm/structuredsetup.rb +74 -0
- metadata +114 -0
checksums.yaml
ADDED
@@ -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
|
data/bin/pslm.rb
ADDED
@@ -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])
|
data/lib/pslm.rb
ADDED
@@ -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
|