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.
@@ -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
@@ -2,7 +2,7 @@
2
2
  #encoding: UTF-8
3
3
  =begin
4
4
  /***************************************************************************
5
- * ©2016-2016 Michael Uplawski <michael.uplawski@uplawski.eu> *
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
- def initialize(lang='de')
28
- require_relative 'liste_' << lang
29
- box = %w~┌ ┐ └ ┘ ─ │~
30
- num_pvs = $proverbs.size
31
- srand(Time.new.to_i)
32
- first = ''
33
- until !first.empty?
34
- fi = rand(num_pvs)
35
- second = first = $proverbs[fi][0]
36
- si = fi
37
- end
38
- until (si != fi && $proverbs[si][0] != first && !second.empty?)
39
- si = rand(num_pvs)
40
- second = $proverbs[si][1]
41
- end
42
- =begin
43
- puts ($proverbs[fi].to_s << " (" << fi.to_s << ")")
44
- puts ($proverbs[si].to_s << " (" << si.to_s << ")")
45
- =end
46
- phr = first << ' ' << second << '.'
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
- #draw
49
- len = phr.size
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
- puts "" << box[0] << box[4] * len << box[1]
52
- puts "" << box[5] << phr << box[5]
53
- puts "" << box[2] << box[4] * len << box[3]
54
- end
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
- sp = SprichWoerter.new(ARGV[0])
202
+ if !ARGV.empty?
203
+ SprichWoerter.new(ARGV[0])
204
+ else
205
+ SprichWoerter.new('de')
206
+ end
59
207
  end
208
+ # EOF
@@ -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
+
@@ -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
+