pslm 0.0.0
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 +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
|