perception 0.1.5

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