Sprichwoerter 0.1 → 1.6
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 +5 -5
- data/Sprichwoerter.gemspec +17 -0
- data/bin/proverbs +43 -2
- data/bin/sprichwoerter +48 -2
- data/doc/html/proverbs.html +472 -0
- data/doc/html/sprichwoerter.html +475 -0
- data/doc/man/proverbs.6.gz +0 -0
- data/doc/man/sprichwoerter.6.gz +0 -0
- data/doc/pdf/proverbs.pdf +0 -0
- data/doc/pdf/sprichwoerter.pdf +0 -0
- data/doc/rst/proverbs.rst +117 -0
- data/doc/rst/sprichwoerter.rst +123 -0
- data/lib/adder.rb +91 -0
- data/lib/argparser.rb +128 -0
- data/lib/color_output.rb +44 -0
- data/lib/liste_de.rb +31 -9
- data/lib/liste_en.rb +134 -86
- data/lib/log.conf +55 -0
- data/lib/logging.rb +193 -0
- data/lib/rearranging.rb +47 -0
- data/lib/sprichw/303/266rter.rb +178 -29
- data/lib/translating.rb +101 -0
- data/lib/translations +164 -0
- data/lib/user_input.rb +48 -0
- data/lib/version.rb +25 -0
- metadata +28 -7
data/lib/rearranging.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
#encoding: UTF-8
|
2
|
+
|
3
|
+
=begin
|
4
|
+
/***************************************************************************
|
5
|
+
* ©2014-2019, Michael Uplawski <michael.uplawski@uplawski.eu> *
|
6
|
+
* *
|
7
|
+
* This program is free software; you can redistribute it and/or modify *
|
8
|
+
* it under the terms of the GNU General Public License as published by *
|
9
|
+
* the Free Software Foundation; either version 3 of the License, or *
|
10
|
+
* (at your option) any later version. *
|
11
|
+
* *
|
12
|
+
* This program is distributed in the hope that it will be useful, *
|
13
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
14
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
15
|
+
* GNU General Public License for more details. *
|
16
|
+
* *
|
17
|
+
* You should have received a copy of the GNU General Public License *
|
18
|
+
* along with this program; if not, write to the *
|
19
|
+
* Free Software Foundation, Inc., *
|
20
|
+
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
21
|
+
***************************************************************************/
|
22
|
+
=end
|
23
|
+
|
24
|
+
=begin
|
25
|
+
Functions which rearrange an array.
|
26
|
+
=end
|
27
|
+
module Rearranging
|
28
|
+
|
29
|
+
public
|
30
|
+
# ... guess
|
31
|
+
def randomize
|
32
|
+
if( self.respond_to?(:to_ary) )
|
33
|
+
size = self.length
|
34
|
+
original_list = self.dup
|
35
|
+
random_list = Array.new
|
36
|
+
while(random_list.size < size) do
|
37
|
+
srand(Time::now.nsec)
|
38
|
+
index = rand(original_list.size)
|
39
|
+
item = original_list.delete_at(index)
|
40
|
+
random_list << item
|
41
|
+
end
|
42
|
+
self.replace(random_list)
|
43
|
+
else
|
44
|
+
raise TypeError.new('can only randomize Array, not ' << self.class.name)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/lib/sprichw/303/266rter.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
#encoding: UTF-8
|
3
3
|
=begin
|
4
4
|
/***************************************************************************
|
5
|
-
* ©2016-
|
5
|
+
* ©2016-2019 Michael Uplawski <michael.uplawski@uplawski.eu> *
|
6
6
|
* *
|
7
7
|
* This program is free software; you can redistribute it and/or modify *
|
8
8
|
* it under the terms of the GNU General Public License as published by *
|
@@ -21,39 +21,188 @@
|
|
21
21
|
***************************************************************************/
|
22
22
|
=end
|
23
23
|
|
24
|
+
require_relative 'user_input'
|
25
|
+
require_relative 'argparser'
|
26
|
+
require_relative 'translating'
|
27
|
+
require_relative 'rearranging'
|
28
|
+
require_relative 'logging'
|
24
29
|
|
25
|
-
|
30
|
+
# Main application class.
|
26
31
|
class SprichWoerter
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
32
|
+
include Translating
|
33
|
+
self.extend( Logging)
|
34
|
+
@@log = self.init_logger(STDOUT)
|
35
|
+
# An object of this class acts as a functor. Calling new() is thus the only
|
36
|
+
# available access to all its functionality.
|
37
|
+
#def initialize(lang='de', action = :create)
|
38
|
+
|
39
|
+
def initialize(lang='de', args)
|
40
|
+
@lang = lang
|
41
|
+
@log = @@log
|
42
|
+
@options = ArgParser.parse(ARGV)
|
43
|
+
@log.debug("options are: " << @options.inspect)
|
44
|
+
listfile = 'liste' << '_' << @lang
|
45
|
+
# ------------- language is set --------------
|
46
|
+
@confdir = ENV['HOME'].dup << File::Separator << ".proverbs"
|
47
|
+
|
48
|
+
if(@options.list)
|
49
|
+
show_favorites
|
50
|
+
exit 0
|
51
|
+
end
|
52
|
+
user_list = @confdir.dup << File::Separator << listfile
|
53
|
+
# cosmetics
|
54
|
+
listrb = user_list << '.rb'
|
55
|
+
|
56
|
+
if File::exist?(listrb) && File.readable?(listrb)
|
57
|
+
require user_list
|
58
|
+
else
|
59
|
+
require_relative listfile
|
60
|
+
end
|
61
|
+
# ------------- proverbs are identified ---------
|
62
|
+
if @options.add
|
63
|
+
Adder.new(@lang, @options.add, *ARGV)
|
64
|
+
exit true
|
65
|
+
end
|
66
|
+
|
67
|
+
# borders
|
68
|
+
up_left = '┌'
|
69
|
+
up_right = '┐'
|
70
|
+
bottom_left = '└'
|
71
|
+
bottom_right = '┘'
|
72
|
+
hor = '─'
|
73
|
+
vert = '│'
|
74
|
+
srand(Time.now.nsec)
|
75
|
+
# group 0 or group 1 ?
|
76
|
+
sfx = [0, 1][rand(2)]
|
77
|
+
proverbs = eval("$proverbs" + sfx.to_s)
|
78
|
+
# This appears to improve the randomness :
|
79
|
+
# allow for the list of proverbs to be 'rearranged' ...
|
80
|
+
proverbs.extend(Rearranging)
|
81
|
+
# ... and do it, each time.
|
82
|
+
# This seeds the pseudo-random generator anew
|
83
|
+
proverbs.randomize
|
84
|
+
num_pvs = proverbs.size
|
85
|
+
first = ''
|
86
|
+
# Find 1 original proverb in the group.
|
87
|
+
until !first.empty?
|
88
|
+
# determine the index of an original proverb.
|
89
|
+
fi = rand(num_pvs)
|
90
|
+
# read the beginning of the proverb
|
91
|
+
second = first = proverbs[fi][0]
|
92
|
+
si = fi
|
93
|
+
end
|
94
|
+
srand(Time.now.nsec)
|
95
|
+
# Find a second proverb, different from the first.
|
96
|
+
until (si != fi && proverbs[si][0] != first && !second.empty?)
|
97
|
+
si = rand(num_pvs)
|
98
|
+
# read the end of the proverb
|
99
|
+
second = proverbs[si][1]
|
100
|
+
end
|
101
|
+
# Construct the new proverb.
|
102
|
+
phr = first << ' ' << second << '.'
|
103
|
+
|
104
|
+
#draw
|
105
|
+
len = phr.size
|
106
|
+
# TODO: Wrap text if needed, determine number of line-breaks, then draw 1
|
107
|
+
# border around all lines of text.
|
108
|
+
col = @options.color
|
109
|
+
puts "" << maybe_in_color(up_left << hor * len << up_right, col)
|
110
|
+
puts "" << maybe_in_color(vert, col) << phr << maybe_in_color(vert, col)
|
111
|
+
puts "" << maybe_in_color(bottom_left << hor * len << bottom_right, col)
|
112
|
+
# Allow the new proverb to be rated
|
113
|
+
qualify( phr) if @options.qualify
|
114
|
+
end
|
115
|
+
|
116
|
+
# This function wraps a call to eval(). It also verifies that a color is
|
117
|
+
# set, although a default should apply, if not.
|
118
|
+
def maybe_in_color(txt, color)
|
119
|
+
if @options.color
|
120
|
+
cmd = @options.color + ' "' << txt << '"'
|
121
|
+
eval (cmd)
|
122
|
+
else
|
123
|
+
txt
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def show_favorites
|
128
|
+
puts read_qualifile[0].join("\n")
|
129
|
+
end
|
47
130
|
|
48
|
-
|
49
|
-
|
131
|
+
# Find the file with the list of rated, generated proverbs. Returns
|
132
|
+
# an Array of those proverbs and the path to the file itself.
|
133
|
+
def read_qualifile
|
134
|
+
qualifile = @confdir.dup << File::Separator << 'qualifile_' << @lang
|
135
|
+
lines = Array.new
|
136
|
+
if(File.exist?(qualifile) )
|
137
|
+
msg = nil
|
138
|
+
if(!File.readable?(qualifile) )
|
139
|
+
msg = trl("ERROR") << '!' << trl("The file %s cannot be opened for reading!") %qualifile
|
140
|
+
elsif (!File.writable?(qualifile) )
|
141
|
+
msg = trl("ERROR") << '!' << trl("The file %s cannot be opened for writing!") %qualifile
|
142
|
+
end
|
143
|
+
if msg
|
144
|
+
puts msg
|
145
|
+
exit false
|
146
|
+
else
|
147
|
+
qf = File.open(qualifile, 'a+')
|
148
|
+
lines = qf.readlines(chomp:true)
|
149
|
+
end
|
150
|
+
else
|
151
|
+
if !File.exist?(@confdir)
|
152
|
+
Dir.mkdir(@confdir)
|
153
|
+
end
|
154
|
+
qf = File.new(qualifile, 'w')
|
155
|
+
end
|
156
|
+
qf.close
|
157
|
+
return lines, qualifile
|
158
|
+
end
|
50
159
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
160
|
+
# Rate a proverb. For the time, only a simple, positive rating is possible.
|
161
|
+
def qualify(phr)
|
162
|
+
# Create a cheap busy-indicator; Asynchronously count down from 5 to 1.
|
163
|
+
thr = Thread.new do
|
164
|
+
5.downto(1) do |n|
|
165
|
+
print n
|
166
|
+
sleep 1
|
167
|
+
print "\b"
|
168
|
+
if(n == 1)
|
169
|
+
print("\n")
|
170
|
+
exit true
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
msg = trl("Push '+' for a positive rating") << ".\n"
|
175
|
+
puts msg
|
176
|
+
# Wait for user-input while the count-down is running.
|
177
|
+
# The loop serves to re
|
178
|
+
while thr.alive? do
|
179
|
+
user_input = wait_for_user
|
180
|
+
if ('+' == user_input.chr.downcase )
|
181
|
+
# Terminate the count-down, if the user pushed '+'
|
182
|
+
thr.terminate
|
183
|
+
qf = nil
|
184
|
+
lines, qf = read_qualifile
|
185
|
+
if (qf && !lines.include?(phr))
|
186
|
+
# add the latest generated proverb
|
187
|
+
File.write(qf, phr + "\n", :mode=>'a+')
|
188
|
+
puts "\b" << trl('Done')
|
189
|
+
exit true
|
190
|
+
end
|
191
|
+
# Handle Ctrl+c, Ctrl+d and Esc in the same way.
|
192
|
+
elsif [3,4,27].include? user_input
|
193
|
+
thr.terminate
|
194
|
+
puts "\n"
|
195
|
+
exit true
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
55
199
|
end
|
56
200
|
|
57
201
|
if __FILE__ == $0
|
58
|
-
|
202
|
+
if !ARGV.empty?
|
203
|
+
SprichWoerter.new(ARGV[0])
|
204
|
+
else
|
205
|
+
SprichWoerter.new('de')
|
206
|
+
end
|
59
207
|
end
|
208
|
+
# EOF
|
data/lib/translating.rb
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
#encoding: UTF-8
|
2
|
+
=begin
|
3
|
+
/***************************************************************************
|
4
|
+
* ©2011-2019, Michael Uplawski <michael.uplawski@uplawski.eu> *
|
5
|
+
* *
|
6
|
+
* This program is free software; you can redistribute it and/or modify *
|
7
|
+
* it under the terms of the GNU General Public License as published by *
|
8
|
+
* the Free Software Foundation; either version 3 of the License, or *
|
9
|
+
* (at your option) any later version. *
|
10
|
+
* *
|
11
|
+
* This program is distributed in the hope that it will be useful, *
|
12
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
13
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
14
|
+
* GNU General Public License for more details. *
|
15
|
+
* *
|
16
|
+
* You should have received a copy of the GNU General Public License *
|
17
|
+
* along with this program; if not, write to the *
|
18
|
+
* Free Software Foundation, Inc., *
|
19
|
+
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
20
|
+
***************************************************************************/
|
21
|
+
=end
|
22
|
+
|
23
|
+
|
24
|
+
RD = File.expand_path(File.dirname(__FILE__) ) + File::SEPARATOR if !defined?(RD)
|
25
|
+
|
26
|
+
require 'yaml'
|
27
|
+
|
28
|
+
# A way to produce translated text in a ruby-program.
|
29
|
+
# Translations are read from a file "translations" in the program folder.
|
30
|
+
module Translating
|
31
|
+
# There are better ways to extend a translated
|
32
|
+
# string, but I keep the 'wild-card' for
|
33
|
+
# historical reasons.
|
34
|
+
|
35
|
+
@@lang = nil
|
36
|
+
@@lang_file = format("%s%s", RD, 'LANG')
|
37
|
+
@@tr = YAML::load_file("#{RD}translations")
|
38
|
+
|
39
|
+
# find the current language-setting and return it.
|
40
|
+
def self.language()
|
41
|
+
if @@lang == nil
|
42
|
+
r = ENV['LANG']
|
43
|
+
if(r)
|
44
|
+
@@lang = r[0, 2]
|
45
|
+
elsif( File.exist?(@@lang_file) && File.readable?(@@lang_file) && File::size(@@lang_file) >= 2)
|
46
|
+
File::open(@@lang_file, 'r') {|f| @@lang = f.readline}
|
47
|
+
@@lang.chomp!.downcase! if @@lang
|
48
|
+
end
|
49
|
+
end
|
50
|
+
@@lang = 'en' if !@@lang
|
51
|
+
end
|
52
|
+
|
53
|
+
# Translate a string to the currently set langage.
|
54
|
+
# Note that the argument may contain a format-string
|
55
|
+
# in sprintf-syntax.
|
56
|
+
def self.trl(t)
|
57
|
+
Translating::language()
|
58
|
+
lt = @@tr[t]
|
59
|
+
if(lt)
|
60
|
+
lt = lt[@@lang]
|
61
|
+
else
|
62
|
+
# File.open('/tmp/mtf', 'a+') {|f| f << t << "\n"}
|
63
|
+
puts "\nTRANSLATION MISSING: \"" << t << "\""
|
64
|
+
end
|
65
|
+
lt ||= t
|
66
|
+
return lt
|
67
|
+
end
|
68
|
+
|
69
|
+
# Translate a string to the currently set langage.
|
70
|
+
# Note that the argument may contain a format-string
|
71
|
+
# in sprintf-syntax.
|
72
|
+
def trl(t )
|
73
|
+
Translating::trl(t)
|
74
|
+
end
|
75
|
+
|
76
|
+
# Translate in the given string only those words for which a translation
|
77
|
+
# is found.
|
78
|
+
# This is useful for mixed content like dates: "Friday, 8. July 2011".
|
79
|
+
# As the order changes with the locale, alphabetic content is matched and the
|
80
|
+
# remainder discarded.
|
81
|
+
def self::trl_words(str)
|
82
|
+
n_str = str.clone
|
83
|
+
loop do
|
84
|
+
m = str.match(/[[:alpha:]]+/)
|
85
|
+
break if !m
|
86
|
+
str.gsub!(m.to_s, '')
|
87
|
+
n_str.gsub!(m.to_s, trl(m.to_s))
|
88
|
+
end
|
89
|
+
return n_str
|
90
|
+
end
|
91
|
+
# Translate in the given string only those words for which a translation
|
92
|
+
# exists.
|
93
|
+
# This is useful for mixed content like dates: "Friday, 8. July 2011".
|
94
|
+
# As the order changes with the locale, alphabetic content is matched and the
|
95
|
+
# remainder discarded.
|
96
|
+
def trl_words(str)
|
97
|
+
Translating::trl_words(str)
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
|
data/lib/translations
ADDED
@@ -0,0 +1,164 @@
|
|
1
|
+
list:
|
2
|
+
de: liste
|
3
|
+
|
4
|
+
Execute with option -h to see an option summary:
|
5
|
+
de: Starten Sie das Program mit -h um die Erklärung der Kommandozeilenargumente zu sehen.
|
6
|
+
|
7
|
+
invalid option:
|
8
|
+
de: Ungültiges Argument
|
9
|
+
|
10
|
+
missing argument:
|
11
|
+
de: Fehlender Wert
|
12
|
+
|
13
|
+
for option:
|
14
|
+
de: für Option
|
15
|
+
|
16
|
+
Error!:
|
17
|
+
de: Fehler!
|
18
|
+
|
19
|
+
Invalid color value:
|
20
|
+
de: Ungültiger Farbname
|
21
|
+
|
22
|
+
Singular or plural (s, p):
|
23
|
+
de: Singular oder Plural (s, p)
|
24
|
+
|
25
|
+
s:
|
26
|
+
de: s
|
27
|
+
|
28
|
+
p:
|
29
|
+
de: p
|
30
|
+
|
31
|
+
singular:
|
32
|
+
de: singular
|
33
|
+
|
34
|
+
plural:
|
35
|
+
de: plural
|
36
|
+
|
37
|
+
Cannot add the proverb, invalid argument:
|
38
|
+
de: Kann das Sprichwort nicht hinzufügen, ungültiges Argument
|
39
|
+
|
40
|
+
List %s has been updated:
|
41
|
+
de: Liste %s wurde aktualisiert
|
42
|
+
|
43
|
+
Push '+' for a positive rating:
|
44
|
+
de: Drücken Sie ‚+’, um das Sprichwort positiv zu bewerten
|
45
|
+
|
46
|
+
Done:
|
47
|
+
de: Fertig
|
48
|
+
a:
|
49
|
+
de: n
|
50
|
+
|
51
|
+
add:
|
52
|
+
de: neu
|
53
|
+
|
54
|
+
GROUP:
|
55
|
+
de: GRUPPE
|
56
|
+
|
57
|
+
LANG:
|
58
|
+
de: SPRACHE
|
59
|
+
|
60
|
+
f:
|
61
|
+
de: l
|
62
|
+
|
63
|
+
l:
|
64
|
+
de: s
|
65
|
+
|
66
|
+
Language:
|
67
|
+
de: Sprache
|
68
|
+
|
69
|
+
lang:
|
70
|
+
de: sprache
|
71
|
+
|
72
|
+
favorites:
|
73
|
+
de: liste
|
74
|
+
|
75
|
+
q:
|
76
|
+
de: w
|
77
|
+
|
78
|
+
qualify:
|
79
|
+
de: werten
|
80
|
+
|
81
|
+
c:
|
82
|
+
de: f
|
83
|
+
|
84
|
+
-c:
|
85
|
+
de: -f
|
86
|
+
|
87
|
+
color:
|
88
|
+
de: farbe
|
89
|
+
|
90
|
+
h:
|
91
|
+
de: h
|
92
|
+
|
93
|
+
help:
|
94
|
+
de: hilfe
|
95
|
+
|
96
|
+
Usage:
|
97
|
+
de: Syntax
|
98
|
+
|
99
|
+
Specific options:
|
100
|
+
de: Spezielle Optionen
|
101
|
+
|
102
|
+
Add real proverb to the base:
|
103
|
+
de: Neues Sprichwort in Stammdaten aufnehmen
|
104
|
+
|
105
|
+
Beginning of the proverb:
|
106
|
+
de: Anfang des Sprichworts
|
107
|
+
|
108
|
+
Ending of the proverb:
|
109
|
+
de: Ende des Sprichworts
|
110
|
+
|
111
|
+
Set language:
|
112
|
+
de: Sprache festlegen
|
113
|
+
|
114
|
+
Show favorites:
|
115
|
+
de: Best Bewertete auflisten
|
116
|
+
|
117
|
+
Qualify proverbs:
|
118
|
+
de: Sprichwörter bewerten
|
119
|
+
|
120
|
+
Use color in program-output (one of red, green, yellow, purple, cyan, blue, white, black):
|
121
|
+
de: Farbige Programmausgabe (eine von rot, grün, gelb, lila, cyan, blau, weiß, schwarz)
|
122
|
+
|
123
|
+
Common options:
|
124
|
+
de: Allgemeine Optionen
|
125
|
+
|
126
|
+
Show this message:
|
127
|
+
de: Diese Meldung anzeigen
|
128
|
+
|
129
|
+
v:
|
130
|
+
de: v
|
131
|
+
|
132
|
+
version:
|
133
|
+
de: version
|
134
|
+
|
135
|
+
Show version and program information:
|
136
|
+
de: Versionsinformationen anzeigen
|
137
|
+
|
138
|
+
COLOR:
|
139
|
+
de: FARBE
|
140
|
+
|
141
|
+
red:
|
142
|
+
de: rot
|
143
|
+
|
144
|
+
green:
|
145
|
+
de: grün
|
146
|
+
|
147
|
+
purple:
|
148
|
+
de: lila
|
149
|
+
|
150
|
+
yellow:
|
151
|
+
de: gelb
|
152
|
+
|
153
|
+
cyan:
|
154
|
+
de: cyan
|
155
|
+
|
156
|
+
blue:
|
157
|
+
de: blau
|
158
|
+
|
159
|
+
white:
|
160
|
+
de: weiß
|
161
|
+
|
162
|
+
black:
|
163
|
+
de: schwarz
|
164
|
+
|