Sprichwoerter 0.1 → 1.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|