U:RDoc::AnyMethod[iI"slice_before:ETI"Enumerable#slice_before;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"6Creates an enumerator for each chunked elements. ;TI"EThe beginnings of chunks are defined by _pattern_ and the block.;To:RDoc::Markup::BlankLineo; ; [I"PIf _pattern_ === _elt_ returns true or the block ;TI"Nreturns true for the element, the element is beginning of a ;TI" chunk.;T@o; ; [I"SThe === and _block_ is called from the first element to the last ;TI"Eelement of _enum_. The result for the first element is ignored.;T@o; ; [I"DThe result enumerator yields the chunked elements as an array. ;TI"/So +each+ method can be called as follows:;T@o:RDoc::Markup::Verbatim; [I"3enum.slice_before(pattern).each { |ary| ... } ;TI"9enum.slice_before { |elt| bool }.each { |ary| ... } ;T: @format0o; ; [I"BOther methods of the Enumerator class and Enumerable module, ;TI"2such as +to_a+, +map+, etc., are also usable.;T@o; ; [I"IFor example, iteration over ChangeLog entries can be implemented as ;TI" follows:;T@o; ; [I"'# iterate over ChangeLog entries. ;TI"open("ChangeLog") { |f| ;TI"0 f.slice_before(/\A\S/).each { |e| pp e } ;TI"} ;TI" ;TI"B# same as above. block is used instead of pattern argument. ;TI"open("ChangeLog") { |f| ;TI"C f.slice_before { |line| /\A\S/ === line }.each { |e| pp e } ;TI"} ;T; 0o; ; [I"@"svn proplist -R" produces multiline output for each file. ;TI"$They can be chunked as follows:;T@o; ; [ I"@IO.popen([{"LC_ALL"=>"C"}, "svn", "proplist", "-R"]) { |f| ;TI"? f.lines.slice_before(/\AProp/).each { |lines| p lines } ;TI"} ;TI"E#=> ["Properties on '.':\n", " svn:ignore\n", " svk:merge\n"] ;TI"># ["Properties on 'goruby.c':\n", " svn:eol-style\n"] ;TI"T# ["Properties on 'complex.c':\n", " svn:mime-type\n", " svn:eol-style\n"] ;TI"@# ["Properties on 'regparse.c':\n", " svn:eol-style\n"] ;TI" # ... ;T; 0o; ; [ I"BIf the block needs to maintain state over multiple elements, ;TI""local variables can be used. ;TI"OFor example, three or more consecutive increasing numbers can be squashed ;TI"5as follows (see +chunk_while+ for a better way):;T@o; ; [I"a = [0, 2, 3, 4, 6, 7, 9] ;TI"prev = a[0] ;TI"p a.slice_before { |e| ;TI" prev, prev2 = e, prev ;TI" prev2 + 1 != e ;TI"}.map { |es| ;TI"@ es.length <= 2 ? es.join(",") : "#{es.first}-#{es.last}" ;TI"}.join(",") ;TI"#=> "0,2-4,6,7,9" ;T; 0o; ; [ I"6However local variables should be used carefully ;TI";if the result enumerator is enumerated twice or more. ;TI"EThe local variables should be initialized for each enumeration. ;TI")Enumerator.new can be used to do it.;T@o; ; [,I"D# Word wrapping. This assumes all characters have same width. ;TI"#def wordwrap(words, maxwidth) ;TI" Enumerator.new {|y| ;TI"2 # cols is initialized in Enumerator.new. ;TI" cols = 0 ;TI"" words.slice_before { |w| ;TI"" cols += 1 if cols != 0 ;TI" cols += w.length ;TI" if maxwidth < cols ;TI" cols = w.length ;TI" true ;TI" else ;TI" false ;TI" end ;TI"# }.each {|ws| y.yield ws } ;TI" } ;TI" end ;TI"#text = (1..20).to_a.join(" ") ;TI",enum = wordwrap(text.split(/\s+/), 10) ;TI"puts "-"*10 ;TI"?enum.each { |ws| puts ws.join(" ") } # first enumeration. ;TI"puts "-"*10 ;TI"cenum.each { |ws| puts ws.join(" ") } # second enumeration generates same result as the first. ;TI"puts "-"*10 ;TI"#=> ---------- ;TI"# 1 2 3 4 5 ;TI"# 6 7 8 9 10 ;TI"# 11 12 13 ;TI"# 14 15 16 ;TI"# 17 18 19 ;TI" # 20 ;TI"# ---------- ;TI"# 1 2 3 4 5 ;TI"# 6 7 8 9 10 ;TI"# 11 12 13 ;TI"# 14 15 16 ;TI"# 17 18 19 ;TI" # 20 ;TI"# ---------- ;T; 0o; ; [I"Dmbox contains series of mails which start with Unix From line. ;TI"BSo each mail can be extracted by slice before Unix From line.;T@o; ; ["I"# parse mbox ;TI"open("mbox") { |f| ;TI" f.slice_before { |line| ;TI"" line.start_with? "From " ;TI" }.each { |mail| ;TI" unix_from = mail.shift ;TI" i = mail.index("\n") ;TI" header = mail[0...i] ;TI" body = mail[(i+1)..-1] ;TI"' body.pop if body.last == "\n" ;TI"O fields = header.slice_before { |line| !" \t".include?(line[0]) }.to_a ;TI" p unix_from ;TI" pp fields ;TI" pp body ;TI" } ;TI"} ;TI" ;TI"M# split mails in mbox (slice before Unix From line after an empty line) ;TI"open("mbox") { |f| ;TI" emp = true ;TI" f.slice_before { |line| ;TI" prevemp = emp ;TI" emp = line == "\n" ;TI". prevemp && line.start_with?("From ") ;TI" }.each { |mail| ;TI"' mail.pop if mail.last == "\n" ;TI" pp mail ;TI" } ;TI"};T; 0: @fileI" enum.c;T:0@omit_headings_from_table_of_contents_below0I"enum.slice_before(pattern) -> an_enumerator enum.slice_before { |elt| bool } -> an_enumerator ;T0[I" (p1);T@FI"Enumerable;TcRDoc::NormalModule00