pry 0.7.7.2 → 0.8.0pre1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,718 +0,0 @@
1
- require "optparse"
2
- require "method_source"
3
- require "pry/command_base"
4
- require "pry/pry_instance"
5
-
6
- begin
7
-
8
- # YARD crashes on rbx, so do not require it
9
- if !Object.const_defined?(:RUBY_ENGINE) || RUBY_ENGINE !~ /rbx/
10
- require "pry-doc"
11
- end
12
- rescue LoadError
13
- end
14
-
15
- class Pry
16
-
17
- # Default commands used by Pry.
18
- class Commands < CommandBase
19
-
20
- # We make this a lambda to avoid documenting it
21
- meth_name_from_binding = lambda do |b|
22
- meth_name = b.eval('__method__')
23
-
24
- # :__script__ for rubinius
25
- if [:__script__, nil, :__binding__, :__binding_impl__].include?(meth_name)
26
- nil
27
- else
28
- meth_name
29
- end
30
- end
31
-
32
- check_for_dynamically_defined_method = lambda do |meth|
33
- file, _ = meth.source_location
34
- if file =~ /(\(.*\))|<.*>/
35
- raise "Cannot retrieve source for dynamically defined method."
36
- end
37
- end
38
-
39
- remnnove_first_word = lambda do |text|
40
- text.split.drop(1).join(' ')
41
- end
42
-
43
- get_method_object = lambda do |meth_name, target, options|
44
- if !meth_name
45
- return nil
46
- end
47
-
48
- if options[:M]
49
- target.eval("instance_method(:#{meth_name})")
50
- elsif options[:m]
51
- target.eval("method(:#{meth_name})")
52
- else
53
- begin
54
- target.eval("instance_method(:#{meth_name})")
55
- rescue
56
- begin
57
- target.eval("method(:#{meth_name})")
58
- rescue
59
- return nil
60
- end
61
- end
62
- end
63
- end
64
-
65
- make_header = lambda do |meth, code_type|
66
- file, line = meth.source_location
67
- header = case code_type
68
- when :ruby
69
- "--\nFrom #{file} @ line #{line}:\n--"
70
- else
71
- "--\nFrom Ruby Core (C Method):\n--"
72
- end
73
- end
74
-
75
- is_a_c_method = lambda do |meth|
76
- meth.source_location.nil?
77
- end
78
-
79
- should_use_pry_doc = lambda do |meth|
80
- Pry.has_pry_doc && is_a_c_method.call(meth)
81
- end
82
-
83
- code_type_for = lambda do |meth|
84
- # only C methods
85
- if should_use_pry_doc.call(meth)
86
- info = Pry::MethodInfo.info_for(meth)
87
- if info && info.source
88
- code_type = :c
89
- else
90
- output.puts "Cannot find C method: #{meth.name}"
91
- code_type = nil
92
- end
93
- else
94
- if is_a_c_method.call(meth)
95
- output.puts "Cannot locate this method: #{meth.name}. Try `gem install pry-doc` to get access to Ruby Core documentation."
96
- code_type = nil
97
- else
98
- check_for_dynamically_defined_method.call(meth)
99
- code_type = :ruby
100
- end
101
- end
102
- code_type
103
- end
104
-
105
- command "!", "Clear the input buffer. Useful if the parsing process goes wrong and you get stuck in the read loop." do
106
- output.puts "Input buffer cleared!"
107
- opts[:eval_string].clear
108
- end
109
-
110
- command "!pry", "Start a Pry session on current self; this even works mid-expression." do
111
- Pry.start(target)
112
- end
113
-
114
- command "exit-program", "End the current program. Aliases: quit-program, !!!" do
115
- exit
116
- end
117
-
118
- alias_command "quit-program", "exit-program", ""
119
- alias_command "!!!", "exit-program", ""
120
-
121
- command "toggle-color", "Toggle syntax highlighting." do
122
- Pry.color = !Pry.color
123
- output.puts "Syntax highlighting #{Pry.color ? "on" : "off"}"
124
- end
125
-
126
- command "simple-prompt", "Toggle the simple prompt." do
127
- case Pry.active_instance.prompt
128
- when Pry::SIMPLE_PROMPT
129
- Pry.active_instance.prompt = Pry::DEFAULT_PROMPT
130
- else
131
- Pry.active_instance.prompt = Pry::SIMPLE_PROMPT
132
- end
133
- end
134
-
135
- command "nesting", "Show nesting information." do
136
- nesting = opts[:nesting]
137
-
138
- output.puts "Nesting status:"
139
- output.puts "--"
140
- nesting.each do |level, obj|
141
- if level == 0
142
- output.puts "#{level}. #{Pry.view_clip(obj)} (Pry top level)"
143
- else
144
- output.puts "#{level}. #{Pry.view_clip(obj)}"
145
- end
146
- end
147
- end
148
-
149
- command "status", "Show status information." do
150
- nesting = opts[:nesting]
151
-
152
- output.puts "Status:"
153
- output.puts "--"
154
- output.puts "Receiver: #{Pry.view_clip(target.eval('self'))}"
155
- output.puts "Nesting level: #{nesting.level}"
156
- output.puts "Pry version: #{Pry::VERSION}"
157
- output.puts "Ruby version: #{RUBY_VERSION}"
158
-
159
- mn = meth_name_from_binding.call(target)
160
- output.puts "Current method: #{mn ? mn : "N/A"}"
161
- output.puts "Pry instance: #{Pry.active_instance}"
162
- output.puts "Last result: #{Pry.view(Pry.last_result)}"
163
- end
164
-
165
- command "whereami", "Show the code context for the session. Shows AROUND lines around the invocation line. AROUND defaults to 5 lines. " do |num|
166
- file = target.eval('__FILE__')
167
- line_num = target.eval('__LINE__')
168
- klass = target.eval('self.class')
169
-
170
- if num
171
- i_num = num.to_i
172
- else
173
- i_num = 5
174
- end
175
-
176
- meth_name = meth_name_from_binding.call(target)
177
- meth_name = "N/A" if !meth_name
178
-
179
- if file =~ /(\(.*\))|<.*>/ || file == ""
180
- output.puts "Cannot find local context. Did you use `binding.pry` ?"
181
- next
182
- end
183
-
184
- output.puts "--\nFrom #{file} @ line #{line_num} in #{klass}##{meth_name}:\n--"
185
-
186
- # This method inspired by http://rubygems.org/gems/ir_b
187
- File.open(file).each_with_index do |line, index|
188
- line_n = index + 1
189
- next unless line_n > (line_num - i_num - 1)
190
- break if line_n > (line_num + i_num)
191
- if line_n == line_num
192
- code =" =>#{line_n.to_s.rjust(3)}: #{line.chomp}"
193
- if Pry.color
194
- code = CodeRay.scan(code, :ruby).term
195
- end
196
- output.puts code
197
- code
198
- else
199
- code = "#{line_n.to_s.rjust(6)}: #{line.chomp}"
200
- if Pry.color
201
- code = CodeRay.scan(code, :ruby).term
202
- end
203
- output.puts code
204
- code
205
- end
206
- end
207
- end
208
-
209
- command "version", "Show Pry version." do
210
- output.puts "Pry version: #{Pry::VERSION} on Ruby #{RUBY_VERSION}."
211
- end
212
-
213
- command "exit-all", "End all nested Pry sessions. Accepts optional return value. Aliases: !@" do
214
- str = remove_first_word.call(opts[:val])
215
- throw(:breakout, [0, target.eval(str)])
216
- end
217
-
218
- alias_command "!@", "exit-all", ""
219
-
220
- command "ls", "Show the list of vars in the current scope. Type `ls --help` for more info." do |*args|
221
- options = {}
222
-
223
- # Set target local to the default -- note that we can set a different target for
224
- # ls if we like: e.g ls my_var
225
- target = target()
226
-
227
- OptionParser.new do |opts|
228
- opts.banner = %{Usage: ls [OPTIONS] [VAR]\n\
229
- List information about VAR (the current context by default).
230
- Shows local and instance variables by default.
231
- --
232
- }
233
- opts.on("-g", "--globals", "Display global variables.") do
234
- options[:g] = true
235
- end
236
-
237
- opts.on("-c", "--constants", "Display constants.") do
238
- options[:c] = true
239
- end
240
-
241
- opts.on("-l", "--locals", "Display locals.") do
242
- options[:l] = true
243
- end
244
-
245
- opts.on("-i", "--ivars", "Display instance variables.") do
246
- options[:i] = true
247
- end
248
-
249
- opts.on("-k", "--class-vars", "Display class variables.") do
250
- options[:k] = true
251
- end
252
-
253
- opts.on("-m", "--methods", "Display methods (public methods by default).") do
254
- options[:m] = true
255
- end
256
-
257
- opts.on("-M", "--instance-methods", "Display instance methods (only relevant to classes and modules).") do
258
- options[:M] = true
259
- end
260
-
261
- opts.on("-P", "--public", "Display public methods (with -m).") do
262
- options[:P] = true
263
- end
264
-
265
- opts.on("-r", "--protected", "Display protected methods (with -m).") do
266
- options[:r] = true
267
- end
268
-
269
- opts.on("-p", "--private", "Display private methods (with -m).") do
270
- options[:p] = true
271
- end
272
-
273
- opts.on("-j", "--just-singletons", "Display just the singleton methods (with -m).") do
274
- options[:j] = true
275
- end
276
-
277
- opts.on("-s", "--super", "Include superclass entries (relevant to constant and methods options).") do
278
- options[:s] = true
279
- end
280
-
281
- opts.on("-a", "--all", "Display all types of entries.") do
282
- options[:a] = true
283
- end
284
-
285
- opts.on("-v", "--verbose", "Verbose ouput.") do
286
- options[:v] = true
287
- end
288
-
289
- opts.on_tail("-h", "--help", "Show this message.") do
290
- output.puts opts
291
- options[:h] = true
292
- end
293
- end.order(args) do |new_target|
294
- target = Pry.binding_for(target.eval("#{new_target}")) if !options[:h]
295
- end
296
-
297
- # exit if we've displayed help
298
- next if options[:h]
299
-
300
- # default is locals/ivars/class vars.
301
- # Only occurs when no options or when only option is verbose
302
- options.merge!({
303
- :l => true,
304
- :i => true,
305
- :k => true
306
- }) if options.empty? || (options.size == 1 && options[:v])
307
-
308
- # Display public methods by default if -m or -M switch is used.
309
- options[:P] = true if (options[:m] || options[:M]) && !(options[:p] || options[:r] || options[:j])
310
-
311
- info = {}
312
- target_self = target.eval('self')
313
-
314
- # ensure we have a real boolean and not a `nil` (important when
315
- # interpolating in the string)
316
- options[:s] = !!options[:s]
317
-
318
- # Numbers (e.g 0, 1, 2) are for ordering the hash values in Ruby 1.8
319
- i = -1
320
-
321
- # Start collecting the entries selected by the user
322
- info["local variables"] = [Array(target.eval("local_variables")).sort, i += 1] if options[:l] || options[:a]
323
- info["instance variables"] = [Array(target.eval("instance_variables")).sort, i += 1] if options[:i] || options[:a]
324
-
325
- info["class variables"] = [if target_self.is_a?(Module)
326
- Array(target.eval("class_variables")).sort
327
- else
328
- Array(target.eval("self.class.class_variables")).sort
329
- end, i += 1] if options[:k] || options[:a]
330
-
331
- info["global variables"] = [Array(target.eval("global_variables")).sort, i += 1] if options[:g] || options[:a]
332
-
333
- info["public methods"] = [Array(target.eval("public_methods(#{options[:s]})")).uniq.sort, i += 1] if (options[:m] && options[:P]) || options[:a]
334
-
335
- info["protected methods"] = [Array(target.eval("protected_methods(#{options[:s]})")).sort, i += 1] if (options[:m] && options[:r]) || options[:a]
336
-
337
- info["private methods"] = [Array(target.eval("private_methods(#{options[:s]})")).sort, i += 1] if (options[:m] && options[:p]) || options[:a]
338
-
339
- info["just singleton methods"] = [Array(target.eval("methods(#{options[:s]})")).sort, i += 1] if (options[:m] && options[:j]) || options[:a]
340
-
341
- info["public instance methods"] = [Array(target.eval("public_instance_methods(#{options[:s]})")).uniq.sort, i += 1] if target_self.is_a?(Module) && ((options[:M] && options[:P]) || options[:a])
342
-
343
- info["protected instance methods"] = [Array(target.eval("protected_instance_methods(#{options[:s]})")).uniq.sort, i += 1] if target_self.is_a?(Module) && ((options[:M] && options[:r]) || options[:a])
344
-
345
- info["private instance methods"] = [Array(target.eval("private_instance_methods(#{options[:s]})")).uniq.sort, i += 1] if target_self.is_a?(Module) && ((options[:M] && options[:p]) || options[:a])
346
-
347
- # dealing with 1.8/1.9 compatibility issues :/
348
- csuper = options[:s]
349
- if Module.method(:constants).arity == 0
350
- csuper = nil
351
- end
352
-
353
- info["constants"] = [Array(target_self.is_a?(Module) ? target.eval("constants(#{csuper})") :
354
- target.eval("self.class.constants(#{csuper})")).uniq.sort, i += 1] if options[:c] || options[:a]
355
-
356
- # verbose output?
357
- if options[:v]
358
-
359
- # verbose
360
- info.sort_by { |k, v| v.last }.each do |k, v|
361
- if !v.first.empty?
362
- output.puts "#{k}:\n--"
363
- if Pry.color
364
- output.puts CodeRay.scan(Pry.view(v.first), :ruby).term
365
- else
366
- output.puts Pry.view(v.first)
367
- end
368
- output.puts
369
- end
370
- end
371
-
372
- # plain
373
- else
374
- list = info.values.sort_by(&:last).map(&:first).inject(&:+)
375
- list.uniq! if list
376
- if Pry.color
377
- output.puts CodeRay.scan(Pry.view(list), :ruby).term
378
- else
379
- output.puts Pry.view(list)
380
- end
381
- list
382
- end
383
- end
384
-
385
- command "cat-file", "Show output of file FILE" do |file_name|
386
- if !file_name
387
- output.puts "Must provide a file name."
388
- next
389
- end
390
-
391
- contents = File.read(File.expand_path(file_name))
392
- output.puts contents
393
- contents
394
- end
395
-
396
- command "eval-file", "Eval a Ruby script. Type `eval-file --help` for more info." do |*args|
397
- options = {}
398
- target = target()
399
- file_name = nil
400
-
401
- OptionParser.new do |opts|
402
- opts.banner = %{Usage: eval-file [OPTIONS] FILE
403
- Eval a Ruby script at top-level or in the specified context. Defaults to top-level.
404
- e.g: eval-file -c self "hello.rb"
405
- --
406
- }
407
- opts.on("-c", "--context CONTEXT", "Eval the script in the specified context.") do |context|
408
- options[:c] = true
409
- target = Pry.binding_for(target.eval(context))
410
- end
411
-
412
- opts.on_tail("-h", "--help", "This message.") do
413
- output.puts opts
414
- options[:h] = true
415
- end
416
- end.order(args) do |v|
417
- file_name = v
418
- end
419
-
420
- next if options[:h]
421
-
422
- if !file_name
423
- output.puts "You need to specify a file name. Type `eval-file --help` for help"
424
- next
425
- end
426
-
427
- old_constants = Object.constants
428
- if options[:c]
429
- target_self = target.eval('self')
430
- target.eval(File.read(File.expand_path(file_name)))
431
- output.puts "--\nEval'd '#{file_name}' in the `#{target_self}` context."
432
- else
433
- TOPLEVEL_BINDING.eval(File.read(File.expand_path(file_name)))
434
- output.puts "--\nEval'd '#{file_name}' at top-level."
435
- end
436
- new_constants = Object.constants - old_constants
437
- output.puts "Brought in the following top-level constants: #{new_constants.inspect}" if !new_constants.empty?
438
- end
439
-
440
- command "cat", "Show output of VAR.inspect. Aliases: inspect" do |obj|
441
- if !obj
442
- output.puts "Must provide an object to inspect."
443
- next
444
- end
445
-
446
- output.puts Pry.view(target.eval("#{obj}"))
447
- end
448
-
449
- alias_command "inspect", "cat", ""
450
-
451
- command "cd", "Start a Pry session on VAR (use `cd ..` to go back and `cd /` to return to Pry top-level)", :keep_retval => true do |obj|
452
- if !obj
453
- output.puts "Must provide an object."
454
- next
455
- end
456
-
457
- throw(:breakout, opts[:nesting].level) if obj == ".."
458
-
459
- if obj == "/"
460
- throw(:breakout, 1) if opts[:nesting].level > 0
461
- next
462
- end
463
-
464
- target.eval("#{obj}").pry
465
- end
466
-
467
- process_comment_markup = lambda do |comment, code_type|
468
- comment.gsub(/<code>(?:\s*\n)?(.*?)\s*<\/code>/m) { Pry.color ? CodeRay.scan($1, code_type).term : $1 }.
469
- gsub(/<em>(?:\s*\n)?(.*?)\s*<\/em>/m) { Pry.color ? "\e[32m#{$1}\e[0m": $1 }.
470
- gsub(/<i>(?:\s*\n)?(.*?)\s*<\/i>/m) { Pry.color ? "\e[34m#{$1}\e[0m" : $1 }.
471
- gsub(/\B\+(\w*?)\+\B/) { Pry.color ? "\e[32m#{$1}\e[0m": $1 }.
472
- gsub(/((?:^[ \t]+.+(?:\n+|\Z))+)/) { Pry.color ? CodeRay.scan($1, code_type).term : $1 }.
473
- gsub(/`(?:\s*\n)?(.*?)\s*`/) { Pry.color ? CodeRay.scan($1, code_type).term : $1 }.
474
- gsub(/^@(param|return|example|option|yield|attr|attr_reader|attr_writer)/) { Pry.color ? "\e[33m#{$1}\e[0m": $1 }
475
- end
476
-
477
- # strip leading whitespace but preserve indentation
478
- strip_leading_whitespace = lambda do |text|
479
- leading_spaces = text.lines.first[/^(\s+)/, 1]
480
- text.gsub(/^#{leading_spaces}/, '')
481
- end
482
-
483
- strip_leading_hash_and_whitespace_from_ruby_comments = lambda do |comment|
484
- comment = comment.dup
485
- comment.gsub!(/^\s*#/, '')
486
- strip_leading_whitespace.call(comment)
487
- end
488
-
489
- command "show-doc", "Show the comments above METH. Type `show-doc --help` for more info." do |*args|
490
- options = {}
491
- target = target()
492
- meth_name = nil
493
-
494
- OptionParser.new do |opts|
495
- opts.banner = %{Usage: show-doc [OPTIONS] [METH]
496
- Show the comments above method METH. Tries instance methods first and then methods by default.
497
- e.g show-doc hello_method
498
- --
499
- }
500
- opts.on("-M", "--instance-methods", "Operate on instance methods.") do
501
- options[:M] = true
502
- end
503
-
504
- opts.on("-m", "--methods", "Operate on methods.") do
505
- options[:m] = true
506
- end
507
-
508
- opts.on("-c", "--context CONTEXT", "Select object context to run under.") do |context|
509
- target = Pry.binding_for(target.eval(context))
510
- end
511
-
512
- opts.on_tail("-h", "--help", "This message.") do
513
- output.puts opts
514
- options[:h] = true
515
- end
516
- end.order(args) do |v|
517
- meth_name = v
518
- end
519
-
520
- next if options[:h]
521
-
522
- if (meth = get_method_object.call(meth_name, target, options)).nil?
523
- output.puts "Invalid method name: #{meth_name}. Type `show-doc --help` for help"
524
- next
525
- end
526
-
527
- case code_type = code_type_for.call(meth)
528
- when nil
529
- next
530
- when :c
531
- doc = Pry::MethodInfo.info_for(meth).docstring
532
- when :ruby
533
- doc = meth.comment
534
- doc = strip_leading_hash_and_whitespace_from_ruby_comments.call(doc)
535
- end
536
-
537
- doc = process_comment_markup.call(doc, code_type)
538
- output.puts make_header.call(meth, code_type)
539
- output.puts doc
540
- doc
541
- end
542
-
543
- strip_comments_from_c_code = lambda do |code|
544
- code.sub /\A\s*\/\*.*?\*\/\s*/m, ''
545
- end
546
-
547
- command "show-method", "Show the source for METH. Type `show-method --help` for more info. Aliases: show-source" do |*args|
548
- options = {}
549
- target = target()
550
- meth_name = nil
551
-
552
- OptionParser.new do |opts|
553
- opts.banner = %{Usage: show-method [OPTIONS] [METH]
554
- Show the source for method METH. Tries instance methods first and then methods by default.
555
- e.g: show-method hello_method
556
- --
557
- }
558
- opts.on("-M", "--instance-methods", "Operate on instance methods.") do
559
- options[:M] = true
560
- end
561
-
562
- opts.on("-m", "--methods", "Operate on methods.") do
563
- options[:m] = true
564
- end
565
-
566
- opts.on("-c", "--context CONTEXT", "Select object context to run under.") do |context|
567
- target = Pry.binding_for(target.eval(context))
568
- end
569
-
570
- opts.on_tail("-h", "--help", "This message.") do
571
- output.puts opts
572
- options[:h] = true
573
- end
574
- end.order(args) do |v|
575
- meth_name = v
576
- end
577
-
578
- next if options[:h]
579
-
580
- meth_name = meth_name_from_binding.call(target) if !meth_name
581
-
582
- if (meth = get_method_object.call(meth_name, target, options)).nil?
583
- output.puts "Invalid method name: #{meth_name}. Type `show-method --help` for help"
584
- next
585
- end
586
-
587
- case code_type = code_type_for.call(meth)
588
- when nil
589
- next
590
- when :c
591
- code = Pry::MethodInfo.info_for(meth).source
592
- code = strip_comments_from_c_code.call(code)
593
- when :ruby
594
- code = strip_leading_whitespace.call(meth.source)
595
- end
596
-
597
- output.puts make_header.call(meth, code_type)
598
- if Pry.color
599
- code = CodeRay.scan(code, code_type).term
600
- end
601
-
602
- output.puts code
603
- code
604
- end
605
-
606
- alias_command "show-source", "show-method", ""
607
-
608
- command "show-command", "Show sourcecode for a Pry command, e.g: show-command cd" do |command_name|
609
- if !command_name
610
- output.puts "You must provide a command name."
611
- next
612
- end
613
-
614
- if commands[command_name]
615
- meth = commands[command_name][:action]
616
-
617
- code = strip_leading_whitespace.call(meth.source)
618
- file, line = meth.source_location
619
- check_for_dynamically_defined_method.call(meth)
620
-
621
- output.puts "--\nFrom #{file} @ line #{line}:\n--"
622
-
623
- if Pry.color
624
- code = CodeRay.scan(code, :ruby).term
625
- end
626
-
627
- output.puts code
628
- code
629
- else
630
- output.puts "No such command: #{command_name}."
631
- end
632
- end
633
-
634
- command "jump-to", "Jump to a Pry session further up the stack, exiting all sessions below." do |break_level|
635
- break_level = break_level.to_i
636
- nesting = opts[:nesting]
637
-
638
- case break_level
639
- when nesting.level
640
- output.puts "Already at nesting level #{nesting.level}"
641
- when (0...nesting.level)
642
- throw(:breakout, break_level + 1)
643
- else
644
- max_nest_level = nesting.level - 1
645
- output.puts "Invalid nest level. Must be between 0 and #{max_nest_level}. Got #{break_level}."
646
- end
647
- end
648
-
649
- command "exit", "End the current Pry session. Accepts optional return value. Aliases: quit, back" do
650
- str = remove_first_word.call(opts[:val])
651
- throw(:breakout, [opts[:nesting].level, target.eval(str)])
652
- end
653
-
654
- alias_command "quit", "exit", ""
655
- alias_command "back", "exit", ""
656
-
657
- command "game", "" do |highest|
658
- highest = highest ? highest.to_i : 100
659
- num = rand(highest)
660
- output.puts "Guess the number between 0-#{highest}: ('.' to quit)"
661
- count = 0
662
- while(true)
663
- count += 1
664
- str = Readline.readline("game > ", true)
665
- break if str == "." || !str
666
- val = str.to_i
667
- output.puts "Too large!" if val > num
668
- output.puts "Too small!" if val < num
669
- if val == num
670
- output.puts "Well done! You guessed right! It took you #{count} guesses."
671
- break
672
- end
673
- end
674
- end
675
-
676
- command "east-coker", "" do
677
- text = %{
678
- --
679
- Now the light falls
680
- Across the open field, leaving the deep lane
681
- Shuttered with branches, dark in the afternoon,
682
- Where you lean against a bank while a van passes,
683
- And the deep lane insists on the direction
684
- Into the village, in the electric heat
685
- Hypnotised. In a warm haze the sultry light
686
- Is absorbed, not refracted, by grey stone.
687
- The dahlias sleep in the empty silence.
688
- Wait for the early owl.
689
- -- T.S Eliot
690
- }
691
- output.puts text
692
- text
693
- end
694
-
695
- command "cohen-poem", "" do
696
- text = %{
697
- --
698
- When this American woman,
699
- whose thighs are bound in casual red cloth,
700
- comes thundering past my sitting place
701
- like a forest-burning Mongol tribe,
702
- the city is ravished
703
- and brittle buildings of a hundred years
704
- splash into the street;
705
- and my eyes are burnt
706
- for the embroidered Chinese girls,
707
- already old,
708
- and so small between the thin pines
709
- on these enormous landscapes,
710
- that if you turn your head
711
- they are lost for hours.
712
- -- Leonard Cohen
713
- }
714
- output.puts text
715
- text
716
- end
717
- end
718
- end