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.
@@ -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
+