textwrapがRubyにないので実装してみた。
「すぐ終わるだろ」とか思っていたら、あっという間に深夜…とほほん。
dedentとfix_sentence_endingsは未実装。間違えたトコはない思うけど、正直微妙。
もっと効率のいい書き方があったら、どなたか教えてください、
require 'strscan' class TextWrapper class << self def wrap(text, options = {}) width = options.fetch(:width, 70) initial_indent = options.fetch(:initial_indent, '') subsequent_indent = options.fetch(:subsequent_indent, '') if options.fetch(:expand_tabs, true) text = text.gsub(/\t/, ' ' * 8) end if options.fetch(:replace_whitespace, true) text = text.gsub(/\s/, ' ') end if options.fetch(:break_long_words, true) rs = [/\s{1,#{width}}/, /\S{1,#{width}}/] else rs = [/\s+/, /\S+/] end s = StringScanner.new(text.split($/).join) lines = [] indent = initial_indent words = [(s.scan(rs.reverse!.first) or s.scan(rs.reverse!.first) or '')] until s.eos? word = s.scan(rs.reverse!.first) line = indent + words.join.strip if (line + word).length > width lines << line words.clear indent = subsequent_indent end words << word end lines << indent + words.join.strip unless words.empty? end def fill(text, options = {}) self.wrap(text, options).join("\n") end end # class method attr_accessor :width attr_accessor :expand_tabs attr_accessor :replace_whitespace attr_accessor :initial_indent attr_accessor :subsequent_indent attr_accessor :break_long_words def initialize(options) @width = options.fetch(:width, 70) @expand_tabs = options.fetch(:expand_tabs, true) @replace_whitespace = options.fetch(:replace_whitespace, true) @initial_indent = options.fetch(:initial_indent, '') @subsequent_indent = options.fetch(:subsequent_indent, '') @break_long_words = options.fetch(:break_long_words, true) end def wrap(text, options ={}) self.class.wrap(text, { :width => @width, :expand_tabs => @expand_tabs, :replace_whitespace => @replace_whitespace, :initial_indent => @initial_indent, :subsequent_indent => @subsequent_indent, :break_long_words => @break_long_words }.merge(options)) end def fill(text, options = {}) self.wrap(text, options) end end
irb(main):007:0> puts TextWrapper.fill(<40)
irb(main):008:1" The wrap() method is just like fill() except that it returns
irb(main):009:1" a list of strings instead of one big string with newlines to separate
irb(main):010:1" the wrapped lines.
irb(main):011:1" EOS
The wrap() method is just like fill()
except that it returns a list of strings
instead of one big string with newlines
to separate the wrapped lines.
=> nil
追記
まじめにキーワード引数もどきを書いてみたいけど、どっかに参考になるコードはないかなぁ…