perception 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- data/0 start all Tests.bat +20 -0
- data/History.txt +4 -0
- data/License.txt +21 -0
- data/Manifest.txt +29 -0
- data/PostInstall.txt +6 -0
- data/README.txt +55 -0
- data/Rakefile.rb +127 -0
- data/demo/demo_pp.rb +163 -0
- data/demo/demo_zz.rb +332 -0
- data/init.rb +2 -0
- data/lib/perception/const.rb +78 -0
- data/lib/perception/date_and_time.rb +78 -0
- data/lib/perception/logging.rb +123 -0
- data/lib/perception/numeric.rb +194 -0
- data/lib/perception/perception_main.rb +317 -0
- data/lib/perception/perception_private.rb +231 -0
- data/lib/perception/ppp.rb +377 -0
- data/lib/perception/string_spread.rb +155 -0
- data/lib/perception/test.rb +114 -0
- data/lib/perception.rb +36 -0
- data/test/_start_all.rb +10 -0
- data/test/test_date_and_time.rb +54 -0
- data/test/test_numeric.rb +104 -0
- data/test/test_ppp.rb +297 -0
- data/website/index.html +11 -0
- data/website/index.txt +83 -0
- data/website/javascripts/rounded_corners_lite.inc.js +285 -0
- data/website/stylesheets/screen.css +138 -0
- data/website/template.html.erb +48 -0
- metadata +119 -0
@@ -0,0 +1,194 @@
|
|
1
|
+
|
2
|
+
require File.join(File.dirname(__FILE__), '..', 'perception' ) if $0 == __FILE__
|
3
|
+
|
4
|
+
module Perception #:nodoc
|
5
|
+
|
6
|
+
module NumericI
|
7
|
+
|
8
|
+
|
9
|
+
# Formatiert eine Zahl so, dass sie leicht menschenlesbar wird:
|
10
|
+
# - Quasi-rechtsbündig (mit dem Komma als Bezugspunkt, abhängig von der Klassenzugehörigkeit der Zahl)
|
11
|
+
# - vorangestellte Währungszeichen oder angefügte Einheiten, ohne die Bündigkeit zu zerstören
|
12
|
+
# - intelligente Ausweichstrategie, wenn der vorgegebene Platz nicht ausreicht
|
13
|
+
# - nur die signifikanten Stellen werden angegeben, damit die Größenordnung leicht erfasst werden kann
|
14
|
+
# - Tausendertrennzeichen wenn nötig
|
15
|
+
#
|
16
|
+
# Optionen sind:
|
17
|
+
# * :precision Wieviel signifikante Stellen sollen ausgegeben werden? Default: 3
|
18
|
+
# * :space_l Wieviel Platz wird vor dem Komma eingeplant?
|
19
|
+
# * :space_r wie :space, bezieht sich aber nur auf den Nachkommateil. Wird abhängig davon vorbelegt, ob self Integer oder Float ist.
|
20
|
+
# * :separator Kommazeichen
|
21
|
+
# * :delimiter Tausendertrennzeichen
|
22
|
+
# * :pre wird direkt vor der Zahl ausgegeben (z.B. €)
|
23
|
+
# * :past wird direkt nach der Zahl ausgegeben (z.B. %)
|
24
|
+
#
|
25
|
+
# Für eine schlichte linksbündige Ausgabe reicht die Methode #significant!
|
26
|
+
# vgl. http://de.wikipedia.org/wiki/Wikipedia:Schreibweise_von_Zahlen
|
27
|
+
#
|
28
|
+
def inspect_see(options={})
|
29
|
+
precision = options[:precision] || 3
|
30
|
+
pre = options[:pre] || ''
|
31
|
+
past = options[:past] || ''
|
32
|
+
space_l = options[:space_l] || 9 + pre.size
|
33
|
+
space_r = options[:space_r] || (self.kind_of?(Integer) ? (0+past.size) : (5+past.size)) # Integer oder Float?
|
34
|
+
separator = options[:separator] || ','
|
35
|
+
delimiter = options[:delimiter] || ' '
|
36
|
+
|
37
|
+
|
38
|
+
# auf die signifikanten Stellen reduzieren und aufteilen
|
39
|
+
zusammengestrichen = self.significant(precision)
|
40
|
+
zahlenteile = zusammengestrichen.to_s.split('.')
|
41
|
+
|
42
|
+
# Tausendertrennzeichen und Pre
|
43
|
+
zahlenteile[0].gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1#{delimiter}") if self.abs >= 10000
|
44
|
+
zahlenteile[0] = pre + zahlenteile[0] unless pre.empty?
|
45
|
+
|
46
|
+
# übereinanderstehende Formatierung
|
47
|
+
result = zahlenteile[0].rjust(space_l)
|
48
|
+
if zahlenteile[1]
|
49
|
+
|
50
|
+
result += (separator + zahlenteile[1] + past).ljust( space_r )
|
51
|
+
#result += separator + (zahlenteile[1]).ljust( space_r-1 )
|
52
|
+
else
|
53
|
+
result += past + (' ' * (space_r-past.size))
|
54
|
+
end
|
55
|
+
|
56
|
+
# zu großen Platzbedarf korrigieren
|
57
|
+
if result.size >= space_l+space_r+1
|
58
|
+
if (space_l - zahlenteile[0].size) < ((space_r-1) - zahlenteile[1].size)
|
59
|
+
return result.strip.ljust(space_l+space_r)#.gsub(/ /,'_') # linksbündig ausgeben
|
60
|
+
else
|
61
|
+
return result.strip.rjust(space_l+space_r)#.gsub(/ /,'_') # rechtsbündig ausgeben
|
62
|
+
end
|
63
|
+
|
64
|
+
# Platz reicht aus
|
65
|
+
else
|
66
|
+
return result#.gsub(/ /,'_')
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
# Streicht überflüssige Stellen weg.
|
73
|
+
# Wandelt in Integer um, wenn das ohne Informationsverlust möglich ist.
|
74
|
+
# Überflüssig sind Stellen, die
|
75
|
+
# * jenseits der Messprecision liegen oder
|
76
|
+
# * nicht von Menschen wahrgenommen werden (stattdessen stören sie die Rezeption)
|
77
|
+
#
|
78
|
+
def significant( precision = 3)
|
79
|
+
|
80
|
+
# sprintf mit gemischter Schreibweise
|
81
|
+
fucking_c_lib_result = sprintf("%.#{precision}g", self)
|
82
|
+
fucking_c_lib_result =~ /^(.*)e/
|
83
|
+
meine_zahl = $+ || fucking_c_lib_result
|
84
|
+
exponent = $'
|
85
|
+
# pp meine_zahl
|
86
|
+
# pp exponent
|
87
|
+
|
88
|
+
# ohne Exponent
|
89
|
+
if exponent.nil?
|
90
|
+
result = meine_zahl.to_f
|
91
|
+
if result.abs >= (10**(precision-1)) || result == result.to_i
|
92
|
+
return result.to_i
|
93
|
+
else
|
94
|
+
return result
|
95
|
+
end
|
96
|
+
|
97
|
+
# mit Exponent
|
98
|
+
else
|
99
|
+
|
100
|
+
result = meine_zahl.to_f * 10**(exponent.to_i)
|
101
|
+
if exponent[0..0] == '+'
|
102
|
+
return result.to_i
|
103
|
+
|
104
|
+
else
|
105
|
+
return result
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
end # Expontent?
|
110
|
+
end # def significant
|
111
|
+
|
112
|
+
|
113
|
+
end # module NumericI
|
114
|
+
end # module Perception
|
115
|
+
|
116
|
+
|
117
|
+
class Numeric #:nodoc:
|
118
|
+
include Perception::NumericI
|
119
|
+
end
|
120
|
+
|
121
|
+
class NilClass #:nodoc:
|
122
|
+
def size(*a); 0; end
|
123
|
+
end
|
124
|
+
|
125
|
+
|
126
|
+
|
127
|
+
|
128
|
+
|
129
|
+
|
130
|
+
|
131
|
+
# -----------------------------------------------------------------------------------------
|
132
|
+
# Ausprobieren, Tests
|
133
|
+
#
|
134
|
+
|
135
|
+
|
136
|
+
if $0 == __FILE__ then
|
137
|
+
|
138
|
+
# Hier einstellen, was laufen soll
|
139
|
+
$run = :inspect_see
|
140
|
+
$run = :significant
|
141
|
+
#$run = :tests
|
142
|
+
|
143
|
+
case $run
|
144
|
+
|
145
|
+
|
146
|
+
when :significant #------------------------------------------------------------------------
|
147
|
+
|
148
|
+
test = [12567.89, 1256.789, 123.56789, 100.01, 100.0, 99.9, 12.0, 12, 12.56789, 1.256789, 1.5, 0, 0.1256789,0.01256789,0.001256789,0.0001256789, ]
|
149
|
+
test.each do |t|
|
150
|
+
see_print t.to_s.rjust(15)
|
151
|
+
see_print t.significant.to_s.rjust(15)
|
152
|
+
see_print (t * -1).significant.to_s.rjust(15)
|
153
|
+
see_print "\n"
|
154
|
+
end
|
155
|
+
|
156
|
+
|
157
|
+
when :inspect_see #------------------------------------------------------------------------
|
158
|
+
|
159
|
+
test = [7213541, 553337, 12567.89, 1256.789, 123.56789, 100.01, 100.0, 99.9, 12.0, 12, 12.56789, 1.256789, 1.5, 0, 0.1256789,0.01256789,0.001256789,0.0001256789, ]
|
160
|
+
test.each do |t|
|
161
|
+
t = t*-1
|
162
|
+
see_print t.to_s.rjust(15) + ' ########' + t.to_f.inspect_see + "########\n"
|
163
|
+
t = t*-1
|
164
|
+
see_print t.to_s.rjust(15) + ' ########' + t.to_f.inspect_see + "########\n"
|
165
|
+
end
|
166
|
+
|
167
|
+
when :tests #------------------------------------------------------------------------------
|
168
|
+
|
169
|
+
require File.join(File.dirname(__FILE__), '..', '..', 'test', 'test_numeric' )
|
170
|
+
|
171
|
+
|
172
|
+
else #--------------------------------------------------------------------------------------
|
173
|
+
|
174
|
+
see '$run einstellen!'
|
175
|
+
|
176
|
+
|
177
|
+
end # case
|
178
|
+
end # if
|
179
|
+
|
180
|
+
|
181
|
+
|
182
|
+
|
183
|
+
|
184
|
+
|
185
|
+
|
186
|
+
|
187
|
+
|
188
|
+
|
189
|
+
|
190
|
+
|
191
|
+
|
192
|
+
|
193
|
+
|
194
|
+
|
@@ -0,0 +1,317 @@
|
|
1
|
+
|
2
|
+
require File.join(File.dirname(__FILE__), '..', 'perception' ) if $0 == __FILE__
|
3
|
+
|
4
|
+
require 'kyanite/array/array'
|
5
|
+
require 'kyanite/enumerable/structure' # Methode contentclass
|
6
|
+
|
7
|
+
# Get auto-intended output on your console without any configuration,
|
8
|
+
# temporary prints, printing two items in one line without destroying the structure.
|
9
|
+
# Optionally slows down printing to readable speed, depending on the complexity of the output.
|
10
|
+
|
11
|
+
|
12
|
+
|
13
|
+
|
14
|
+
|
15
|
+
# Perception: Human perceptible printouts
|
16
|
+
# ========================================
|
17
|
+
#
|
18
|
+
# Welcome to Perception. It's a intuitive toolkit for simple everyday debugging.
|
19
|
+
# Perception offers a powerfull replacement for print, puts and pp.
|
20
|
+
# You get auto-intended and structured output on your console without any configuration.
|
21
|
+
# Perception also offers temporary printouts (overwritten by the next print),
|
22
|
+
# printing two informations in one line without destroying the structure and
|
23
|
+
# optionally slows down printing to readable speed, depending on the complexity of the output.
|
24
|
+
#
|
25
|
+
module Perception #:nodoc
|
26
|
+
|
27
|
+
# Eine SeeSession-Instanz entspricht einer Session mit der Konsole.
|
28
|
+
class SeeSession
|
29
|
+
|
30
|
+
# Turns automatic indention ON.
|
31
|
+
def indent!
|
32
|
+
@indent = true
|
33
|
+
@level = SEE_LEVEL_START
|
34
|
+
@call_stack_last = 0
|
35
|
+
@call_stack_now = 0
|
36
|
+
nil
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
# Turns automatic indention OFF.
|
41
|
+
def left!
|
42
|
+
@indent = false
|
43
|
+
@level = SEE_LEVEL_START
|
44
|
+
@call_stack_last = 0
|
45
|
+
@call_stack_now = 0
|
46
|
+
nil
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
# Undos the last print.
|
51
|
+
# Note: Indention will get lost.
|
52
|
+
def clear!
|
53
|
+
return if @cursor_now <= SEE_TAB_WIDTH * @level
|
54
|
+
return if @string_last.empty?
|
55
|
+
return unless @out.include?(:console)
|
56
|
+
self.wait!('') if @speed
|
57
|
+
printout( ("\b" * @string_last.size) + (" " * @string_last.size) + ("\b" * @string_last.size), @string_last.size )
|
58
|
+
@string_last = ''
|
59
|
+
@method_last = nil
|
60
|
+
@time_last = Time.now
|
61
|
+
@delayed_newlines = 0
|
62
|
+
@delayed_clear = false
|
63
|
+
nil
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
# Marks the last print as temporary.
|
68
|
+
# The following print will overwrite it.
|
69
|
+
# Note: Indention will get lost.
|
70
|
+
def temp!
|
71
|
+
@delayed_clear = true
|
72
|
+
nil
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
# Slows down output to readable speed.
|
77
|
+
# The speed depends on the length and the complexity of the printing.
|
78
|
+
# You can adjust the speed with the parameter:
|
79
|
+
# * slow! 1 --> same as slow!
|
80
|
+
# * slow! 2 --> slow, but double speed
|
81
|
+
# * slow! 0.5 --> even slower
|
82
|
+
# * slow! nil --> full speed (same as fast!)
|
83
|
+
def slow!(speed=1)
|
84
|
+
@speed = speed
|
85
|
+
nil
|
86
|
+
end
|
87
|
+
|
88
|
+
|
89
|
+
# Adjusts printing speed to full speed.
|
90
|
+
# This is used after slow!
|
91
|
+
def fast!
|
92
|
+
@speed = nil
|
93
|
+
nil
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
# Returns the time in seconds since the last #see-printout.
|
98
|
+
def bench
|
99
|
+
return 0 unless @time_last
|
100
|
+
return (Time.now - @time_last)
|
101
|
+
end
|
102
|
+
|
103
|
+
|
104
|
+
# Shows two informations in one line. See the demo.
|
105
|
+
#
|
106
|
+
# Via seee.flash! können zwei Informationen abwechselnd in der gleichen Zeile angezeigt werden.
|
107
|
+
# Das ist nützlich, wenn man bestimmte Werte anzeigen will ohne das Gesamtlayout zu zerstören.
|
108
|
+
#
|
109
|
+
# Ohne Angabe eines Zweittextes wird der Ersttext einfach zum Blinken gebracht. Nachträglich, also wenn er schon ausgegeben ist.
|
110
|
+
# Das ist sehr nützlich, wenn man bestimme Werte verfolgen will.
|
111
|
+
#
|
112
|
+
def flash!(alternativtext=' ', how_many=6)
|
113
|
+
string_bak = @string_last.dup
|
114
|
+
method_bak = @method_last
|
115
|
+
method_bak = :puts if method_bak == :pp
|
116
|
+
speed_bak = @speed
|
117
|
+
if speed_bak
|
118
|
+
seee.slow!(speed_bak * 0.8)
|
119
|
+
else
|
120
|
+
seee.slow!
|
121
|
+
end
|
122
|
+
how_many.times do
|
123
|
+
seee.clear!
|
124
|
+
seee.temp!
|
125
|
+
process_print( alternativtext, {:method => :print } )
|
126
|
+
seee.clear!
|
127
|
+
process_print( string_bak, {:method => method_bak } )
|
128
|
+
end
|
129
|
+
@speed = speed_bak
|
130
|
+
return alternativtext
|
131
|
+
end # def
|
132
|
+
|
133
|
+
|
134
|
+
end # class
|
135
|
+
end # module
|
136
|
+
|
137
|
+
|
138
|
+
|
139
|
+
|
140
|
+
|
141
|
+
class Object
|
142
|
+
|
143
|
+
# ------------------------------------------------------------------------------
|
144
|
+
# Wrapper for SeeSession
|
145
|
+
#
|
146
|
+
|
147
|
+
# Returns the SeeSession-Object. Offers the following methods:
|
148
|
+
# * seee.indent!
|
149
|
+
# * seee.left!
|
150
|
+
# * seee.clear!
|
151
|
+
# * seee.slow!
|
152
|
+
# * seee.fast!
|
153
|
+
# * seee.temp!
|
154
|
+
# * seee.flash!
|
155
|
+
# * seee.bench
|
156
|
+
#
|
157
|
+
def seee
|
158
|
+
return Perception::SeeSession.instance
|
159
|
+
end
|
160
|
+
|
161
|
+
|
162
|
+
# This is the main method. It prints out objects. See the demo.
|
163
|
+
def see(input=:kein_input, *rest)
|
164
|
+
|
165
|
+
if input == :kein_input
|
166
|
+
seee.process_print( "\n", :method => :puts )
|
167
|
+
return ''
|
168
|
+
end
|
169
|
+
|
170
|
+
return seee.process_print( ( [input] + rest), :method => :multi ) unless rest.empty?
|
171
|
+
return see_puts(input) if input.class == String
|
172
|
+
return see_pp(input) if input.class == Hash
|
173
|
+
return see_puts(input) unless (input.respond_to?(:compact) || input.instance_variables ) # Ordinäre Objekte macht puts
|
174
|
+
return see_pp(input) # Den Rest macht pp
|
175
|
+
|
176
|
+
end # def
|
177
|
+
|
178
|
+
|
179
|
+
def see_each(input)
|
180
|
+
if self.contentclass == Array
|
181
|
+
see_puts '['
|
182
|
+
input.each {|elt| see elt}
|
183
|
+
see_puts']'
|
184
|
+
end
|
185
|
+
input.each {|elt| see elt}
|
186
|
+
end
|
187
|
+
|
188
|
+
|
189
|
+
|
190
|
+
# Like see, but temporary print.
|
191
|
+
# The following print will overwrite it.
|
192
|
+
# Note: Indention will get lost.
|
193
|
+
def see_temp(input=:kein_input)
|
194
|
+
if input == :kein_input
|
195
|
+
seee.delayed_newlines += 1
|
196
|
+
return ''
|
197
|
+
end
|
198
|
+
see_print input
|
199
|
+
seee.temp!
|
200
|
+
end
|
201
|
+
|
202
|
+
|
203
|
+
# Shows two informations in one line. See the demo.
|
204
|
+
def see_flash(input=:kein_input, alternativtext=' ', times=6)
|
205
|
+
if input == :kein_input
|
206
|
+
seee.delayed_newlines += 1
|
207
|
+
return ''
|
208
|
+
end
|
209
|
+
see_puts input
|
210
|
+
seee.flash!(alternativtext,times) if input != :kein_input
|
211
|
+
end
|
212
|
+
|
213
|
+
|
214
|
+
# Like see, but forces behavior like the originally puts method.
|
215
|
+
# So you get a newline after every print.
|
216
|
+
# Note: All newlines are delayed. This offers you to undo the print.
|
217
|
+
def see_puts(input=:kein_input)
|
218
|
+
if input == :kein_input
|
219
|
+
seee.delayed_newlines += 1
|
220
|
+
return ''
|
221
|
+
end
|
222
|
+
seee.process_print( input, :method => :puts )
|
223
|
+
end
|
224
|
+
|
225
|
+
|
226
|
+
# Like see, but forces behavior like the originally print method.
|
227
|
+
# So you have fully control over your newlines.
|
228
|
+
# Note: If you use "\n", #see will indent it. See SEE_LEVEL_START.
|
229
|
+
def see_print(input=$_)
|
230
|
+
return seee.process_print( input, :method => :print )
|
231
|
+
end
|
232
|
+
|
233
|
+
|
234
|
+
# Like see, but forces behavior like the originally pp method.
|
235
|
+
def see_pp(input=:kein_input)
|
236
|
+
if input == :kein_input
|
237
|
+
seee.delayed_newlines += 1
|
238
|
+
return ''
|
239
|
+
end
|
240
|
+
return seee.process_print( input, :method => :pp )
|
241
|
+
end
|
242
|
+
|
243
|
+
|
244
|
+
|
245
|
+
|
246
|
+
|
247
|
+
|
248
|
+
# Waits for you / the user to press a key.
|
249
|
+
# Returns the key.
|
250
|
+
# Display it with #{wait_for_key.chr.inspect}.
|
251
|
+
# Note: Indention will get lost.
|
252
|
+
def wait_for_key(message='Press any key')
|
253
|
+
seee.clear_indent!
|
254
|
+
#seee.level -= 1 # Zählt nicht als Level
|
255
|
+
see_temp message
|
256
|
+
unless defined?(HighLine)
|
257
|
+
require 'highline/import'
|
258
|
+
HighLine.send(:public, :get_character)
|
259
|
+
end
|
260
|
+
input = HighLine.new
|
261
|
+
return input.get_character
|
262
|
+
end
|
263
|
+
|
264
|
+
|
265
|
+
# Like inspect, but uses the PrettyPrint library.
|
266
|
+
# Returns the output of pp as String.
|
267
|
+
def inspect_pp( wrap = 200 )
|
268
|
+
result = ''
|
269
|
+
return PPP::pp(self, result, wrap)
|
270
|
+
end
|
271
|
+
|
272
|
+
|
273
|
+
# inspect_pp with beautification
|
274
|
+
def inspect_see( wrap = 200 )
|
275
|
+
result = ''
|
276
|
+
result = PPP::pp(self, result, wrap) # normal prettyprint
|
277
|
+
result = PPP.beautify(result)
|
278
|
+
return result
|
279
|
+
end
|
280
|
+
|
281
|
+
|
282
|
+
|
283
|
+
|
284
|
+
|
285
|
+
#
|
286
|
+
# def ljust(width)
|
287
|
+
# try_inspect = self.inspect
|
288
|
+
# end
|
289
|
+
|
290
|
+
|
291
|
+
end # class
|
292
|
+
|
293
|
+
|
294
|
+
|
295
|
+
|
296
|
+
|
297
|
+
|
298
|
+
|
299
|
+
|
300
|
+
|
301
|
+
|
302
|
+
|
303
|
+
if $0 == __FILE__ then
|
304
|
+
require File.join(File.dirname(__FILE__), '..', '..', 'demo', 'demo_pp' )
|
305
|
+
Perception::DemoSee.see_all_demos
|
306
|
+
|
307
|
+
end # if
|
308
|
+
|
309
|
+
|
310
|
+
|
311
|
+
|
312
|
+
|
313
|
+
|
314
|
+
|
315
|
+
|
316
|
+
|
317
|
+
|