#!/usr/bin/ruby # vim: et sw=2 VER="(d4e2ac8)" ME="blfmt: " $rs=78 $quiet=false $wib=false $incl=[] $excl=[] $map=nil mode="txt" def in_list(s,list) for i in list if i.match(s) return true end end return false end def regexfix2(str) tmp=[] for t in str.scan(/(_)|(\|)|([^_\|]*)/).flatten.compact tmp.push(t) if not t.empty? end res="" while t=tmp.shift case t when "_" then res+=(tmp.empty? or tmp[0]=="|") ? '([ ."\[\]\(\)]+|$)' : '[ ."\[\]\(\)]+' when "|" then res+="|" else res+="#{t}" end end return res end def block_ok?(hdr) return false if /^#!/.match(hdr) and not $wib return false if not $incl.empty?() and not in_list(hdr,$incl) return false if in_list(hdr,$excl) return true end $ft=[] def fix_cols(tmp,col,s=nil) $err=nil c=col.length tl=0 i=0 j=0 t=0 ret="" if tmp[0].empty? if !s or $ft.empty? or tmp.length<2 $err="broken file?" return nil end tc=/\t+/.match(s)[0].length j=$ft.index(tc) if !j or j<1 $err="broken file?" return nil end t=0 i=0 while i0 and !tmp[j+1]) cs=$rs-tl if !col[i+1] or not col[i+1].start_with?("+") if l>cs $err="column #{i+1} exceed specified size" return nil end else if l>=cs $err="column #{i+1} exceed specified size" return nil end end tl+=cs ret+="\t"*t+tmp[j] t=col[i].to_i-(l/8) i+=1 j+=1 end if tl>$rs $err="row length exceeded" return nil end if tmp[j] $err="column count mismatch" return nil end $ls=row if not tmp[0].empty? return ret end def remap(row) tmp=[] $map.each { |i| tmp<0 and ti!=zf $stderr.puts ME+"line #{line}: secondary line misalign" if not $quiet err=true next end tmp=s.split(/\t+/) if tmp.length<1 $stderr.puts ME+"line #{line}: empty line inside block" if not $quiet err=true next end if tmp.length>cc $stderr.puts ME+"line #{line}: columns mismatch" if not $quiet err=true next end if zt==0 or zt!=ti if !ret=fix_cols(tmp,col,s) $stderr.puts ME+"line #{line}: "+$err if not $quiet err=true next end if ret!=s $stderr.puts ME+"line #{line}: format error" if not $quiet err=true next end else zf=zt if tmp.length>2 or s.count("\t")!=zt $stderr.puts ME+"line #{line}: format error" if not $quiet err=true next end end if /[ \t]$/.match(s) $stderr.puts ME+"line #{line}: whitespace at the end of line" if not $quiet err=true next end t=tmp.shift if / $/.match(t) $stderr.puts ME+"line #{line}: whitespace at the end of column" if not $quiet err=true next end for t in tmp if t.include?(" ") $stderr.puts ME+"line #{line}: double space detected" if not $quiet err=true break end if /^ /.match(t) $stderr.puts ME+"line #{line}: whitespace at the begining of column" if not $quiet err=true break end if / $/.match(t) $stderr.puts ME+"line #{line}: whitespace at the end of column" if not $quiet err=true break end end next end if s.start_with?("#") hdr=s next end if s.start_with?("-----") if !hdr or !fld $stderr.puts ME+"line #{line}: missing block header" if not $quiet err=true break end sep=s if block_ok?(hdr) if fld.include?(" ") $stderr.puts ME+"line #{line}: double space detected" if not $quiet err=true break end cc=fld.split(/\t+/).length $ft=[] tc=0 for t in fld.scan(/[^\t]+\t*/) n=t.count("\t")+t.count("^\t")/8 if t.start_with?("_") zt=tc u=col.pop col<] [-S ] []" exit end outfn=nil i=0 while i=ARGV.length fn=nil else fn=ARGV[i] if mode!="check" usage if i+1>=ARGV.length col=ARGV[i+1].split(",") end end sbuf=[] err=false if !fn or fn=="-" for l in $stdin err=l.include?("\r") if not err l.chop! sbuf.push(l) end else begin f=File.open(fn,"r") rescue $stderr.puts ME+"unable to open file" exit end for l in f err=l.include?("\r") if not err l.chop! sbuf.push(l) end f.close end if mode=="check" if err $stderr.puts ME+"file is not in UNIX format" if not $quiet exit(1) end if not sbuf[0].start_with?("! vim:") $stderr.puts ME+"line 1: VIM options not found" if not $quiet exit(1) end if m=/^! blrs:([0-9]+)/.match(sbuf[1]) $rs=m[1].to_i end exit(1) if p_txt_check(sbuf) exit(0) end if !outfn if mode=="csv" tmp=fn.split(".") tmp.pop if tmp.length>1 tmp.push("txt") outfn=tmp.join(".") else outfn=fn end end if mode=="txt" dbuf=p_txt(sbuf,col) end if mode=="csv" dbuf=p_csv(sbuf,col) end if outfn=="-" dbuf.each { |l| $stdout.puts l } exit end begin f=File.open(outfn,"w") rescue $stderr.puts ME+"unable to open file" exit end dbuf.each { |l| f.puts l } f.close