From ac654580ff2d245402eb2bca3d8685a97dd5d1fb Mon Sep 17 00:00:00 2001 From: Ralph Amissah Date: Thu, 19 Jun 2014 19:36:14 -0400 Subject: v6: ao, syntax, introduce tics quotes markup (blockquote equivalent) --- lib/sisu/v6/ao_doc_objects.rb | 22 +++++++-- lib/sisu/v6/ao_doc_str.rb | 104 +++++++++++++++++++++++++---------------- lib/sisu/v6/ao_misc_arrange.rb | 30 ++++++++++-- lib/sisu/v6/ao_syntax.rb | 1 + 4 files changed, 108 insertions(+), 49 deletions(-) (limited to 'lib') diff --git a/lib/sisu/v6/ao_doc_objects.rb b/lib/sisu/v6/ao_doc_objects.rb index e1a14da1..ee229200 100644 --- a/lib/sisu/v6/ao_doc_objects.rb +++ b/lib/sisu/v6/ao_doc_objects.rb @@ -184,10 +184,10 @@ module SiSU_AO_DocumentStructure end end class ObjectPara - attr_accessor :obj,:is,:tags,:of,:name,:idx,:bullet_,:indent,:hang,:ocn,:odv,:osp,:parent,:note_,:image_,:ocn_,:digest,:tmp + attr_accessor :obj,:is,:tags,:of,:name,:idx,:quote_,:bullet_,:indent,:hang,:ocn,:odv,:osp,:parent,:note_,:image_,:ocn_,:digest,:tmp def initialize @of=:para - @is=@obj=@name=@idx=@bullet_=@indent=@hang=@size=@ocn=@odv=@osp=@parent=@note_=@image_=@ocn_=@digest=@tmp=nil + @is=@obj=@name=@idx=@quote_=@bullet_=@indent=@hang=@size=@ocn=@odv=@osp=@parent=@note_=@image_=@ocn_=@digest=@tmp=nil @tags=[] end def paragraph(h,o=nil) @@ -204,6 +204,7 @@ module SiSU_AO_DocumentStructure indent= h[:indent].to_s || ((defined? o.indent) ? o.indent.to_s : nil) #Integer, indent level hang= h[:hang].to_s || ((defined? o.hang) ? o.hang.to_s : nil) #Integer, hanging indent level bullet_=h[:bullet_] || ((defined? o.bullet_) ? o.bullet_ : false) #Bool, bulleted? + quote_= h[:quote_] || ((defined? o.quote_) ? o.quote_ : false) #Bool, quote (blockquote)? note_= h[:note_] || ((defined? o.note_) ? o.note_ : false) #Bool, endnotes/footnotes? (processing optimization) image_= h[:image_] || ((defined? o.image_) ? o.image_ : false) #Bool, images? (processing optimization) ocn_=if h[:ocn_].nil? then ((defined? o.ocn_) ? o.ocn_ : true) #Bool? no ocn, non-substantive content, do not include in toc #consider @@ -211,7 +212,7 @@ module SiSU_AO_DocumentStructure end digest= h[:digest] || ((defined? o.digest) ? o.digest : nil) #hash digests, sha512, sha256 or md5 tmp= h[:tmp] || ((defined? o.tmp) ? o.tmp : nil) #available for processing, empty after use - @of,@is,@name,@tags,@obj,@indent,@hang,@bullet_,@idx,@ocn,@odv,@osp,@parent,@image_,@note_,@ocn_,@digest,@tmp=of,is,name,tags,obj,indent,hang,bullet_,idx,ocn,odv,osp,parent,image_,note_,ocn_,digest,tmp + @of,@is,@name,@tags,@obj,@indent,@hang,@bullet_,@quote_,@idx,@ocn,@odv,@osp,@parent,@image_,@note_,@ocn_,@digest,@tmp=of,is,name,tags,obj,indent,hang,bullet_,quote_,idx,ocn,odv,osp,parent,image_,note_,ocn_,digest,tmp self end def docinfo(h,o=nil) @@ -476,10 +477,10 @@ module SiSU_AO_DocumentStructure end end class ObjectLayout - attr_accessor :obj,:is,:of,:from,:tmp + attr_accessor :obj,:sym,:attr,:is,:of,:from,:tmp,:num def initialize @of=:layout - @is=@obj=@from=@tmp=nil + @is=@obj=@from=@tmp=@num=nil end def break(h,f=nil) #decide how to deal with of= @of #Symbol, classification - group @@ -498,6 +499,17 @@ module SiSU_AO_DocumentStructure @of,@is,@obj,@tmp=of,is,obj,tmp self end + def open_close(h,o=nil) #useful for poem & quote + of= @of #Symbol, classification - group + is= :open_close_tags #Symbol, classification - specific type + obj= h[:obj] || ((defined? o.obj) ? o.obj : nil) #String, text content + sym= h[:sym] || ((defined? o.sym) ? o.sym : nil) #Symbol tag_open, tag_close + attr= h[:attr] || ((defined? o.attr) ? o.attr : nil) #String, text content + tmp= h[:tmp] || ((defined? o.tmp) ? o.tmp : nil) #available for processing, empty after use + num= h[:num] || ((defined? o.num) ? o.num : nil) + @of,@is,@obj,@sym,@attr,@tmp,@num=of,is,obj,sym,attr,tmp,num + self + end end class ObjectComment attr_accessor :obj,:is,:of,:tmp diff --git a/lib/sisu/v6/ao_doc_str.rb b/lib/sisu/v6/ao_doc_str.rb index cd4f62e8..7f2815d8 100644 --- a/lib/sisu/v6/ao_doc_str.rb +++ b/lib/sisu/v6/ao_doc_str.rb @@ -71,6 +71,7 @@ module SiSU_AO_DocumentStructureExtract box: :off, group: :off, alt: :off, + quote: :off, table: :off, table_to: :off, } @@ -89,6 +90,7 @@ module SiSU_AO_DocumentStructureExtract box: :off, group: :off, alt: :off, + quote: :off, table: :off, table_to: :off, } @@ -123,6 +125,11 @@ module SiSU_AO_DocumentStructureExtract ? true : false end + def quotes? + @@flag[:quote]==:open \ + ? true + : false + end def hang_and_indent_test(str) hang_indent=if str=~/^_([1-9])[^_]/ [$1,$1] @@ -236,6 +243,7 @@ module SiSU_AO_DocumentStructureExtract box: 0, group: 0, alt: 0, + quote: 0, table: 0, } @metadata={} @@ -260,7 +268,7 @@ module SiSU_AO_DocumentStructureExtract end t_o=t_o.gsub(/(?:\n\s*\n)+/m,"\n") if @@flag[:code]==:off if t_o !~/^(?:code(?:\.[a-z][0-9a-z_]+)?|box(?:\.[a-z_]+)?|poem|alt|group|block)\{|^\}(?:code|poem|alt|group|block)|^(?:table\{|\{table)[ ~]/ \ - and t_o !~/^```[ ]+(?:code(?:\.[a-z][0-9a-z_]+)?|box(?:\.[a-z_]+)?|poem|alt|group|block|table)|^```(?:\s+[~-][#]|\s+\~\{.+?\}\~)?\s*$/ \ + and t_o !~/^```[ ]+(?:code(?:\.[a-z][0-9a-z_]+)?|box(?:\.[a-z_]+)?|poem|alt|group|block|table)|^```(?:\s+[~-][#]|\s+\~\{.+?\}\~)?\s*$|^`:quote_(?:open|close)`/ \ and @@flag[:code]==:off \ and @@flag[:poem]==:off \ and @@flag[:group]==:off \ @@ -370,7 +378,7 @@ module SiSU_AO_DocumentStructureExtract obj << ' ~#' end end - h={ bullet_: bullet, hang: hang, indent: indent, obj: obj, idx: idx, note_: note, image_: image, tags: tags } + h={ bullet_: bullet, hang: hang, indent: indent, obj: obj, idx: idx, note_: note, image_: image, tags: tags, quote: quotes? } SiSU_AO_DocumentStructure::ObjectPara.new.paragraph(h) end else nil @@ -393,7 +401,7 @@ module SiSU_AO_DocumentStructureExtract obj << ' ~#' end end - h={ hang: hang, indent: indent, obj: obj, idx: idx, note_: note, image_: image, tags: tags } + h={ hang: hang, indent: indent, obj: obj, idx: idx, note_: note, image_: image, tags: tags, quote: quotes? } SiSU_AO_DocumentStructure::ObjectPara.new.paragraph(h) end else nil @@ -417,7 +425,7 @@ module SiSU_AO_DocumentStructureExtract end end unless obj=~/\A\s*\Z/m - h={ bullet_: false, indent: 0, hang: 0, obj: obj, idx: idx, note_: note, image_: image, tags: tags } + h={ bullet_: false, indent: 0, hang: 0, obj: obj, idx: idx, note_: note, image_: image, tags: tags, quote: quotes? } SiSU_AO_DocumentStructure::ObjectPara.new.paragraph(h) end end @@ -450,8 +458,8 @@ module SiSU_AO_DocumentStructureExtract else @@flag[:poem] #error end @num_id[:poem] +=1 - h={ obj: "poem start #{@num_id[:poem]}" } - t_o=SiSU_AO_DocumentStructure::ObjectComment.new.comment(h) + h={ obj: '', sym: :poem_open, num: @num_id[:poem] } + t_o=SiSU_AO_DocumentStructure::ObjectLayout.new.open_close(h) tuned_file << t_o elsif t_o =~/^(?:box(?:\.[a-z_]+)?\{|```[ ]+box(?:\.[a-z_]+)?)/ @@flag[:box]=case t_o @@ -460,8 +468,8 @@ module SiSU_AO_DocumentStructureExtract else @@flag[:box] #error end @num_id[:box] +=1 - h={ obj: "box text start #{@num_id[:box]}" } - t_o=SiSU_AO_DocumentStructure::ObjectComment.new.comment(h) + h={ obj: '', sym: :box_open, num: @num_id[:box] } + t_o=SiSU_AO_DocumentStructure::ObjectLayout.new.open_close(h) tuned_file << t_o elsif t_o =~/^(?:group\{|```[ ]+group)/ @@flag[:group]=case t_o @@ -470,8 +478,8 @@ module SiSU_AO_DocumentStructureExtract else @@flag[:group] #error end @num_id[:group] +=1 - h={ obj: "group text start #{@num_id[:group]}" } - t_o=SiSU_AO_DocumentStructure::ObjectComment.new.comment(h) + h={ obj: '', sym: :group_open, num: @num_id[:group] } + t_o=SiSU_AO_DocumentStructure::ObjectLayout.new.open_close(h) tuned_file << t_o elsif t_o =~/^(?:block\{|```[ ]+block)/ @@flag[:block]=case t_o @@ -480,8 +488,8 @@ module SiSU_AO_DocumentStructureExtract else @@flag[:block] #error end @num_id[:block] +=1 - h={ obj: "block text start #{@num_id[:block]}" } - t_o=SiSU_AO_DocumentStructure::ObjectComment.new.comment(h) + h={ obj: '', sym: :block_open, num: @num_id[:block] } + t_o=SiSU_AO_DocumentStructure::ObjectLayout.new.open_close(h) tuned_file << t_o elsif t_o =~/^(?:alt\{|```[ ]+alt)/ @@flag[:alt]=case t_o @@ -490,14 +498,20 @@ module SiSU_AO_DocumentStructureExtract else @@flag[:alt] #error end @num_id[:alt] +=1 - h={ obj: "alt text start #{@num_id[:alt]}" } - t_o=SiSU_AO_DocumentStructure::ObjectComment.new.comment(h) + h={ obj: '', sym: :alt_open, num: @num_id[:alt] } + t_o=SiSU_AO_DocumentStructure::ObjectLayout.new.open_close(h) tuned_file << t_o + elsif t_o =~/^`:quote_open`/ + @@flag[:quote]=:open + @num_id[:quote] +=1 + h={ obj: '', sym: :quote_open, num: @num_id[:quote] } + t_o=SiSU_AO_DocumentStructure::ObjectLayout.new.open_close(h) + #tuned_file << t_o #% find second source, entered twice, should be once so closed off here elsif t_o =~/^(?:table\{|```[ ]+table|\{table)[ ~]/ @num_id[:table] +=1 - h={ obj: "table start #{@num_id[:table]}" } - ins=SiSU_AO_DocumentStructure::ObjectComment.new.comment(h) - tuned_file << ins + h={ obj: '', sym: :table_open, num: @num_id[:table] } + ins_o=SiSU_AO_DocumentStructure::ObjectLayout.new.open_close(h) + tuned_file << ins_o if t_o=~/^table\{(?:~h)?\s+/ @@flag[:table]=:curls @rows='' @@ -552,8 +566,8 @@ module SiSU_AO_DocumentStructureExtract h={ head_: hd, cols: cols, widths: col, obj: rows, idx: idx, tags: tags, num: @num_id[:table] } t_o=SiSU_AO_DocumentStructure::ObjectTable.new.table(h) unless h.nil? tuned_file << t_o - h={ obj: "table end #{@num_id[:table]}" } - t_o=SiSU_AO_DocumentStructure::ObjectComment.new.comment(h) + h={ obj: '', sym: :table_close, num: @num_id[:table] } + t_o=SiSU_AO_DocumentStructure::ObjectLayout.new.open_close(h) t_o elsif t_o=~/^```[ ]+table(?:~h)?\s+/ m1,m2,hd=nil,nil,nil @@ -575,8 +589,8 @@ module SiSU_AO_DocumentStructureExtract h={ head_: hd, cols: col.length, widths: col, obj: rows, idx: idx, tags: tags, num: @num_id[:table] } t_o=SiSU_AO_DocumentStructure::ObjectTable.new.table(h) unless h.nil? tuned_file << t_o - h={ obj: "table end #{@num_id[:table]}" } - t_o=SiSU_AO_DocumentStructure::ObjectComment.new.comment(h) + h={ obj: '', sym: :table_close, num: @num_id[:table] } + t_o=SiSU_AO_DocumentStructure::ObjectLayout.new.open_close(h) t_o elsif t_o=~/^\{table(?:~h)?\s+/ m1,m2,hd=nil,nil,nil @@ -598,8 +612,8 @@ module SiSU_AO_DocumentStructureExtract h={ head_: hd, cols: col.length, widths: col, obj: rows, idx: idx, tags: tags, num: @num_id[:table] } t_o=SiSU_AO_DocumentStructure::ObjectTable.new.table(h) unless h.nil? tuned_file << t_o - h={ obj: "table end #{@num_id[:table]}" } - t_o=SiSU_AO_DocumentStructure::ObjectComment.new.comment(h) + h={ obj: '', sym: :table_close, num: @num_id[:table] } + t_o=SiSU_AO_DocumentStructure::ObjectLayout.new.open_close(h) t_o end end @@ -616,13 +630,13 @@ module SiSU_AO_DocumentStructureExtract t_o=SiSU_AO_DocumentStructure::ObjectTable.new.table(@h) tuned_file << t_o @h,@rows=nil,'' - h={ obj: "table end #{@num_id[:table]}" } - t_o=SiSU_AO_DocumentStructure::ObjectComment.new.comment(h) + h={ obj: '', sym: :table_close, num: @num_id[:table] } + t_o=SiSU_AO_DocumentStructure::ObjectLayout.new.open_close(h) t_o else if t_o.is_a?(String) \ and t_o !~/^(?:table\{|```[ ]+table)/ - t_o=t_o.gsub(/^\n+/m,''). #check added for ruby 1.9.2 not needed in 1.8 series (tested in v2) + t_o=t_o.gsub(/^\n+/m,''). gsub(/\n+/m,"#{Mx[:tc_p]}") @rows += t_o + Mx[:tc_c] end @@ -641,8 +655,8 @@ module SiSU_AO_DocumentStructureExtract t_o=SiSU_AO_DocumentStructure::ObjectBlockTxt.new.code(h) @tuned_code=[] tuned_file << t_o - h={ obj: "code block end #{@num_id[:code_block]}" } - t_o=SiSU_AO_DocumentStructure::ObjectComment.new.comment(h) + h={ obj: '', sym: :code_close, num: @num_id[:code_block] } + t_o=SiSU_AO_DocumentStructure::ObjectLayout.new.open_close(h) end if (@@flag[:code]==:curls or @@flag[:code]==:tics) \ and t_o.is_a?(String) @@ -657,12 +671,13 @@ module SiSU_AO_DocumentStructureExtract or (@@flag[:box]==:curls or @@flag[:box]==:tics) \ or (@@flag[:group]==:curls or @@flag[:group]==:tics) \ or (@@flag[:block]==:curls or @@flag[:block]==:tics) \ - or (@@flag[:alt]==:curls or @@flag[:alt]==:tics) + or (@@flag[:alt]==:curls or @@flag[:alt]==:tics) \ + or (@@flag[:quote]==:open and t_o =~/`:quote_close`/m) #not if (@@flag[:poem]==:curls and t_o =~/^\}poem/) \ or (@@flag[:poem]==:tics and t_o =~/^```(?:\s+[~-][#]|\s+\~\{.+?\}\~)?\s*$/) @@flag[:poem]=:off - h={ obj: "poem end #{@num_id[:poem]}" } - t_o=SiSU_AO_DocumentStructure::ObjectComment.new.comment(h) + h={ obj: '', sym: :poem_close, num: @num_id[:poem] } + t_o=SiSU_AO_DocumentStructure::ObjectLayout.new.open_close(h) elsif (@@flag[:box]==:curls and t_o =~/^\}box/) \ or (@@flag[:box]==:tics and t_o =~/^```(?:\s+[~-][#]|\s+\~\{.+?\}\~)?\s*$/) @@flag[:box]=:off @@ -671,8 +686,8 @@ module SiSU_AO_DocumentStructureExtract @tuned_block=[] t_o=SiSU_AO_DocumentStructure::ObjectBlockTxt.new.box(h) tuned_file << t_o - h={ obj: "box text end #{@num_id[:box]}" } - t_o=SiSU_AO_DocumentStructure::ObjectComment.new.comment(h) + h={ obj: '', sym: :box_close, num: @num_id[:box] } + t_o=SiSU_AO_DocumentStructure::ObjectLayout.new.open_close(h) elsif (@@flag[:group]==:curls and t_o =~/^\}group/) \ or (@@flag[:group]==:tics and t_o =~/^```(?:\s+[~-][#]|\s+\~\{.+?\}\~)?\s*$/) @@flag[:group]=:off @@ -681,8 +696,8 @@ module SiSU_AO_DocumentStructureExtract @tuned_block=[] t_o=SiSU_AO_DocumentStructure::ObjectBlockTxt.new.group(h) tuned_file << t_o - h={ obj: "group text end #{@num_id[:group]}" } - t_o=SiSU_AO_DocumentStructure::ObjectComment.new.comment(h) + h={ obj: '', sym: :group_close, num: @num_id[:group] } + t_o=SiSU_AO_DocumentStructure::ObjectLayout.new.open_close(h) elsif (@@flag[:block]==:curls and t_o =~/^\}block/) \ or (@@flag[:block]==:tics and t_o =~/^```(?:\s+[~-][#]|\s+\~\{.+?\}\~)?\s*$/) @@flag[:block]=:off @@ -691,8 +706,8 @@ module SiSU_AO_DocumentStructureExtract @tuned_block=[] t_o=SiSU_AO_DocumentStructure::ObjectBlockTxt.new.block(h) tuned_file << t_o - h={ obj: "block text end #{@num_id[:block]}" } - t_o=SiSU_AO_DocumentStructure::ObjectComment.new.comment(h) + h={ obj: '', sym: :block_close, num: @num_id[:block] } + t_o=SiSU_AO_DocumentStructure::ObjectLayout.new.open_close(h) elsif (@@flag[:alt]==:curls and t_o =~/^\}alt/) \ or (@@flag[:alt]==:tics and t_o =~/^```(?:\s+[~-][#]|\s+\~\{.+?\}\~)?\s*$/) @@flag[:alt]=:off @@ -701,8 +716,16 @@ module SiSU_AO_DocumentStructureExtract t_o=SiSU_AO_DocumentStructure::ObjectBlockTxt.new.alt(h) @tuned_block=[] tuned_file << t_o - h={ obj: "alt text end #{@num_id[:alt]}" } - t_o=SiSU_AO_DocumentStructure::ObjectComment.new.comment(h) + h={ obj: '', sym: :alt_close, num: @num_id[:alt] } + t_o=SiSU_AO_DocumentStructure::ObjectLayout.new.open_close(h) + elsif @@flag[:quote]==:open and t_o =~/`:quote_close`/m + @@flag[:quote]=:off + h={ obj: '', sym: :quote_close, num: @num_id[:quote] } + t_o=SiSU_AO_DocumentStructure::ObjectLayout.new.open_close(h) + elsif @@flag[:quote]==:open + t_o,tags=extract_tags(t_o) + h={ indent: 1, obj: t_o, idx: idx, note_: note, image_: image, tags: tags, quote: quotes? } + SiSU_AO_DocumentStructure::ObjectPara.new.paragraph(h) end if (@@flag[:poem]==:curls or @@flag[:poem]==:tics \ or @@flag[:group]==:curls or @@flag[:group]==:tics \ @@ -732,7 +755,8 @@ module SiSU_AO_DocumentStructureExtract if @@flag[:poem]==:curls or @@flag[:poem]==:tics \ or @@flag[:box]==:curls or @@flag[:box]==:tics \ or @@flag[:group]==:curls or @@flag[:group]==:tics \ - or @@flag[:alt]==:curls or @@flag[:alt]==:tics + or @@flag[:alt]==:curls or @@flag[:alt]==:tics \ + or (@@flag[:quote]==:open and t_o =~/`:quote_close`/m) if t_o.is_a?(String) t_o=t_o.gsub(/\n/m,"#{Mx[:br_nl]}"). gsub(/[ ][ ]/m,"#{Mx[:nbsp]*2}"). diff --git a/lib/sisu/v6/ao_misc_arrange.rb b/lib/sisu/v6/ao_misc_arrange.rb index 9279f888..de32f560 100644 --- a/lib/sisu/v6/ao_misc_arrange.rb +++ b/lib/sisu/v6/ao_misc_arrange.rb @@ -115,6 +115,22 @@ module SiSU_AO_MiscArrangeText gsub(/```\s*/m,''). strip end + def ticks_quote(para) + @flag=:quote_open + text=para + para=[] + if text =~ /```[ ]+quote/m + para << '`:quote_open`' + text=text.gsub(/```[ ]+quote/m,'') + end + text=text.gsub(/(?:\n|\A)([^`=\n]+)/m,'_1 \1') #not a perfect match for book index \n={ + para << text.gsub(/```/m,'') + if text =~/```/m + @flag=:quote_close + para << '`:quote_close`' + end + para + end def curly_braces(para) block_open,block_close,text=nil,nil,nil para=if para =~/\A(?:code(?:\.[a-z][0-9a-z_]+)?|box(?:\.[a-z_]+)?|poem|alt|group|block|table)\{ .+?\n.+?\n\}(?:code|box|poem|alt|group|block|table)(?: [~-][#])?\s*\Z/m @@ -141,7 +157,11 @@ module SiSU_AO_MiscArrangeText end para end - para=if para =~/\A```[ ]+(?:code(?:\.[a-z][0-9a-z_]+)?|box(?:\.[a-z_]+)?|poem|alt|group|block|table).*?\n.*?\Z/m \ + para=if (para =~/\A```[ ]+quote/m \ + and @flag !=:open) \ + or @flag==:quote_open + ticks_quote(para) + elsif para =~/\A```[ ]+(?:code(?:\.[a-z][0-9a-z_]+)?|box(?:\.[a-z_]+)?|poem|alt|group|block|table).*?\n.*?\Z/m \ or @flag==:open ticks(para) elsif para =~/```/m @@ -149,9 +169,11 @@ module SiSU_AO_MiscArrangeText else para end - para=(para =~/^(?:code(?:\.[a-z][0-9a-z_]+)?|box(?:\.[a-z_]+)?|poem|alt|group|block|table)\{|^\}(?:code|poem|alt|group|block|table)/m) \ - ? curly_braces(para) - : para + para=if para =~/^(?:code(?:\.[a-z][0-9a-z_]+)?|box(?:\.[a-z_]+)?|poem|alt|group|block|table)\{|^\}(?:code|box|poem|alt|group|block|table)/m + curly_braces(para) + else + para + end end def prepare_text data=@data diff --git a/lib/sisu/v6/ao_syntax.rb b/lib/sisu/v6/ao_syntax.rb index b30847a8..68720aca 100644 --- a/lib/sisu/v6/ao_syntax.rb +++ b/lib/sisu/v6/ao_syntax.rb @@ -163,6 +163,7 @@ module SiSU_AO_Syntax && dob.is !=:heading \ && dob.is !=:heading_insert \ && dob.is !=:code \ + && dob.is !=:layout \ && dob.is !=:comment word=dob.obj.scan(@line_scan_ital) word=word.flatten.compact -- cgit v1.2.3