From: kjana@... (YANAGAWA Kazuhisa) Date: 1998-12-21T23:10:01+09:00 Subject: [ruby-list:11397] fold.rb ちょっとしたスクリプトを書いてみました.割と使えると思うんで,公表して みようかな,と. * テキストの折り畳みをします. * <- こういう箇条書やプリフィクスがついた文章もそれなりに扱えるつ もりです. # filladapt.el 並に便利に使えるといいな,と. * はなはだいい加減な禁則処理もついてます. # ちなみに禁則用の正規表現は JISX-0208 で定義された文字を EUC か # SJIS で表現し,正しく e/s を振ったものでなければなりません. * 日本語 EUC か ShiftJIS が入力になると安易に仮定しているため違う ものが入ってくるとわやになります. * パラグラフの区切りは空行か箇条書のプリフィクスがついている行のみ で,インデントの変化なんかは別に見ていません. # 簡単に直せると思うけど. * プリフィクスつきの箇条書はうまく扱えません. # * こんな感じの # 文章. * あんまり効率が良くないと思います. * コメントの英語に似た文字列が変です (^^; なにか御意見頂ければ幸い. # unexpand もつけようかと思っていたけど簡単にできなかったのでちょっと # くじけてしまった.まあぼちぼちと,ね. =========================================================================== 柳川和久 @ 東大阪市 . 大阪府 kjana@os.xaxon.ne.jp December 21, 1998 「....生き伸びられたら労災長者になれるわね」 「やっぱりあんた何にも考えてないな!」 #!/usr/local/bin/ruby class NilClass def ascii? false end end class Fixnum def ascii? (0..127).include? self end end class String def normalize strip.gsub(/\s+/, " ") end def expand(tabs = 8) if tabs.is_a? Integer tw = tabs tabs = [] for n in 0..(120/tw) tabs << tw*(n+1) end end nc = 0 ts = 0 col = 0 ostr = "" while nc < size c = self[nc] case c when ?\t while not tabs[ts] > col ts += 1 end ostr << " "*(tabs[ts]-col) col = tabs[ts] when ?\n ostr << "\n" col = 0 ts = 0 else ostr << c.chr col += 1 end nc += 1 end ostr end def join self.dup.join! end def join! n = 0 while n < size n = index("\n", n) break if n.nil? if self[n-1].ascii? or self[n+1].ascii? self[n] = " " n += 1 else self[n, 1] = "" end end self end def can_break?(n) if self[n, 1] =~ /\s/ true elsif self[n].ascii? false else i = 0 while i < n if not self[i].ascii? i += 2 else i += 1 end end if i == n true else false end end end # Regular expressions below should be given in same coding system of # expected input texts. HeadInhibitCharsHang = /^[、。,.!?:;…‥)}]】〕」』>》’”°]/e HeadInhibitChars = /^[ー〜ヽヾゝゞ〃仝々んっゃゅょぁぃぅぇぉンッャュョァィゥェォ]/e TailInhibitChars = /[({[【〔「『<《‘“]$/e def fold(len) istr = normalize ostr = "" if size < len ostr << istr else while istr.size > len n = len while n > 0 and not istr.can_break? n n -= 1 end if n == 0 n = len while n < istr.size and not istr.can_break? n n += 1 end end # not proper KINSOKU processing :-P n -= 2 while n > 1 and istr[0..n-1] =~ TailInhibitChars n -= 2 while n > 0 and istr[n..-1] =~ HeadInhibitChars n += 2 while n < istr.size and istr[n..-1] =~ HeadInhibitCharsHang ostr << istr[0..n-1]+"\n" n += 1 if istr[n] == ? # space istr = istr[n..-1] end ostr << istr end ostr end end if $0 == __FILE__ # Usage: # fold.rb [-wwidth] [file] # # Description: # Format a text file `file' in given width `width.' If `file' is omitted, # text from standarad input is formatted. If `width' is omitted, default # (70) is used. # # Output texts are pretty good than those of fold(1). Prefixed texts, # such as items in a list or comments, are properly treated, I hope :-P # # Bugs: # * Japanese-EUC/SJIS texts are expected for inputs. So ISO-2022 or # ISO-8859 texts are not properly handled. # * Nested prefixed form (like this section) is not supported. # * More efficient execution is desired. # * ....somthing more :-< DotPrefix = /^(\s*(?:\d+(?:\.|\))|\*|\+|\-)\s*)/ DupPrefix = /^(\s*(?:#)?\s*)/ w = 70 dotp = "" pref = "" pline = "" if ARGV[0] =~ /-w(\d+)/ w = $1.to_i ARGV.shift end while not eof? line = pline while not eof? gets if $_ =~ DotPrefix or $_ =~ /^\s*$/ pline = $_ break end line << $_ end case line when DotPrefix dotp = $1 pref = " "*$1.expand.size line = $' when DupPrefix dotp = "" pref = $1 line.gsub! DupPrefix, "" else dotp = "" pref = "" end line.join.fold(w-pref.size).each do |ln| if dotp == "" puts pref+ln else puts dotp+ln dotp = "" end end if pline =~ /^\s*$/ puts pline = "" end end end