# xmp.rb =begin == NAME ((*xmp*)) - example printer == SYNOPSIS require "xmp" Kernel::xmp string [, fmt [, sep]] xmp string [, fmt [, sep]] == DESCRIPTION ((*xmp*)) is an example printer. It makes it easier to write example code. It executes given code line by line printing the code and evaluated result. The function (({xmp})) evaluates the first argument ((|string|)) (code) and then prints the code and evaluated value ((|string|)) result value. The second argument ((|fmt|)) specifies the report format. The format string ((|fmt|)) can include special patterns "%l" and "%r". "%l"s are replaced with the code line and "%r" with the result. If (({false})) or (({nil})) is given as second argument ((|fmt|)), (({xmp})) doesn't print the result. The third argument ((|sep|)) specifies the report separator for the multi-line output. This string ((|sep|)) is put between the output lines unless ((|fmt|)) is false. Unless (({false})) is given as the second argument, (({xmp})) can't treat a statement which consist of more than one line. If (({false})) is given as the second argument (({xmp})) doesn't print the evaluated result. In other words it doesn't support multi-line statements. == CONSTANTS :XMP_VERSION (({XMP_VERSION})) is version string which stand for the last modification date (YYYY-MM-DD). :XMP_DEFAULT_OPTION (({XMP_DEFAULT_OPTION})) is default option. (({xmp(arg)})) is intepreted as (({xmp(arg, *XMP_DEFAULT_OPTION)})). == SIMPLE EXAMPLE === EXAMPLE 1 To show what `(({nil.to_i}))' returns xmp "nil.to_i" That report as follows (In this section, A vertical bar `(('|'))' at beginnig of a line indicates output): | nil.to_i | #=> 0 === EXAMPLE 2 To demonstate few built-in library functions xmp <<-EOS a = "The moon Fly" b = [a.split, "TO", "Me"] b = b.flatten b.sort! b.join(" ").capitalize EOS The result: | a = "The moon Fly" | #=> "The moon Fly" | b = [a.split, "TO", "Me"] | #=> [["The", "moon", "Fly"], "TO", "Me"] | b = b.flatten | #=> ["The", "moon", "Fly", "TO", "Me"] | b.sort! | #=> ["Fly", "Me", "TO", "The", "moon"] | b.join(" ").capitalize | #=> "Fly me to the moon" === EXAMPLE 3 To show how attr works xmp <<-EOS, false class Foo attr :a, true end EOS xmp <<-EOS foo = Foo.new foo.a foo.a = 10 foo.b foo.a end The result: | class Foo | attr :a, true | end | | foo = Foo.new | #=> # | foo.a | #=> nil | foo.a = 10 | #=> 10 | foo.b | #!! undefined method `b' for # | foo.a | #=> 10 == TIPS By default (({xmp})) prepends ``(({#=> }))'' to each evaluated result. It is convenient when one includes (({xmp}))'s output to an email message by cutting & pasting because such messages can be cut & pasted immediately to ruby interpreter by recipient. In combination with (({if __FILE__ == $0})) idiom, one can give an example how to use the functionality in the source file. For example, one can put some code at the end of foo.rb to show usage as follows: if __FILE__ == $0 require "xmp" xmp <<-EOS, false class Bar ... end EOS xmp <<-EOS bar = BAR.new ... EOS end Another example in the end of (({xmp.rb})). For code demonstrating purposes, however, usage of RubyUnit or Testsupp might be more appropriate. == SEE ALSO Irb - interactive ruby (written by Keiju Ishitsuka) == BUG (({Xmp}))'s report follows the outout of the first argument ((|string|)) to the standard output or the standard error. Doesn't handle multi-line statements or comments (well at least :). == HISTORY 2000-10-12: commits "2000-07-03" with little change (gotoken@notwork.org) 2000-07-03: few changes in documentation and simple comment handling (aleksi) 2000-02-07: format customizing and excepcion reporting (gotoken@notwork.org) 2000-01-03: documentation (gotoken@notwork.org) == URL See Ruby Application Archive (()) for information about the latest version. == AUTHOR Gotoken =end module Kernel XMP_VERSION = "2000-10-12" XMP_DEFAULT_OPTION = ["%l\n #=> %r\n", "\n # "] def xmpsec(*a) puts *a; end def xmp(arg, fmt = XMP_DEFAULT_OPTION[0], sep=XMP_DEFAULT_OPTION[1]) if fmt fmt = fmt.to_s eval("___sep___ = #{sep.inspect}; ___res___ = []", TOPLEVEL_BINDING) eval(arg.gsub(/^(.*)\n?/){%Q| begin ___res___ << eval(%Q\0#{$1}\0).inspect.gsub(/^\\n/, ___sep___); rescue ___res___ << "!! " + $!; end|}, TOPLEVEL_BINDING) arg.split(/\n/).each_with_index{|l,i| (puts "\n" ; next) if l =~ /^$/ (puts l ; next) if l =~ /^\s*#/ res = fmt.gsub(/%l/, l) res = res.gsub(/%r/, eval("___res___", TOPLEVEL_BINDING)[i]) print res } else print arg; eval(arg, TOPLEVEL_BINDING) end end alias __xmp__ xmp end if __FILE__ == $0 if ARGV[0] xmp ARGF.read exit end puts "## EXAMPLE 1" xmp "nil.to_i" xmp <<-EOS ## EXAMPLE 2 a = "The moon Fly" b = [a.split, "TO", "Me"] b = b.flatten b.sort! b.join(" ").capitalize EOS xmp <<-EOS, false ## EXAMPLE 3 class Foo attr :a, true end EOS xmp <<-EOS foo = Foo.new foo.a foo.a = 10 foo.b foo.a EOS end