timequiz 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/timequiz +26 -0
- data/doc/html/timequiz.html +515 -0
- data/doc/license.txt +674 -0
- data/doc/man/timequiz.6.gz +0 -0
- data/doc/pdf/timequiz.pdf +0 -0
- data/doc/rst/timequiz.rst +156 -0
- data/lib/adder.rb +74 -0
- data/lib/argparser.rb +85 -0
- data/lib/busy_indicator.rb +104 -0
- data/lib/color_output.rb +73 -0
- data/lib/console.rb +219 -0
- data/lib/constants.rb +41 -0
- data/lib/event.rb +41 -0
- data/lib/events.rb +45 -0
- data/lib/extstring.rb +161 -0
- data/lib/file_checking.rb +89 -0
- data/lib/logging.rb +204 -0
- data/lib/timequiz.rb +216 -0
- data/lib/user_input.rb +246 -0
- metadata +63 -0
data/lib/console.rb
ADDED
@@ -0,0 +1,219 @@
|
|
1
|
+
#encoding: UTF-8
|
2
|
+
|
3
|
+
=begin
|
4
|
+
/***************************************************************************
|
5
|
+
* Copyright © 2017-2017, 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
|
+
require_relative 'extstring'
|
25
|
+
require_relative 'user_input'
|
26
|
+
require_relative 'constants'
|
27
|
+
|
28
|
+
# Functions which create a user-interface in the terminal
|
29
|
+
module Console
|
30
|
+
# Some definitions which may change one day, become configurable one day,
|
31
|
+
# need to be accessed (one day) from somewhere else or not.
|
32
|
+
@@win_sequence = %w"won.. won.. Won.. WOn.. wON.. wON!. woN!! won!! won.! won.. _on.. __n.. ___.. ___.. w__.. wo_.. "
|
33
|
+
@@wait_sequence = %w"U\ V\ Y\ T\ |\ ¦\ :\ .\ _\ .\ o\ O\ "
|
34
|
+
@@fail_sequence = %w":-|\ :-|\ :-[\ :-[\ :-(\ :-(\ 8-(\ 8-(\ 8-(\ 8-(\ 8-(\ 8-(\ 8-(\ 8-(\ .... |... lo.. Los. LOso LOSe LOSE lOSE loSE lose"
|
35
|
+
@@points = 0
|
36
|
+
# start with some arbitrary events
|
37
|
+
def start_game
|
38
|
+
available = $events
|
39
|
+
clear
|
40
|
+
puts "Put the following events into the right chronological order (e.g.: 2 3 1)."
|
41
|
+
@m_events = Array.new
|
42
|
+
out = ''
|
43
|
+
$num_events.times do |i|
|
44
|
+
srand(Time.new.usec)
|
45
|
+
index = rand(available.length)
|
46
|
+
ev = Event.new(available.delete_at(index))
|
47
|
+
ev.disp_index = (i + 1)
|
48
|
+
@m_events << ev
|
49
|
+
out << (i + 1).to_s << ') ' << ev.title << "\n"
|
50
|
+
end
|
51
|
+
puts out.box(:left => 2)
|
52
|
+
response = nil
|
53
|
+
|
54
|
+
response = int_array_input($num_events, (1..$num_events) )
|
55
|
+
if response == :quit_game
|
56
|
+
score @@points
|
57
|
+
exit true
|
58
|
+
end
|
59
|
+
|
60
|
+
compare_order(response)
|
61
|
+
# good order of the response-array
|
62
|
+
if good_order(response)
|
63
|
+
@@points += $num_events
|
64
|
+
win
|
65
|
+
score(@@points)
|
66
|
+
else
|
67
|
+
lose
|
68
|
+
score(@@points)
|
69
|
+
end
|
70
|
+
|
71
|
+
# Start the loop. Add events as requested.
|
72
|
+
until @m_events.length == $MAX_NUM_EVENTS do
|
73
|
+
ui = ask_new_event
|
74
|
+
if ui == :quit_game
|
75
|
+
score @@points
|
76
|
+
exit true
|
77
|
+
end
|
78
|
+
if('a' == ui)
|
79
|
+
ev = new_event
|
80
|
+
if ev == :all_events_done
|
81
|
+
score(@@points)
|
82
|
+
exit true
|
83
|
+
end
|
84
|
+
|
85
|
+
# ------> unresolved trouble with 0-based array.indices. <----------
|
86
|
+
# 1) exclude new event from the choices (hence -1), allow 0 as 'earlier than any'.
|
87
|
+
r = int_input(0..(@m_events.length - 1) )
|
88
|
+
if r == :quit_game
|
89
|
+
score @@points
|
90
|
+
exit true
|
91
|
+
end
|
92
|
+
# User-input can be 0, which complicates the comparison with the
|
93
|
+
# 0-based event-array.
|
94
|
+
|
95
|
+
# 2) in the range of known events, if not 0 (hence 0 is allowed).
|
96
|
+
position_by_user(r)
|
97
|
+
|
98
|
+
# 4) 'order' must fit in between the indices of the event-array (0-based, hence -1. Again.)
|
99
|
+
ok = good_order(r - 1, ev)
|
100
|
+
|
101
|
+
sort_years(true)
|
102
|
+
# 5) show the resulting order as starting from 1, not 0.
|
103
|
+
show_correct_order
|
104
|
+
# <---------- This should be it. ------------>
|
105
|
+
|
106
|
+
if ok
|
107
|
+
@@points += 1
|
108
|
+
win
|
109
|
+
score(@@points)
|
110
|
+
else
|
111
|
+
lose
|
112
|
+
score(@@points)
|
113
|
+
end
|
114
|
+
else
|
115
|
+
detail( a2i(ui) )
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
|
121
|
+
def clear
|
122
|
+
system 'clear'
|
123
|
+
end
|
124
|
+
|
125
|
+
|
126
|
+
# add a new event to the game
|
127
|
+
def new_event
|
128
|
+
known_events = @m_events.collect {|ev| ev.title}
|
129
|
+
available = $events.collect {|ev| ev unless known_events.include?(ev[0]) }.compact
|
130
|
+
if !available || available.empty?
|
131
|
+
puts "\n\tNo more events available. Aborting. Bye"
|
132
|
+
puts
|
133
|
+
return :all_events_done
|
134
|
+
end
|
135
|
+
clear
|
136
|
+
out = ''
|
137
|
+
@m_events.each_with_index {|ev, i| out << (i + 1).to_s << ') ' << ev.title << "\n"}
|
138
|
+
puts out.box(:left => 2)
|
139
|
+
|
140
|
+
puts "Indicate the event from the previous list, which precedes the following, or '0' (zero) to put it in front:"
|
141
|
+
srand(Time.new.usec)
|
142
|
+
index = rand(available.length)
|
143
|
+
ev = Event.new(available[index])
|
144
|
+
@m_events << ev
|
145
|
+
puts ev.title.box(:color => :yellow)
|
146
|
+
return ev
|
147
|
+
end
|
148
|
+
|
149
|
+
def a2i(array)
|
150
|
+
UserInput::a2i(array)
|
151
|
+
end
|
152
|
+
|
153
|
+
def int_input(range = nil)
|
154
|
+
UserInput::int_input(range)
|
155
|
+
end
|
156
|
+
def int_array_input(len, range)
|
157
|
+
UserInput::int_array_input(len, range )
|
158
|
+
end
|
159
|
+
|
160
|
+
def ask_new_event
|
161
|
+
puts "\nEnter number for more information about an event, 'a' to play with one new, random event, 'q' to quit."
|
162
|
+
UserInput::input()
|
163
|
+
end
|
164
|
+
|
165
|
+
def score(pts)
|
166
|
+
puts ' (Current score: %i %s)' %[pts, (pts == 1 ? 'point' : 'points')]
|
167
|
+
end
|
168
|
+
|
169
|
+
def lose
|
170
|
+
cmt = 'You ' << red('lose.')
|
171
|
+
wait @@fail_sequence, 1, cmt
|
172
|
+
end
|
173
|
+
|
174
|
+
def win
|
175
|
+
cmt = 'You ' << cyan(' W O N !!')
|
176
|
+
wait(@@win_sequence, 1, cmt)
|
177
|
+
end
|
178
|
+
|
179
|
+
def show_correct_order
|
180
|
+
cmt = "\tThe right order is:\n" << @m_events.collect {|ev| (@m_events.index(ev) + 1).to_s << ') ' << ev.title << ' (' << ev.year.to_s << ')'}.join("\n").box()
|
181
|
+
wait(@@wait_sequence, 1, cmt)
|
182
|
+
end
|
183
|
+
|
184
|
+
# show information on an event
|
185
|
+
def detail(num)
|
186
|
+
if(0 != num && num <= @m_events.length)
|
187
|
+
det = @m_events.detect{|ev| ev.disp_index == num}.detail
|
188
|
+
if(det && !det.empty?)
|
189
|
+
puts ("\n" << num.to_s << ') ' << det).box(:color => :green)
|
190
|
+
else
|
191
|
+
puts " - No details known -"
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
def position_by_user(p)
|
197
|
+
if(p > 0)
|
198
|
+
puts "\n... You say: " << bold("after \"" << @m_events[p-1].title << "\"")
|
199
|
+
else
|
200
|
+
puts "\n... You say: " << bold("Earlier than any of the listed events")
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
def compare_order(response)
|
205
|
+
puts "\n... You say: " << bold(response.join(', '))
|
206
|
+
devents = @m_events.dup.sort {|f, s| f.year <=> s.year }
|
207
|
+
cmt = "\tThe right order is:\n" << devents.collect {|ev| ev.disp_index.to_s << ') ' << ev.year.to_s }.join("\n").box()
|
208
|
+
wait(@@wait_sequence, 1, cmt)
|
209
|
+
end
|
210
|
+
|
211
|
+
def wait(seq, sec, cmt)
|
212
|
+
bi = BusyIndicator.new(false)
|
213
|
+
bi.sequence = seq
|
214
|
+
bi.run
|
215
|
+
sleep sec
|
216
|
+
bi.stop(cmt)
|
217
|
+
end
|
218
|
+
|
219
|
+
end
|
data/lib/constants.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
#encoding: UTF-8
|
2
|
+
|
3
|
+
=begin
|
4
|
+
/***************************************************************************
|
5
|
+
* Copyright © 2017-2017, 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
|
+
require_relative 'logging'
|
24
|
+
|
25
|
+
$APPNAME='Timequiz'
|
26
|
+
$VERSION = '0.1.3'
|
27
|
+
|
28
|
+
# number of initial events
|
29
|
+
$num_events = 3
|
30
|
+
# maximal, final number of events per game
|
31
|
+
$MAX_NUM_EVENTS = 15
|
32
|
+
$LOG_LEVEL=Logger::INFO
|
33
|
+
$events = Array.new
|
34
|
+
# Constants for the Gtk-Interface
|
35
|
+
# EVENTS
|
36
|
+
CLICKED = 'clicked'
|
37
|
+
ACTIVATE = 'activate'
|
38
|
+
ENTER = 'enter-notify-event'
|
39
|
+
LEAVE = 'leave'
|
40
|
+
TOGGLED = 'toggled'
|
41
|
+
|
data/lib/event.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
#encoding: UTF-8
|
2
|
+
|
3
|
+
=begin
|
4
|
+
/******************************************************************************
|
5
|
+
* Copyright © 2017-2017, 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
|
+
# An object of this class is representing a historical event.
|
25
|
+
class Event
|
26
|
+
|
27
|
+
def initialize(ev)
|
28
|
+
@title = ev[0]
|
29
|
+
@year = ev[1]
|
30
|
+
@detail = ev[2]
|
31
|
+
@disp_index = 0
|
32
|
+
end
|
33
|
+
|
34
|
+
def to_s
|
35
|
+
str = '' << self.class.name << '{ title=' << @title << ', year=' << @year.to_s << ', detail=' << @detail << ', disp_index=' << @disp_index.to_s << '}'
|
36
|
+
end
|
37
|
+
attr_reader :title, :year, :detail
|
38
|
+
attr_accessor :disp_index
|
39
|
+
end
|
40
|
+
#EOF
|
41
|
+
|
data/lib/events.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
#encoding: UTF-8
|
2
|
+
|
3
|
+
=begin
|
4
|
+
/******************************************************************************
|
5
|
+
* Copyright © 2017-2017, 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
|
+
# All events known.
|
25
|
+
$events << ['Foundation of the UNESCO', 1946, '(4/11/1946) The United Nations Educational, Scientific and Cultural Organization wants to intensify the cooperation between peoples by developing education, science and culture']
|
26
|
+
$events << ['Invention of soap', -1500, '']
|
27
|
+
$events << ['First honeybees', -100000000, '']
|
28
|
+
$events << ['Artisanal production of glass', -2500, '']
|
29
|
+
$events << ['Invention of the door key', -2000, '']
|
30
|
+
$events << ['Invention of the solar clock', -1500, '']
|
31
|
+
$events << ['The Roman emperor Diocletian devides the empire in two', 185 , 'Caius Aurelius Valerianus Diocletianus also devides the power as he lets Maximian rule the western part of the Roman Empire and eight years later associates with each of the two "Augustus" one lesser colegue and designated successor of the title "Cæsar".']
|
32
|
+
$events << ['The American Saxophonist William John Coltrane is born', 1926, 'Coltrane played with Miles Davis and Thelonious Monk, then founded his own quartet. Major recordings: "My Favourite Things" (1960) and "A Love Supreme" (1964)']
|
33
|
+
$events << ['The French architect Jacques Lemercier becomes the principal architect of Louis XIII', 1618, 'Lemercier is considered one of the initiators of the French Classicism']
|
34
|
+
$events << ['The treaty of Greenville (USA/Ohio)', 1795, 'The British company of Ohio has ended the French occupation of the territory in 1763. Already under US administration since 1783, with the end of the Indian wars (Greenville, 1795), Ohio could become the 17th US-state in 1803.']
|
35
|
+
$events << ['"Each acceptor of electrons is an acid and each emitter a base" (Gilbert Newton LEWIS).', 1938, 'Lewis worked after 1913 on the chemical liaisons between non-metalic atoms. Since 1923 he elaborates a theory on acids and bases.']
|
36
|
+
$events << ['Destruction of Nimrod and Ninive by the Medians and Neo-Babylonians', -612, 'The medians were nomads and had become a thread to the Assyrian empire when their tribes united under king Phraorte. The Assyrians fought several preventive wars but in the end lost their empire to the victorious Medians.']
|
37
|
+
$events << ['French writer François Rabelais dies', 1553, 'Rabelais work show the humanists\' enthusiasm for philosophy, moral and knowledge of antiquity, the wisdom of which he admired. His freedom of expression, wealth of vocabulary and imagination still appear unequalled.']
|
38
|
+
$events << ['The anarchist Léon Czolgoscz assassinates the US-president William McKinley', 1901, 'President since 1896, McKinley advocates a strict economic protectionism. The victory in the Spanish-American war of 1898 assures his easy re-election in 1900. After the murder, McKinley is replaced by his vice-president Theodor Rosevelt']
|
39
|
+
$events << ['The German army under General Alexander von Kluck reaches the River Marne for the first time', 1914, '(05/09/1914) The first battle of the Marne took place in 1914, when a weakened German 1st army under General von Kluck was attacked and finally beaten by the 6th French army under Maunoury with decisive assistance by the British corps under John French.']
|
40
|
+
$events << ['The Italian painter Lorenzo Lotto dies', 1556, 'Unable to stand his ground against contemporaries like Raphael (in Rome) and Titian (in Venise), Lotto retreats to Bergamo, where he paints his big religious compositions between 1518 and 1528.']
|
41
|
+
$events << ['End of the "War of the mercenaries"', -238, 'Out of work after the first punic war and discriminated, the mercenaries of Carthago unite in -240 with other dissatisfied people under the Libyan Matho, besiege the city of Utica, but get finally massacred by an army under Hamilcar Barca and Hannon the Great.']
|
42
|
+
$events << ['Independence of the Republic of Nicaragua', 1821, 'Discovered by Christopher Columbus in 1502, the country was conquered by Gonzales d\'Avila who bate the Indian chief Nicarao. Since 1560, Nicaragua was part of the territory of Guatemala.']
|
43
|
+
$events << ['First siege of Vienna (Austria) by Süleyman the Magnificent', 1529, 'Under sultan Süleyman, the Ottoman empire won much territory and prospered in all respects. In October 1529, the Turkish army of 120000 men could though not break the resistance of the citizens of Vienna and finally had to retreat.']
|
44
|
+
$events << ['The Roman empress Galla Placidia dies', 450, 'Born around the year 390 as the daughter of Theodosius I, she was first married to Alaric\'s brother in law, Athaulf, king of the Visigoths, then to the future Constantius III, a general of her brother Honorius who inherited from her the title of "Augustus". After Honorius\' death and at the decision of Theodosius II, grandson of Theodosius I and emperor of the orient, Galla Placida governed the western empire for her six year old son Valentinian (the future Valentinian III).']
|
45
|
+
$events << ['Birth of Kathleen Mansfield', 1888, '(1888 Wellington, New-Zealand). Of vivid sensibility, Katherine Mansfield is the most representative novelist and poet of the era after World War I. Her novels had the biggest success in France. She died in 1923 on tuberculosis.']
|
data/lib/extstring.rb
ADDED
@@ -0,0 +1,161 @@
|
|
1
|
+
#encoding: UTF-8
|
2
|
+
|
3
|
+
=begin
|
4
|
+
/******************************************************************************
|
5
|
+
* Copyright © 2017-2017, 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
|
+
require_relative 'color_output'
|
25
|
+
|
26
|
+
# Functions which extend the String-class. Simply require this file to add
|
27
|
+
# capabilities to each String-object in your code.
|
28
|
+
|
29
|
+
# For historical reasons. Probably obsolete
|
30
|
+
if(! String.method_defined?(:end_with?))
|
31
|
+
class String
|
32
|
+
def end_with?(str)
|
33
|
+
isso = false;
|
34
|
+
if(str.respond_to?(:to_str) && self.include?(str))
|
35
|
+
isso = (slice(rindex(str), (size()-1)) == str)
|
36
|
+
end
|
37
|
+
return isso
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Not obsolete
|
43
|
+
|
44
|
+
class String
|
45
|
+
|
46
|
+
# Draws a box around the content.
|
47
|
+
# TODO: the :padding option is currently disabled as it confuses me.
|
48
|
+
def box(opt = {})
|
49
|
+
# ---------------
|
50
|
+
# Welcome to hell
|
51
|
+
# ---------------
|
52
|
+
|
53
|
+
color = opt[:color]
|
54
|
+
|
55
|
+
upleft = color ? colorize("\u250F", color) : "\u250F"
|
56
|
+
upright = color ? colorize("\u2513", color) : "\u2513"
|
57
|
+
downleft = color ? colorize("\u2517", color) : "\u2517"
|
58
|
+
downright = color ? colorize("\u251B", color) : "\u251B"
|
59
|
+
|
60
|
+
vert = color ? colorize("\u2503", color) : "\u2503"
|
61
|
+
hor = color ? colorize("\u2501", color) : "\u2501"
|
62
|
+
|
63
|
+
left = opt[:left]
|
64
|
+
top = opt[:top]
|
65
|
+
# padding = opt[:padding]
|
66
|
+
|
67
|
+
min_width = opt[:min_width]
|
68
|
+
|
69
|
+
size = `stty size`.split.map { |x| x.to_i }.reverse
|
70
|
+
left ||= 0
|
71
|
+
top ||= 0
|
72
|
+
# padding ||= 0
|
73
|
+
|
74
|
+
min_width ||= 15
|
75
|
+
|
76
|
+
# max_width is the width of the screen - left margin - 2x border
|
77
|
+
max_width = size[0] - left - 2
|
78
|
+
|
79
|
+
gsub!("\t", ' ')
|
80
|
+
width = max_width
|
81
|
+
# wrap lines, maybe
|
82
|
+
wrap(width , /^\d\)/)
|
83
|
+
# determine the width of the box
|
84
|
+
width = self.split("\n").max {|l1, l2| l1.chomp.length <=> l2.chomp.length}.length
|
85
|
+
width = [width, min_width].max
|
86
|
+
|
87
|
+
box = ''
|
88
|
+
# top margin
|
89
|
+
box << "\n" * top
|
90
|
+
# top border, left margin
|
91
|
+
box << ' ' * left << upleft.dup << hor.dup * width << upright.dup << "\n"
|
92
|
+
# top padding, left margin and so on ...
|
93
|
+
box << ' ' * left << vert.dup << ' ' * width << vert.dup << "\n"
|
94
|
+
# lines
|
95
|
+
self.split("\n").each do |line|
|
96
|
+
if(line && !line.empty?)
|
97
|
+
nl = ' ' * left << vert.dup << "%-#{width}s" %line
|
98
|
+
while(nl.length < width )
|
99
|
+
nl << ' '
|
100
|
+
end
|
101
|
+
nl << vert.dup << "\n"
|
102
|
+
else
|
103
|
+
nl = ' ' * left << vert.dup << ' ' * width << vert.dup << "\n"
|
104
|
+
end
|
105
|
+
box << nl
|
106
|
+
end
|
107
|
+
# bottom padding
|
108
|
+
box << ' ' * left << vert.dup << ' ' * width << vert.dup << "\n"
|
109
|
+
# bottom border
|
110
|
+
box << ' ' * left << downleft.dup << hor.dup * width << downright.dup
|
111
|
+
return box
|
112
|
+
end
|
113
|
+
|
114
|
+
def box!(opt = {})
|
115
|
+
self.replace(String.new(box(opt)))
|
116
|
+
end
|
117
|
+
|
118
|
+
# A wrap-function which works here, but may fail everywhere else.
|
119
|
+
def wrap(width, delimiter = "\n")
|
120
|
+
# YEAH. Ruby is crap because its regular expressions do not work as they
|
121
|
+
# should with special characters. And your coffee mug has a speech
|
122
|
+
# impediment. Face it!
|
123
|
+
words = self.scan(/\p{P}*[\wöÖüÜäÄßéèàôûùîçÇœæŒÆ]+\p{P}*/)
|
124
|
+
|
125
|
+
lines = []
|
126
|
+
lines << ''
|
127
|
+
li = 0
|
128
|
+
words.each do |w|
|
129
|
+
w.strip!
|
130
|
+
if( w.length + lines[li].length + 1 > width || w != words.first && w.match(delimiter) )
|
131
|
+
lines[li].squeeze!(' ')
|
132
|
+
lines << ''
|
133
|
+
li += 1
|
134
|
+
else
|
135
|
+
end
|
136
|
+
lines[li] << w
|
137
|
+
lines[li] << ' ' if w != words.last
|
138
|
+
end
|
139
|
+
self.replace(lines.join("\n"))
|
140
|
+
end
|
141
|
+
|
142
|
+
end
|
143
|
+
|
144
|
+
#--------------- TEST ---------------
|
145
|
+
if __FILE__ == $0
|
146
|
+
s = "Ein König mit Krone ist besser als ohne,\n\n(du Nase)!!".wrap(12)
|
147
|
+
puts s
|
148
|
+
|
149
|
+
s = "1) Ein Koenig mit Krone ist besser als ohne,\n\n(du Nase)!!\n2) We are not in Kansas anymore.\n3) Toto? Ich glaub, der Köter hieß Toto... ".wrap(12, /^\d/)
|
150
|
+
puts s
|
151
|
+
|
152
|
+
|
153
|
+
# puts "Ein Koenig mit Krone ist besser als ohne,\n\ndu Nase!!".box(:padding=>2)
|
154
|
+
|
155
|
+
s = "1) Didudel Doedel didödeledel dödeldödel dödeldödel du dödel. DOEDEL !\n"
|
156
|
+
s << "2) Man gab uns mancherlei auf Erden.\nZum Denken gab man uns die Stirn."
|
157
|
+
s << "2a) Man gab uns Herz- und Leibbeschwerden.\nDoch auch den Himmel und den Zwirn."
|
158
|
+
s << "3) Himmel, Ding und Zwirn."
|
159
|
+
s.wrap(12, /\d\)/)
|
160
|
+
puts s.box(:min_width=>20, :left => 20)
|
161
|
+
end
|