perception 0.1.5
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.
- 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
|
+
|