# coding: utf-8
=begin
* Name: SiSU
* Description: a framework for document structuring, publishing and search
* Author: Ralph Amissah
* Copyright: (C) 1997 - 2010, Ralph Amissah, All Rights Reserved.
* License: GPL 3 or later:
SiSU, a framework for document structuring, publishing and search
Copyright (C) Ralph Amissah
This program is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free
Software Foundation, either version 3 of the License, or (at your option)
any later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program. If not, see .
If you have Internet connection, the latest version of the GPL should be
available at these locations:
* SiSU uses:
* Standard SiSU markup syntax,
* Standard SiSU meta-markup syntax, and the
* Standard SiSU object citation numbering and system
* Hompages:
* Download:
* Ralph Amissah
** Description: document abstraction
=end
module SiSU_document_structure_extract
class Instantiate < SiSU_Param::Parameters::Instructions
@@flag={} #Beware!!
def initialize
@@flag['table_to']=false
@@counter=@@column=@@columns=0
@@line_mode=''
end
end
class Build
@@flag={} #Beware!!
def initialize(md,data)
@md,@data=md,data
Instantiate.new
@pb=SiSU_document_structure::Object_layout.new.break(Hx[:br_page])
@pbn=SiSU_document_structure::Object_layout.new.break(Hx[:br_page_new])
end
def ln_get(lv)
ln=case lv
when /A/; 1
when /B/; 2
when /C/; 3
when /1/; 4
when /2/; 5
when /3/; 6
when /4/; 7
when /5/; 8
when /6/; 9
end
end
def image_test(str)
boolean=(str=~/\{\s*\S+?\.png.+?\}https?:\/\/\S+/ ? true : false)
end
def bullet_test(str)
bool=((str=~/\*/) ? true : false)
end
def indent_test(str)
num=((str=~/^_([1-9])/) ? $1 : 0)
end
def endnote_test?(str)
bool=((str=~/~\{.+?\}~|~\[.+?\]~/) ? true : false)
end
def extract_tags(str,nametag=nil)
tags=[]
if str.nil?
else
if str =~/(?:^|[ ])\*~([a-z0-9._-]+)(?=[ #{Mx[:br_nl]}]|$)/
str.gsub!(/(^|[ ])\*~([a-z0-9._-]+)(?=[ #{Mx[:br_nl]}]|$)/i,
"\\1#{Mx[:tag_o]}\\2#{Mx[:tag_c]}")
str.gsub!(/ [ ]+/i,' ')
tags=str.scan(/#{Mx[:tag_o]}(\S+?)#{Mx[:tag_c]}/).flatten
str.gsub!(/[ ]?#{Mx[:tag_o]}\S+?#{Mx[:tag_c]}[ ]?/,' ') #may be issues with spaces would leave one, but "code" blocks?
end
tags=nametag ? (tags << nametag) : tags
end
[str,tags]
end
def identify_parts
data=@data
tuned_file=[]
@tuned_group,@tuned_code=[],[]
@@counter,@verse_count=0,0
@metadata={}
@data.each do |t_o|
t_o.gsub!(/(?:\n\s*\n)+/m,"\n") unless @@flag['code']
if t_o !~/^(?:code|poem|alt|group)\{|^\}(?:code|poem|alt|group)|^(?:table\{|\{table)[ ~]/ \
and not @@flag['code'] \
and not @@flag['poem'] \
and not @@flag['group'] \
and not @@flag['alt'] \
and not @@flag['table']
unless t_o =~/^(?:@\S+?:|%+)\s/ # extract book index for paragraph if any
idx=if t_o=~/^=\{(.+)\}\s*$\Z/m; m=$1
t_o.gsub!(/\n=\{.+\}\s*$\Z/m,'')
m
else nil
end
end
t_o=case t_o
when /^#{Mx[:meta_o]}\S+?#{Mx[:meta_c]}/ #metadata, header
if t_o=~/^#{Mx[:meta_o]}(\S+?)#{Mx[:meta_c]}\s*(.+)/m
tag,obj=$1,$2
@metadata[tag]=obj
end
t_o=nil
when /^%+\s/ #comment
t_o=if t_o=~/^%+\s+(.+)/
h={:obj=>$1}
SiSU_document_structure::Object_comment.new.comment(h)
else nil
end
when /^:?([A-C1-6])\~/ #heading / lv
lv=$1
ln=ln_get(lv)
t_o=if t_o=~/^:?[A-C1-6]\~\s+(.+)/
obj=$1
note=endnote_test?(obj)
obj,tags=extract_tags(obj)
h={:lv=>lv,:ln=>ln,:obj=>obj,:idx=>idx,:tags=>tags}
SiSU_document_structure::Object_heading.new.heading(h)
elsif t_o=~/^:?[A-C1-6]\~(\S+?)-\s+(.+)/
name,obj=$1,$2
note=endnote_test?(obj)
obj,tags=extract_tags(obj)
h={:lv=>lv,:name=>name,:obj=>obj,:idx=>idx,:autonum_=>false,:tags=>tags}
SiSU_document_structure::Object_heading.new.heading(h)
elsif t_o=~/^:?[A-C1-6]\~(\S+)\s+(.+)/
name,obj=$1,$2
note=endnote_test?(obj)
obj,tags=extract_tags(obj,name)
h={:lv=>lv,:name=>name,:obj=>obj,:idx=>idx,:tags=>tags}
SiSU_document_structure::Object_heading.new.heading(h)
else nil
end
when /^(?:_[1-9]|_[1-9]?\*)\s+/ #indented and/or bullet paragraph
t_o=if t_o=~/^(_(?:[1-9]?\*|[1-9])\s+)(.+)/
tst,obj=$1,$2
indent=indent_test(tst)
bullet=bullet_test(tst)
image=image_test(obj)
note=endnote_test?(obj)
obj,tags=extract_tags(obj)
h={:bullet_=>bullet,:indent=>indent,:obj=>obj,:idx=>idx,:note_=>note,:image_=>image,:tags=>tags}
SiSU_document_structure::Object_para.new.paragraph(h)
else nil
end
when /^(?:?)\s*$/ #indented and/or bullet paragraph
if t_o =~/^(?:?)\s*$/
SiSU_document_structure::Object_layout.new.break(Hx[:br_page_new])
else SiSU_document_structure::Object_layout.new.break(Hx[:br_page])
end
else #paragraph
image=image_test(t_o)
note=endnote_test?(t_o)
obj,tags=extract_tags(t_o)
h={:bullet_=>false,:indent=>0,:obj=>obj,:idx=>idx,:note_=>note,:image_=>image,:tags=>tags}
SiSU_document_structure::Object_para.new.paragraph(h)
end
elsif not @@flag['code']
if t_o =~/^code\{/
@@flag['code']=true
@@counter=1
@codeblock_numbered=(t_o =~/^code\{#/) ? true : false
h={:obj=>'code block start'} #introduce a counter
t_o=SiSU_document_structure::Object_comment.new.comment(h) #t_o=SiSU_document_structure::Object_layout.new.insert(h)
elsif t_o =~/^poem\{/
@@flag['poem']=true
h={:obj=>'poem start'} #introduce a counter
t_o=SiSU_document_structure::Object_comment.new.comment(h) #t_o=SiSU_document_structure::Object_layout.new.insert(h)
tuned_file << t_o
elsif t_o =~/^group\{/
@@flag['group']=true
h={:obj=>'group text start'} #introduce a counter
t_o=SiSU_document_structure::Object_comment.new.comment(h) #t_o=SiSU_document_structure::Object_layout.new.insert(h)
tuned_file << t_o
elsif t_o =~/^alt\{/
@@flag['alt']=true
h={:obj=>'alt text start'} #introduce a counter
t_o=SiSU_document_structure::Object_comment.new.comment(h) #t_o=SiSU_document_structure::Object_layout.new.insert(h)
tuned_file << t_o
elsif t_o =~/^(?:table\{|\{table)[ ~]/
h={:obj=>'table start'} #introduce a counter
ins=SiSU_document_structure::Object_comment.new.comment(h) #ins=SiSU_document_structure::Object_layout.new.insert(h)
tuned_file << ins
if t_o=~/^table\{(?:~h)?\s+/
@@flag['table']=true
@rows=''
case t_o
when /table\{~h\s+c(\d+);\s+(.+)/
cols=$1
col=$2.scan(/\d+/)
heading=true
when /table\{\s+c(\d+);\s+(.+)/
cols=$1
col=$2.scan(/\d+/)
heading=false
end
@h={:head_=>heading,:cols=>cols,:widths=>col,:idx=>idx}
elsif t_o=~/^\{table(?:~h)?(?:\s+\d+;?)?\}\n.+\Z/m
m1,m2,hd=nil,nil,nil
tbl=/^\{table(?:~h)?(?:\s+\d+;?)?\}\n(.+)\Z/m.match(t_o)[1] #two table representations should be consolidated as one
hd=((t_o =~/^\{table~h/) ? true : false)
tbl,tags=extract_tags(tbl)
rws=tbl.split(/\n/)
rows=''
cols=nil
rws.each do |r|
cols=(cols ? cols : (r.scan('|').length) +1)
r.gsub!(/\s*\|\s*/m,"#{Mx[:tc_p]}") #r.gsub!(/\|/m,"#{Mx[:tc_p]}")
rows += r + Mx[:tc_c]
end
col=[]
if t_o =~/^\{table(?:~h)?\s+(\d+);?\}/ #width of col 1 given as %, usually when wider than rest that are even
c1=$1.to_i
width=(100 - c1)/(cols - 1)
col=[ c1 ]
(cols - 1).times { col << width }
else #all columns of equal width
width=100.00/cols
cols.times { col << width }
end
h={:head_=>hd,:cols=>cols,:widths=>col,:obj=>rows,:idx=>idx,:tags=>tags}
t_o=SiSU_document_structure::Object_table.new.table(h) unless h.nil?
tuned_file << t_o
h={:obj=>'table end'} #introduce a counter
t_o=SiSU_document_structure::Object_comment.new.comment(h)
t_o
elsif t_o=~/^\{table(?:~h)?\s+/
m1,m2,hd=nil,nil,nil
h=case t_o
when /\{table~h\s+(.+?)\}\n(.+)\Z/m #two table representations should be consolidated as one
m1,tbl,hd=$1,$2,true
when /\{table\s+(.+?)\}\n(.+)\Z/m #two table representations should be consolidated as one
m1,tbl,hd=$1,$2,false
else nil
end
tbl,tags=extract_tags(tbl)
col=m1.scan(/\d+/)
rws=tbl.split(/\n/)
rows=''
rws.each do |r|
r.gsub!(/\s*\|\s*/m,"#{Mx[:tc_p]}") #r.gsub!(/\|/m,"#{Mx[:tc_p]}")
rows += r + Mx[:tc_c]
end
h={:head_=>hd,:cols=>col.length,:widths=>col,:obj=>rows,:idx=>idx,:tags=>tags}
t_o=SiSU_document_structure::Object_table.new.table(h) unless h.nil?
tuned_file << t_o
h={:obj=>'table end'} #introduce a counter
t_o=SiSU_document_structure::Object_comment.new.comment(h)
t_o
end
end
t_o
end
if @@flag['table']
if @@flag['table'] \
and t_o =~/^\}table/ #two table representations should be consolidated as one
@@flag['table']=false
headings,columns,widths,idx=@h[:head_],@h[:cols],@h[:widths],@h[:idx]
@h={:head_=>headings,:cols=>columns,:widths=>widths,:idx=>idx,:obj=>@rows}
t_o=SiSU_document_structure::Object_table.new.table(@h)
tuned_file << t_o
@h,@rows=nil,''
t_o
h={:obj=>'table end'} #introduce a counter
t_o=SiSU_document_structure::Object_comment.new.comment(h) #t_o=SiSU_document_structure::Object_layout.new.insert(h)
t_o
else
if t_o !~/^table\{/ and not t_o.nil?
t_o.gsub!(/\n/m,"#{Mx[:tc_p]}")
@rows += t_o + Mx[:tc_c]
end
t_o=nil
end
end
if @@flag['code']
if t_o =~/^\}code/
@@flag['code']=false
obj,tags=extract_tags(@tuned_code.join("\n"))
h={:obj=>obj,:tags=>tags,:number_=>@codeblock_numbered}
t_o=SiSU_document_structure::Object_group.new.code(h)
@tuned_code=[]
tuned_file << t_o
h={:obj=>'code block end'} #introduce a counter
t_o=SiSU_document_structure::Object_comment.new.comment(h) #t_o=SiSU_document_structure::Object_layout.new.insert(h)
end
if @@flag['code'] \
and t_o.class==String \
and not t_o.nil? #you may need to introduce t_o.class==String test more widely
sub_array=t_o.dup + "#{Mx[:br_nl]}"
@line_mode=sub_array.scan(/.+/)
@line_mode=[]
sub_array.scan(/.+/) {|w| @line_mode << w if w =~/[\Ss]+/}
t_o=SiSU_document_structure_extract::Build.new(@md,@line_mode).build_lines('code').join
@tuned_code << t_o
t_o=nil
end
elsif @@flag['poem'] \
or @@flag['group'] \
or @@flag['alt']
if @@flag['poem'] \
and t_o =~/^\}poem/
@@flag['poem']=false
h={:obj=>'poem end'} #introduce a counter
t_o=SiSU_document_structure::Object_comment.new.comment(h) #t_o=SiSU_document_structure::Object_layout.new.insert(h)
elsif ( @@flag['group'] \
and t_o =~/^\}group/ )
@@flag['group']=false
obj,tags=extract_tags(@tuned_group.join("\n"))
h={:obj=>obj,:tags=>tags}
@tuned_group=[]
t_o=SiSU_document_structure::Object_group.new.group(h)
tuned_file << t_o
h={:obj=>'group text end'} #introduce a counter
t_o=SiSU_document_structure::Object_comment.new.comment(h) #t_o=SiSU_document_structure::Object_layout.new.insert(h)
elsif ( @@flag['alt'] \
and t_o =~/^\}alt/ )
@@flag['alt']=false
obj,tags=extract_tags(@tuned_group.join("\n"))
h={:obj=>obj,:tags=>tags}
t_o=SiSU_document_structure::Object_group.new.alt(h)
@tuned_group=[]
tuned_file << t_o
h={:obj=>'alt text end'} #introduce a counter
t_o=SiSU_document_structure::Object_comment.new.comment(h) #t_o=SiSU_document_structure::Object_layout.new.insert(h)
end
if @@flag['poem'] \
or @@flag['group'] \
or @@flag['alt'] \
and t_o =~/\S/ \
and t_o !~/^(?:\}(?:verse|code|alt|group)|(?:verse|code|alt|group)\{)/ # fix logic
sub_array=t_o.dup
@line_mode=sub_array.scan(/.+/)
type=if @@flag['poem']; 'poem'
t_o=SiSU_document_structure_extract::Build.new(@md,@line_mode).build_lines(type).join
poem=t_o.split(/\n\n/)
poem.each do |v|
v.gsub!(/\n/m,"#{Mx[:br_nl]}\n")
obj,tags=extract_tags(v)
h={:obj=>obj,:tags=>tags}
t_o=SiSU_document_structure::Object_group.new.verse(h)
tuned_file << t_o
end
else 'group'
end
@verse_count+=1 if @@flag['poem']
end
end
if not @@flag['code']
if @@flag['poem'] \
or @@flag['group'] \
or @@flag['alt']
if t_o.class==String
t_o.gsub!(/\n/m,"#{Mx[:br_nl]}")
t_o.gsub!(/[ ][ ]/m,"#{Mx[:nbsp]*2}")
t_o.gsub!(/#{Mx[:nbsp]}\s/,"#{Mx[:nbsp]*2}")
t_o=t_o + Mx[:br_nl] if t_o =~/\S+/
elsif t_o.is=='group' \
or t_o.is=='alt' \
or t_o.is=='verse'
t_o.obj.gsub!(/\n/m,"#{Mx[:br_nl]}")
t_o.obj.gsub!(/[ ][ ]/m,"#{Mx[:nbsp]*2}")
t_o.obj.gsub!(/#{Mx[:nbsp]}\s/,"#{Mx[:nbsp]*2}")
end
@tuned_group << t_o if t_o =~/\S+/
else tuned_file << t_o
end
else tuned_file << t_o
end
end
if @md.flag_endnotes
tuned_file << @pb
h={:ln=>2,:obj=>'Endnotes',:autonum_=>false}
tuned_file << SiSU_document_structure::Object_heading.new.heading_insert(h)
h={:ln=>4,:obj=>'Endnotes',:name=>'endnotes',:autonum_=>false}
tuned_file << SiSU_document_structure::Object_heading.new.heading_insert(h)
h={:obj=>'Endnotes'}
end
if @md.book_idx
tuned_file << @pb
h={:ln=>2,:obj=>'Index',:autonum_=>false}
tuned_file << SiSU_document_structure::Object_heading.new.heading_insert(h)
h={:ln=>4,:obj=>'Index',:name=>'book_index',:autonum_=>false}
tuned_file << SiSU_document_structure::Object_heading.new.heading_insert(h)
h={:obj=>'Index'}
end
tuned_file << @pb
h={:ln=>2,:obj=>'Metadata',:autonum_=>false,:ocn_=>false}
tuned_file << SiSU_document_structure::Object_heading.new.heading_insert(h)
h={:ln=>4,:obj=>'SiSU Metadata, document information',:name=>'metadata',:autonum_=>false,:ocn_=>false}
tuned_file << SiSU_document_structure::Object_heading.new.heading_insert(h)
tuned_file << @pb
h={:ln=>2,:obj=>'Manifest',:autonum_=>false,:ocn_=>false}
tuned_file << SiSU_document_structure::Object_heading.new.heading_insert(h)
h={:ln=>4,:obj=>'SiSU Manifest, alternative outputs etc.',:name=>'sisu_manifest',:autonum_=>false,:ocn_=>false}
tuned_file << SiSU_document_structure::Object_heading.new.heading_insert(h)
tuned_file
h={:obj=>'eof'}
meta=SiSU_document_structure::Object_metadata.new.metadata(@metadata)
[tuned_file,meta]
end
def table_rows_and_columns_array(table_str)
table=[]
table_str.split(/#{Mx[:tc_c]}/).each do |table_row|
table_row_with_columns=table_row.split(/#{Mx[:tc_p]}/)
table << table_row_with_columns
end
table
end
def meta_heading(h)
h={:lv=>h[:lv],:ln=>h[:ln],:name=>h[:name],:obj=>h[:obj],:ocn=>'0'}
SiSU_document_structure::Object_heading.new.heading(h)
end
def meta_para(str)
h={:obj=>str,:ocn_=>false}
SiSU_document_structure::Object_para.new.paragraph(h)
end
def metadata
meta=[]
dir=SiSU_Env::Info_env.new(@md.fns)
base_html="#{dir.url.root}/#{@md.fnb}"
l=SiSU_Env::Standardise_language.new.file_to_language(@md.fns)
language=l[:l]
tr=SiSU_Translate::Source.new(@md,language)
meta << @pb
h={:ln=>2,:obj=>'Metadata',:ocn_=>false}
meta << SiSU_document_structure::Object_heading.new.heading(h)
h={:ln=>4,:name=>'metadata',:obj=>'Metadata',:autonum_=>false,:ocn_=>false}
meta << SiSU_document_structure::Object_heading.new.heading(h) #add ocnm
s="Document Manifest @\n #{base_html}/#{@md.fn[:manifest]}"
meta << meta_para(s)
s="#{Mx[:fa_bold_o]}Dublin Core#{Mx[:fa_bold_c]} (DC)" #add ocnm
meta << meta_para(s)
s="#{Mx[:fa_italics_o]}DC tags included with this document are provided here.#{Mx[:fa_italics_c]}" #add ocnm
meta << meta_para(s)
if defined? @md.title.full \
and @md.title.full=~/\S+/
s="#{tr.full_title}: #{Mx[:fa_underscore_o]}#{@md.title.full}#{Mx[:fa_underscore_c]}"
meta << meta_para(s)
end
if defined? @md.creator.author \
and @md.creator.author=~/\S+/
s="\n#{tr.author}: #{Mx[:fa_underscore_o]}#{@md.creator.author}#{Mx[:fa_underscore_c]}"
meta << meta_para(s)
end
if defined? @md.creator.translator \
and @md.creator.translator=~/\S+/
s="#{tr.translator}: #{Mx[:fa_underscore_o]}#{@md.creator.translator}#{Mx[:fa_underscore_c]}"
meta << meta_para(s)
end
if defined? @md.creator.illustrator \
and @md.creator.illustrator=~/\S+/
s="#{tr.illustrator}: #{Mx[:fa_underscore_o]}#{@md.creator.illustrator}#{Mx[:fa_underscore_c]}"
meta << meta_para(s)
end
if defined? @md.creator.prepared_by \
and @md.creator.prepared_by=~/\S+/
s="\n#{tr.prepared_by}: #{Mx[:fa_underscore_o]}#{@md.creator.prepared_by}#{Mx[:fa_underscore_c]}"
meta << meta_para(s)
end
if defined? @md.creator.digitized_by \
and @md.creator.digitized_by=~/\S+/
s="#{tr.digitized_by}: #{Mx[:fa_underscore_o]}#{@md.creator.digitized_by}#{Mx[:fa_underscore_c]}"
meta << meta_para(s)
end
if defined? @md.rights.all \
and @md.rights.all=~/\S+/
s="\n#{tr.rights}: #{Mx[:fa_underscore_o]}#{@md.rights.all}#{Mx[:fa_underscore_c]}"
meta << meta_para(s)
end
if defined? @md.notes.description \
and @md.notes.description=~/\S+/
s="#{tr.description}: #{Mx[:fa_underscore_o]}#{@md.notes.description}#{Mx[:fa_underscore_c]}"
meta << meta_para(s)
end
if defined? @md.classify.subject \
and @md.classify.subject=~/\S+/
s="#{tr.subject}: #{Mx[:fa_underscore_o]}#{@md.classify.subject}#{Mx[:fa_underscore_c]}"
meta << meta_para(s)
end
if defined? @md.publisher \
and @md.publisher=~/\S+/
s="\n#{tr.publisher}: #{Mx[:fa_underscore_o]}#{@md.publisher}#{Mx[:fa_underscore_c]}"
meta << meta_para(s)
end
if defined? @md.creator.contributor \
and @md.creator.contributor=~/\S+/
s="\n#{tr.contributor}: #{Mx[:fa_underscore_o]}#{@md.creator.contributor}#{Mx[:fa_underscore_c]}"
meta << meta_para(s)
end
if defined? @md.notes.abstract \
and @md.notes.abstract=~/\S+/
s="\n#{tr.abstract}: #{Mx[:fa_underscore_o]}#{@md.notes.abstract}#{Mx[:fa_underscore_c]}"
meta << meta_para(s)
end
if defined? @md.date.created \
and @md.date.created=~/\S+/
s="\n#{tr.date_created}: #{Mx[:fa_underscore_o]}#{@md.date.created}#{Mx[:fa_underscore_c]}"
meta << meta_para(s)
end
if defined? @md.date.issued \
and @md.date.issued=~/\S+/
s="\n#{tr.date_issued}: #{Mx[:fa_underscore_o]}#{@md.date.issued}#{Mx[:fa_underscore_c]}"
meta << meta_para(s)
end
if defined? @md.date.available \
and @md.date.available=~/\S+/
s="\n#{tr.date_available}: #{Mx[:fa_underscore_o]}#{@md.date.available}#{Mx[:fa_underscore_c]}"
meta << meta_para(s)
end
if defined? @md.date.modified \
and @md.date.modified=~/\S+/
s="\n#{tr.date_modified}: #{Mx[:fa_underscore_o]}#{@md.date.modified}#{Mx[:fa_underscore_c]}"
meta << meta_para(s)
end
if defined? @md.date.valid \
and @md.date.valid=~/\S+/
s="\n#{tr.date_valid}: #{Mx[:fa_underscore_o]}#{@md.date.valid}#{Mx[:fa_underscore_c]}"
meta << meta_para(s)
end
if defined? @md.date.published \
and @md.date.published=~/\S+/
s="\n#{tr.date}: #{Mx[:fa_underscore_o]}#{@md.date.published}#{Mx[:fa_underscore_c]}"
meta << meta_para(s)
end
if defined? @md.classify.loc \
and @md.classify.loc=~/\S+/
s="\n#{tr.cls_loc}: #{Mx[:fa_underscore_o]}#{@md.classify.loc}#{Mx[:fa_underscore_c]}"
meta << meta_para(s)
end
if defined? @md.classify.dewey \
and @md.classify.dewey=~/\S+/
s="\n#{@cls_dewey}: #{Mx[:fa_underscore_o]}#{@md.classify.dewey}#{Mx[:fa_underscore_c]}"
meta << meta_para(s)
end
if defined? @md.classify.pg \
and @md.classify.pg=~/\S+/
s="\n#{tr.cls_gutenberg}: #{Mx[:fa_underscore_o]}#{@md.classify.pg}#{Mx[:fa_underscore_c]}"
meta << meta_para(s)
end
if defined? @md.classify.isbn \
and @md.classify.isbn=~/\S+/
s="\n#{tr.cls_isbn}: #{Mx[:fa_underscore_o]}#{@md.classify.isbn}#{Mx[:fa_underscore_c]}"
meta << meta_para(s)
end
if defined? @md.notes.comment \
and @md.notes.comment=~/\S+/
s="\n#{tr.comments}: #{Mx[:fa_underscore_o]}#{@md.notes.comment}#{Mx[:fa_underscore_c]}"
meta << meta_para(s)
end
if defined? @md.notes.prefix_a \
and @md.notes.prefix_a=~/\S+/
s="\n#{tr.prefix_a}: #{Mx[:fa_underscore_o]}#{@md.notes.prefix_a}#{Mx[:fa_underscore_c]}"
meta << meta_para(s)
end
if defined? @md.notes.prefix_b \
and @md.notes.prefix_b=~/\S+/
s="\n#{tr.prefix_b}: #{Mx[:fa_underscore_o]}#{@md.notes.prefix_b}#{Mx[:fa_underscore_c]}"
meta << meta_para(s)
end
if defined? @md.classify.identifier \
and @md.classify.identifier=~/\S+/
s="\n#{tr.identifier}: #{Mx[:fa_underscore_o]}#{@md.classify.identifier}#{Mx[:fa_underscore_c]}"
meta << meta_para(s)
end
if defined? @md.original.source \
and @md.original.source=~/\S+/
s="\n#{tr.source}: #{Mx[:fa_underscore_o]}#{@md.original.source}#{Mx[:fa_underscore_c]}"
meta << meta_para(s)
end
if defined? @md.title.language \
and @md.title.language=~/\S+/
s="\n#{tr.language}: #{Mx[:fa_underscore_o]}#{@md.title.language}#{Mx[:fa_underscore_c]}"
meta << meta_para(s)
end
if defined? @md.original.language \
and @md.original.language=~/\S+/
s="\n#{tr.language_original}: #{Mx[:fa_underscore_o]}#{@md.original.language}#{Mx[:fa_underscore_c]}"
meta << meta_para(s)
end
if defined? @md.classify.format \
and @md.classify.format=~/\S+/
s="\n#{tr.format}: #{Mx[:fa_underscore_o]}#{@md.classify.format}#{Mx[:fa_underscore_c]}"
meta << meta_para(s)
end
if defined? @md.classify.relation \
and @md.classify.relation=~/\S+/
s="\n#{tr.relation}: #{Mx[:fa_underscore_o]}#{@md.classify.relation}#{Mx[:fa_underscore_c]}"
meta << meta_para(s)
end
if defined? @md.classify.coverage \
and @md.classify.coverage=~/\S+/
s="\n#{tr.coverage}: #{Mx[:fa_underscore_o]}#{@md.classify.coverage}#{Mx[:fa_underscore_c]}"
meta << meta_para(s)
end
if defined? @md.classify.keywords \
and @md.classify.keywords=~/\S+/
s="\n#{tr.keywords}: #{Mx[:fa_underscore_o]}#{@md.classify.keywords}#{Mx[:fa_underscore_c]}"
meta << meta_para(s)
end
s="#{Mx[:fa_bold_o]}Version Information#{Mx[:fa_bold_c]}"
meta << meta_para(s)
if defined? @md.fns \
and @md.fns=~/\S+/
s="#{tr.sourcefile}: #{Mx[:fa_underscore_o]}#{@md.fns}#{Mx[:fa_underscore_c]}"
meta << meta_para(s)
end
if defined? @md.file_encoding \
and @md.file_encoding=~/\S+/
s="Filetype: #{Mx[:fa_underscore_o]}#{@md.file_encoding}#{Mx[:fa_underscore_c]}"
meta << meta_para(s)
end
if defined? @md.dgst \
and @md.dgst.class==Array
s="Source Digest: #{@md.dgst[0]} #{Mx[:fa_underscore_o]}#{@md.dgst[1]}#{Mx[:fa_underscore_c]}"
meta << meta_para(s)
end
if defined? @md.dgst_skin \
and @md.dgst_skin.class==Array
s="Skin Digest: #{@md.dgst_skin[0]} #{Mx[:fa_underscore_o]}#{@md.dgst_skin[1]}#{Mx[:fa_underscore_c]}"
meta << meta_para(s)
end
s="#{Mx[:fa_bold_o]}Generated#{Mx[:fa_bold_c]}"
meta << meta_para(s)
s="#{tr.last_generated}: #{Mx[:fa_underscore_o]}#{Time.now}#{Mx[:fa_underscore_c]}"
meta << meta_para(s)
s="#{tr.sisu_version}: #{Mx[:fa_underscore_o]}#{@md.sisu_version[:project]}#{Mx[:fa_underscore_c]} #{Mx[:fa_underscore_o]}#{@md.sisu_version[:version]}#{Mx[:fa_underscore_c]} of #{@md.sisu_version[:date_stamp]} (#{@md.sisu_version[:date]})"
meta << meta_para(s)
meta
end
def build_lines(type='')
data=@data
data.each do |line|
if line =~/\S/ \
and line !~/^code\{|^\}code/ \
and line.class != Hash
line.gsub!(/\s\s/,"#{Mx[:nbsp]*2}")
line.gsub!(/#{Mx[:nbsp]}\s/,"#{Mx[:nbsp]*2}")
line.gsub!(/^/,"#{Mx[:gr_o]}codeline#{Mx[:gr_c]}") if type=='code' # REMOVE try sort for texpdf special case
if line =~/(?:https?|file|ftp):\/\/\S+$/
line.gsub!(/\s*$/," #{Mx[:br_nl]}")
else line.gsub!(/\s*$/,"#{Mx[:br_nl]}") #unless type=='code'
end
if @@flag['code']; @@counter+=1
else
end
elsif line =~/^\s*$/
line.gsub!(/\s*$/,"#{Mx[:br_nl]}")
end
end
data
end
end
class Structure # this must happen early
def initialize(md,dob)
@md,@dob=md,dob
end
def structure
structure_markup_normalize
structure_markup
@dob
end
def structure_markup #build structure where structure provided only in meta header
@dob=if @dob.is =~/para/ \
and @dob.indent !~/[1-9]/ \
and not @dob.bullet_
@dob=case @dob.obj
when /^#{@md.lv1}/
h={:lv=>'A',:ln=>1}
SiSU_document_structure::Object_heading.new.heading(h,@dob)
when /^#{@md.lv2}/
h={:lv=>'B',:ln=>2}
SiSU_document_structure::Object_heading.new.heading(h,@dob)
when /^#{@md.lv3}/
h={:lv=>'C',:ln=>3}
SiSU_document_structure::Object_heading.new.heading(h,@dob)
when /^#{@md.lv4}/
h={:lv=>'1',:ln=>4}
SiSU_document_structure::Object_heading.new.heading(h,@dob)
when /^#{@md.lv5}/
h={:lv=>'2',:ln=>5}
SiSU_document_structure::Object_heading.new.heading(h,@dob)
when /^#{@md.lv6}/
h={:lv=>'3',:ln=>6}
SiSU_document_structure::Object_heading.new.heading(h,@dob)
else @dob
end
else @dob
end
@dob
end
def structure_markup_normalize #needs a bit of thinking
dob=if @md.markup_version.determined < 0.38 #%convert internal representation, consider making 0.38 structure default ([A-C1-6] instead of [1-9]), requires downstream changes
@dob.gsub!(/^[456]~/,'!_')
@dob.gsub!(/^3~(\S+)/,"#{Mx[:lv_o]}6:\\1#{Mx[:lv_c]}")
@dob.gsub!(/^3~\s+/,"#{Mx[:lv_o]}6:#{Mx[:lv_c]}")
@dob.gsub!(/^2~(\S+)/,"#{Mx[:lv_o]}5:\\1#{Mx[:lv_c]}")
@dob.gsub!(/^2~\s+/,"#{Mx[:lv_o]}5:#{Mx[:lv_c]}")
@dob.gsub!(/^1~(\S+)/,"#{Mx[:lv_o]}4:\\1#{Mx[:lv_c]}")
@dob.gsub!(/^1~\s+/,"#{Mx[:lv_o]}4:#{Mx[:lv_c]}")
@dob.gsub!(/^:?C~(\S+)/,"#{Mx[:lv_o]}3:\\1#{Mx[:lv_c]}")
@dob.gsub!(/^:?C~\s+/,"#{Mx[:lv_o]}3:#{Mx[:lv_c]}")
@dob.gsub!(/^:?B~(\S+)/,"#{Mx[:lv_o]}2:\\1#{Mx[:lv_c]}")
@dob.gsub!(/^:?B~\s+/,"#{Mx[:lv_o]}2:#{Mx[:lv_c]}")
@dob.gsub!(/^:?A~(\S+)/,"#{Mx[:lv_o]}1:\\1#{Mx[:lv_c]}")
@dob.gsub!(/^:?A~\s+/,"#{Mx[:lv_o]}1:#{Mx[:lv_c]}")
@dob=if @dob =~/^@(?:level|markup):\s/
@dob.gsub!(/3/,'6')
@dob.gsub!(/2/,'5')
@dob.gsub!(/1/,'4')
@dob.gsub!(/:?C/,'3')
@dob.gsub!(/:?B/,'2')
@dob.gsub!(/:?A/,'1')
@dob
else @dob
end
else @dob
end
end
def structure_marks
t_o=if @md.markup_version.determined < 0.38
@t_o.gsub!(/^1~(\S+)/,"#{Mx[:lv_o]}1:\\1#{Mx[:lv_c]}")
@t_o.gsub!(/^1~\s+/,"#{Mx[:lv_o]}1:#{Mx[:lv_c]}")
@t_o.gsub!(/^2~(\S+)/,"#{Mx[:lv_o]}2:\\1#{Mx[:lv_c]}")
@t_o.gsub!(/^2~\s+/,"#{Mx[:lv_o]}2:#{Mx[:lv_c]}")
@t_o.gsub!(/^3~(\S+)/,"#{Mx[:lv_o]}3:\\1#{Mx[:lv_c]}")
@t_o.gsub!(/^3~\s+/,"#{Mx[:lv_o]}3:#{Mx[:lv_c]}")
@t_o.gsub!(/^4~(\S+)/,"#{Mx[:lv_o]}4:\\1#{Mx[:lv_c]}")
@t_o.gsub!(/^4~\s+/,"#{Mx[:lv_o]}4:#{Mx[:lv_c]}")
@t_o.gsub!(/^5~(\S+)/,"#{Mx[:lv_o]}5:\\1#{Mx[:lv_c]}")
@t_o.gsub!(/^5~\s+/,"#{Mx[:lv_o]}5:#{Mx[:lv_c]}")
@t_o.gsub!(/^6~(\S+)/,"#{Mx[:lv_o]}6:\\1#{Mx[:lv_c]}")
@t_o.gsub!(/^6~\s+/,"#{Mx[:lv_o]}6:#{Mx[:lv_c]}")
@t_o.gsub!(/^[789]~/,'!_')
@t_o
else @t_o
end
end
end
class OCN
def initialize(md,data)
@md,@data=md,data
end
def ocn #and auto segment numbering increment
data=@data
@o_array=[]
node=ocn=ocn_dv=ocn_sp=ocnh=ocnh1=ocnh2=ocnh3=ocnh4=ocnh5=ocnh6=ocno=ocnp=ocnt=ocnc=ocng=ocni=ocnm=ocnu=ocnk=nm=0 # h heading, o other, t table, g group, i image
node_count_flag=false
regex_exclude_ocn_and_node = /#{Rx[:meta]}|^@\S+?:\s|^4~endnotes|^#{Mx[:lv_o]}4:endnotes#{Mx[:lv_c]}|^\^~ |<:e[:_]\d+?>|^#{Mx[:fa_o]}p[bn]#{Mx[:fa_c]}|^<:\#|<:- |<[:!]!4|
if dob.is=='heading'
ln=case dob.lv
when 'A'; 1
when 'B'; 2
when 'C'; 3
when '1'; 4
when '2'; 5
when '3'; 6
when '4'; 7
when '5'; 8
when '6'; 9
end
end
if not dob.obj =~/<:#>|~#|-#/ \
or not dob.toc_ # fix this no longer in dob.obj
ocn+=1
if dob.is=='heading' \
and (ln.to_s =~/^[1-9]/ \
or ln.to_s =~@md.lv1 \
or ln.to_s =~@md.lv2 \
or ln.to_s =~@md.lv3 \
or ln.to_s =~@md.lv4 \
or ln.to_s =~@md.lv5 \
or ln.to_s =~@md.lv6)
ocnh+=1
if ln==1 \
or ln=~@md.lv1; ocnh1+=1 #heading
node1="1:#{ocnh1};#{ocn}"
node,ocn_sp,parent=node1,"h#{ocnh}",0 #FIX
elsif ln==2 \
or ln=~@md.lv2; ocnh2+=1
node2="2:#{ocnh2};#{ocn}"
node,ocn_sp,parent=node2,"h#{ocnh}",node1
elsif ln==3 \
or ln=~@md.lv3; ocnh3+=1
node3="3:#{ocnh3};#{ocn}"
node,ocn_sp,parent=node3,"h#{ocnh}",node2
elsif ln==4 \
or ln=~@md.lv4; ocnh4+=1
node4="4:#{ocnh4};#{ocn}"
node,ocn_sp,parent=node4,"h#{ocnh}",node3
elsif ln==5 \
or ln=~@md.lv5; ocnh5+=1
node5="5:#{ocnh5};#{ocn}"
node,ocn_sp,parent=node5,"h#{ocnh}",node4
elsif ln==6 \
or ln=~@md.lv6; ocnh6+=1
node6="6:#{ocnh6};#{ocn}"
node,ocn_sp,parent=node6,"h#{ocnh}",node5
end
else
ocno+=1
if dob.is=='table'
ocnt+=1
ocn_sp,parent="t#{ocnt}",node
elsif dob.is=='code'
ocnc+=1
ocn_sp,parent="c#{ocnc}",node
elsif dob.is=~/^(?:group|alt|verse)/
ocng+=1 #group, poem
ocn_sp,parent="g#{ocng}",node
elsif dob.is=~/image|#{Mx[:lnk_o]}\S+?\.(?:png|jpg|gif)\s+/m
ocni+=1
ocn_sp,parent="i#{ocni}",node
else ocnp+=1 #paragraph
ocn_sp,parent="p#{ocnp}",node
end
end
if dob.is=='heading'
dob.ln,dob.node,dob.ocn,dob.odv,dob.osp,dob.parent=ln,node,ocn,ocn_dv,ocn_sp,parent
else
unless dob.of=~/meta|comment|layout/
dob.ocn,dob.odv,dob.osp,dob.parent=ocn,ocn_dv,ocn_sp,parent
end
end
else ocnu+=1
dob.obj.gsub!(/#{Mx[:fa_o]}~##{Mx[:fa_c]}/,'') if dob.obj
ocn_dv,ocn_sp="u#{ocnu}","u#{ocnu}"
dob.ocn,dob.odv,dob.osp=ocn,ocn_dv,ocn_sp
end
h
elsif dob.obj=~/#{Mx[:pa_non_object_no_heading]}/
dob.obj.gsub!(/#{Mx[:pa_non_object_no_heading]}/,'')
if dob.is=='para'
h={:obj=>dob.obj,:ocn_=>false,:ocn=>nil}
dob=SiSU_document_structure::Object_para.new.paragraph(h,dob)
elsif dob.is=='heading'
h={:obj=>dob.obj,:ocn_=>false,:ocn=>nil,:toc_=>true}
dob=SiSU_document_structure::Object_heading.new.heading(h,dob)
end
elsif dob.obj=~/#{Mx[:pa_non_object_dummy_heading]}/
dob.obj.gsub!(/#{Mx[:pa_non_object_dummy_heading]}/,'')
if dob.is=='para'
h={:obj=>dob.obj,:ocn_=>false,:ocn=>nil}
dob=SiSU_document_structure::Object_para.new.paragraph(h,dob)
elsif dob.is=='heading'
h={:obj=>dob.obj,:ocn_=>false,:ocn=>nil,:toc_=>false}
dob=SiSU_document_structure::Object_heading.new.heading(h,dob)
end
else dob
end
dob.obj.gsub!(/\n\n/,"\n") if dob.is =~/(?:code|verse|alt|group)/ #newlines taken out
@o_array << dob
end
@o_array
end
end
class XML
def initialize(md,data)
@data,@md=data,md
end
def dom
@s=['0',
'A',
'B',
'C',
'1',
'2',
'3'
]
@sp=' '
tuned_file=structure_build
tuned_file
end
def structure_build
data=@data
tuned_file=[]
hs=[0,false,false,false]
t={:lv =>@s[0],:status =>'open'}
tuned_file << tags(t)
if @md.cmd =~/V/
puts "\nXML sisu structure outline --->\n"
puts "<#{@s[0]}>"
end
data.each_with_index do |o,i|
if o.is =~/^heading/
case o.ln
when 1
tuned_file << tag_close(o.ln,hs)
tuned_file << tag_open(o,@s)
if @md.cmd =~/V/
puts_tag_close(o.ln,hs)
puts_tag_open(o,@s)
end
hs=[1,true,false,false]
when 2
tuned_file << tag_close(o.ln,hs)
tuned_file << tag_open(o,@s)
if @md.cmd =~/V/
puts_tag_close(o.ln,hs)
puts_tag_open(o,@s)
end
hs=[2,true,true,false]
when 3
tuned_file << tag_close(o.ln,hs)
tuned_file << tag_open(o,@s)
if @md.cmd =~/V/
puts_tag_close(o.ln,hs)
puts_tag_open(o,@s)
end
hs=[3,true,true,true]
when 4
tuned_file << tag_close(o.ln,hs)
tuned_file << tag_open(o,@s)
if @md.cmd =~/V/
puts_tag_close(o.ln,hs)
puts_tag_open(o,@s)
end
hs[0]=4
when 5
tuned_file << tag_close(o.ln,hs)
tuned_file << tag_open(o,@s)
if @md.cmd =~/V/
puts_tag_close(o.ln,hs)
puts_tag_open(o,@s)
end
hs[0]=5
when 6
tuned_file << tag_close(o.ln,hs)
tuned_file << tag_open(o,@s)
if @md.cmd =~/V/
puts_tag_close(o.ln,hs)
puts_tag_open(o,@s)
end
hs[0]=6
end
end
tuned_file << o
end
puts_tag_close(0,hs) if @md.cmd =~/V/
tuned_file << tag_close(0,hs)
tuned_file.flatten!
tuned_file
end
def tags(o)
tag=if o[:status]=='open'
%{<#{o[:lv]} id="#{o[:node]}">}
else "#{o[:lv]}>"
end
ln=case o[:lv]
when 'A'; 1
when 'B'; 2
when 'C'; 3
when '1'; 4
when '2'; 5
when '3'; 6
when '4'; 7
when '5'; 8
when '6'; 9
end
h={:tag=>tag,:node=>o[:node],:lv =>o[:lv],:ln =>ln,:status =>o[:status]}
SiSU_document_structure::Object_structure.new.xml_dom(h) #downstream code utilise else ignore like comments
end
def tag_open(o,tag)
t={:lv =>tag[o.ln],:node =>o.node,:status =>'open'}
t_o=tags(t)
t_o
end
def tag_close(lev,hs)
ary=[]
case hs[0]
when 1
if (lev <= 1) and hs[1]
t={:lv =>@s[1],:status =>'close'}
ary << tags(t)
end
if (lev==0)
t={:lv =>@s[0],:status =>'close'}
ary << tags(t)
end
when 2
if (lev <= 2) and hs[2]
t={:lv =>@s[2],:status =>'close'}
ary << tags(t)
end
if (lev <= 1) and hs[1]
t={:lv =>@s[1],:status =>'close'}
ary << tags(t)
end
if (lev==0)
t={:lv =>@s[0],:status =>'close'}
ary << tags(t)
end
when 3
if (lev <= 3) and hs[3]
t={:lv =>@s[3],:status =>'close'}
ary << tags(t)
end
if (lev <= 2) and hs[2]
t={:lv =>@s[2],:status =>'close'}
ary << tags(t)
end
if (lev <= 1) and hs[1]
t={:lv =>@s[1],:status =>'close'}
ary << tags(t)
end
if (lev==0)
t={:lv =>@s[0],:status =>'close'}
ary << tags(t)
end
when 4
if (lev <= 4)
t={:lv =>@s[4],:status =>'close'}
ary << tags(t)
end
if (lev <= 3) and hs[3]
t={:lv =>@s[3],:status =>'close'}
ary << tags(t)
end
if (lev <= 2) and hs[2]
t={:lv =>@s[2],:status =>'close'}
ary << tags(t)
end
if (lev <= 1) and hs[1]
t={:lv =>@s[1],:status =>'close'}
ary << tags(t)
end
if (lev==0)
t={:lv =>@s[0],:status =>'close'}
ary << tags(t)
end
when 5
if (lev <= 5)
t={:lv =>@s[5],:status =>'close'}
ary << tags(t)
end
if (lev <= 4)
t={:lv =>@s[4],:status =>'close'}
ary << tags(t)
end
if (lev <= 3) and hs[3]
t={:lv =>@s[3],:status =>'close'}
ary << tags(t)
end
if (lev <= 2) and hs[2]
t={:lv =>@s[2],:status =>'close'}
ary << tags(t)
end
if (lev <= 1) and hs[1]
t={:lv =>@s[1],:status =>'close'}
ary << tags(t)
end
if (lev==0)
t={:lv =>@s[0],:status =>'close'}
ary << tags(t)
end
when 6
if (lev <= 6)
t={:lv =>@s[6],:status =>'close'}
ary << tags(t)
end
if (lev <= 5)
t={:lv =>@s[5],:status =>'close'}
ary << tags(t)
end
if (lev <= 4)
t={:lv =>@s[4],:status =>'close'}
ary << tags(t)
end
if (lev <= 3) and hs[3]
t={:lv =>@s[3],:status =>'close'}
ary << tags(t)
end
if (lev <= 2) and hs[2]
t={:lv =>@s[2],:status =>'close'}
ary << tags(t)
end
if (lev <= 1) and hs[1]
t={:lv =>@s[1],:status =>'close'}
ary << tags(t)
end
if (lev==0)
t={:lv =>@s[0],:status =>'close'}
ary << tags(t)
end
end
ary
end
def puts_tag_open(o,tag)
puts %{#{@sp*o.ln}<#{tag[o.ln]} id="#{o.node}">}
end
def puts_tag_close(lev,hs)
case hs[0]
when 1
puts "#{@sp*1}#{@s[1]}>" if (lev <= 1) and hs[1]
puts "#{@s[0]}>" if (lev==0)
when 2
puts "#{@sp*2}#{@s[2]}>" if (lev <= 2) and hs[2]
puts "#{@sp*1}#{@s[1]}>" if (lev <= 1) and hs[1]
puts "#{@s[0]}>" if (lev==0)
when 3
puts "#{@sp*3}#{@s[3]}>" if (lev <= 3) and hs[3]
puts "#{@sp*2}#{@s[2]}>" if (lev <= 2) and hs[2]
puts "#{@sp*1}#{@s[1]}>" if (lev <= 1) and hs[1]
puts "#{@s[0]}>" if (lev==0)
when 4
puts "#{@sp*4}#{@s[4]}>" if (lev <= 4)
puts "#{@sp*3}#{@s[3]}>" if (lev <= 3) and hs[3]
puts "#{@sp*2}#{@s[2]}>" if (lev <= 2) and hs[2]
puts "#{@sp*1}#{@s[1]}>" if (lev <= 1) and hs[1]
puts "#{@s[0]}>" if (lev==0)
when 5
puts "#{@sp*5}#{@s[5]}>" if (lev <= 5)
puts "#{@sp*4}#{@s[4]}>" if (lev <= 4)
puts "#{@sp*3}#{@s[3]}>" if (lev <= 3) and hs[3]
puts "#{@sp*2}#{@s[2]}>" if (lev <= 2) and hs[2]
puts "#{@sp*1}#{@s[1]}>" if (lev <= 1) and hs[1]
puts "#{@s[0]}>" if (lev==0)
when 6
puts "#{@sp*6}#{@s[6]}>" if (lev <= 6)
puts "#{@sp*5}#{@s[5]}>" if (lev <= 5)
puts "#{@sp*4}#{@s[4]}>" if (lev <= 4)
puts "#{@sp*3}#{@s[3]}>" if (lev <= 3) and hs[3]
puts "#{@sp*2}#{@s[2]}>" if (lev <= 2) and hs[2]
puts "#{@sp*1}#{@s[1]}>" if (lev <= 1) and hs[1]
puts "#{@s[0]}>" if (lev==0)
end
end
end
end
__END__