text-format-1.0.0/ 0000755 0001750 0001750 00000000000 11600332303 013275 5 ustar ondrej ondrej text-format-1.0.0/metaconfig 0000644 0001750 0001750 00000000000 11600332303 015322 0 ustar ondrej ondrej text-format-1.0.0/tests/ 0000755 0001750 0001750 00000000000 11600332303 014437 5 ustar ondrej ondrej text-format-1.0.0/tests/testall.rb 0000644 0001750 0001750 00000000735 11600332303 016441 0 ustar ondrej ondrej #!/usr/bin/env ruby
#--
# Ruwiki version 0.8.0
# Copyright © 2002 - 2003, Digikata and HaloStatue
# Alan Chen (alan@digikata.com)
# Austin Ziegler (ruwiki@halostatue.ca)
#
# Licensed under the same terms as Ruby.
#
# $Id: testall.rb,v 1.1 2005/01/17 16:15:04 austin Exp $
#++
$LOAD_PATH.unshift("#{File.dirname(__FILE__)}/../lib") if __FILE__ == $0
puts "Checking for test cases:"
Dir['tc*.rb'].each do |testcase|
puts "\t#{testcase}"
require testcase
end
puts " "
text-format-1.0.0/tests/tc_text_format.rb 0000644 0001750 0001750 00000052752 11600332303 020021 0 ustar ondrej ondrej $LOAD_PATH.unshift("#{File.dirname(__FILE__)}/../lib") if __FILE__ == $0
require 'text/format'
require 'test/unit'
class TestText__Format < Test::Unit::TestCase
attr_accessor :format_o
GETTYSBURG = <<-'EOS'
Four score and seven years ago our fathers brought forth on this
continent a new nation, conceived in liberty and dedicated to the
proposition that all men are created equal. Now we are engaged in
a great civil war, testing whether that nation or any nation so
conceived and so dedicated can long endure. We are met on a great
battlefield of that war. We have come to dedicate a portion of
that field as a final resting-place for those who here gave their
lives that that nation might live. It is altogether fitting and
proper that we should do this. But in a larger sense, we cannot
dedicate, we cannot consecrate, we cannot hallow this ground.
The brave men, living and dead who struggled here have consecrated
it far above our poor power to add or detract. The world will
little note nor long remember what we say here, but it can never
forget what they did here. It is for us the living rather to be
dedicated here to the unfinished work which they who fought here
have thus far so nobly advanced. It is rather for us to be here
dedicated to the great task remaining before us--that from these
honored dead we take increased devotion to that cause for which
they gave the last full measure of devotion--that we here highly
resolve that these dead shall not have died in vain, that this
nation under God shall have a new birth of freedom, and that
government of the people, by the people, for the people shall
not perish from the earth.
-- Pres. Abraham Lincoln, 19 November 1863
EOS
FIVE_COL = "Four \nscore\nand s\neven \nyears\nago o\nur fa\nthers\nbroug\nht fo\nrth o\nn thi\ns con\ntinen\nt a n\new na\ntion,\nconce\nived \nin li\nberty\nand d\nedica\nted t\no the\npropo\nsitio\nn tha\nt all\nmen a\nre cr\neated\nequal\n. Now\nwe ar\ne eng\naged \nin a \ngreat\ncivil\nwar, \ntesti\nng wh\nether\nthat \nnatio\nn or \nany n\nation\nso co\nnceiv\ned an\nd so \ndedic\nated \ncan l\nong e\nndure\n. We \nare m\net on\na gre\nat ba\nttlef\nield \nof th\nat wa\nr. We\nhave \ncome \nto de\ndicat\ne a p\nortio\nn of \nthat \nfield\nas a \nfinal\nresti\nng-pl\nace f\nor th\nose w\nho he\nre ga\nve th\neir l\nives \nthat \nthat \nnatio\nn mig\nht li\nve. I\nt is \naltog\nether\nfitti\nng an\nd pro\nper t\nhat w\ne sho\nuld d\no thi\ns. Bu\nt in \na lar\nger s\nense,\nwe ca\nnnot \ndedic\nate, \nwe ca\nnnot \nconse\ncrate\n, we \ncanno\nt hal\nlow t\nhis g\nround\n. The\nbrave\nmen, \nlivin\ng and\ndead \nwho s\ntrugg\nled h\nere h\nave c\nonsec\nrated\nit fa\nr abo\nve ou\nr poo\nr pow\ner to\nadd o\nr det\nract.\nThe w\norld \nwill \nlittl\ne not\ne nor\nlong \nremem\nber w\nhat w\ne say\nhere,\nbut i\nt can\nnever\nforge\nt wha\nt the\ny did\nhere.\nIt is\nfor u\ns the\nlivin\ng rat\nher t\no be \ndedic\nated \nhere \nto th\ne unf\ninish\ned wo\nrk wh\nich t\nhey w\nho fo\nught \nhere \nhave \nthus \nfar s\no nob\nly ad\nvance\nd. It\nis ra\nther \nfor u\ns to \nbe he\nre de\ndicat\ned to\nthe g\nreat \ntask \nremai\nning \nbefor\ne us-\n-that\nfrom \nthese\nhonor\ned de\nad we\ntake \nincre\nased \ndevot\nion t\no tha\nt cau\nse fo\nr whi\nch th\ney ga\nve th\ne las\nt ful\nl mea\nsure \nof de\nvotio\nn--th\nat we\nhere \nhighl\ny res\nolve \nthat \nthese\ndead \nshall\nnot h\nave d\nied i\nn vai\nn, th\nat th\nis na\ntion \nunder\nGod s\nhall \nhave \na new\nbirth\nof fr\needom\n, and\nthat \ngover\nnment\nof th\ne peo\nple, \nby th\ne peo\nple, \nfor t\nhe pe\nople \nshall\nnot p\nerish\nfrom \nthe e\narth.\n-- Pr\nes. A\nbraha\nm Lin\ncoln,\n19 No\nvembe\nr 186\n3 \n"
FIVE_CNF = "Four \nscore\nand s\neven \nyears\nago o\nur f\\\nathe\\\nrs b\\\nroug\\\nht f\\\north \non t\\\nhis c\nonti\\\nnent \na new\nnati\\\non, c\nonce\\\nived \nin l\\\niber\\\nty a\\\nnd d\\\nedic\\\nated \nto t\\\nhe p\\\nropo\\\nsiti\\\non t\\\nhat a\nll m\\\nen a\\\nre c\\\nreat\\\ned e\\\nqual.\nNow w\ne are\nenga\\\nged i\nn a g\nreat \ncivil\nwar, \ntest\\\ning w\nheth\\\ner t\\\nhat n\nation\nor a\\\nny n\\\nation\nso c\\\nonce\\\nived \nand s\no de\\\ndica\\\nted c\nan l\\\nong e\nndur\\\ne. We\nare m\net on\na gr\\\neat b\nattl\\\nefie\\\nld of\nthat \nwar. \nWe h\\\nave c\nome t\no de\\\ndica\\\nte a \nport\\\nion o\nf th\\\nat f\\\nield \nas a \nfinal\nrest\\\ning-\\\nplace\nfor t\nhose \nwho h\nere g\nave t\nheir \nlives\nthat \nthat \nnati\\\non m\\\night \nlive.\nIt is\nalto\\\ngeth\\\ner f\\\nitti\\\nng a\\\nnd p\\\nroper\nthat \nwe s\\\nhould\ndo t\\\nhis. \nBut i\nn a l\narger\nsens\\\ne, we\ncann\\\not d\\\nedic\\\nate, \nwe c\\\nannot\ncons\\\necra\\\nte, w\ne ca\\\nnnot \nhall\\\now t\\\nhis g\nroun\\\nd. T\\\nhe b\\\nrave \nmen, \nlivi\\\nng a\\\nnd d\\\nead w\nho s\\\ntrug\\\ngled \nhere \nhave \ncons\\\necra\\\nted i\nt far\nabove\nour p\noor p\nower \nto a\\\ndd or\ndetr\\\nact. \nThe w\norld \nwill \nlitt\\\nle n\\\note n\nor l\\\nong r\nemem\\\nber w\nhat w\ne say\nhere,\nbut i\nt can\nnever\nforg\\\net w\\\nhat t\nhey d\nid h\\\nere. \nIt is\nfor u\ns the\nlivi\\\nng r\\\nather\nto be\ndedi\\\ncated\nhere \nto t\\\nhe u\\\nnfin\\\nished\nwork \nwhich\nthey \nwho f\nought\nhere \nhave \nthus \nfar s\no no\\\nbly a\ndvan\\\nced. \nIt is\nrath\\\ner f\\\nor us\nto be\nhere \ndedi\\\ncated\nto t\\\nhe g\\\nreat \ntask \nrema\\\nining\nbefo\\\nre u\\\ns--t\\\nhat f\nrom t\nhese \nhono\\\nred d\nead w\ne ta\\\nke i\\\nncre\\\nased \ndevo\\\ntion \nto t\\\nhat c\nause \nfor w\nhich \nthey \ngave \nthe l\nast f\null m\neasu\\\nre of\ndevo\\\ntion\\\n--th\\\nat we\nhere \nhigh\\\nly r\\\nesol\\\nve t\\\nhat t\nhese \ndead \nshall\nnot h\nave d\nied i\nn va\\\nin, t\nhat t\nhis n\nation\nunder\nGod s\nhall \nhave \na new\nbirth\nof f\\\nreed\\\nom, a\nnd t\\\nhat g\nover\\\nnment\nof t\\\nhe p\\\neopl\\\ne, by\nthe p\neopl\\\ne, f\\\nor t\\\nhe p\\\neople\nshall\nnot p\nerish\nfrom \nthe e\narth.\n-- P\\\nres. \nAbra\\\nham L\ninco\\\nln, 1\n9 No\\\nvemb\\\ner 1\\\n863 \n"
FIVE_CNT = "Four \nscore\nand \nseven\nyears\nago \nour f\nathe\\\nrs b\\\nroug\\\nht f\\\north \non t\\\nhis c\nonti\\\nnent \na new\nnati\\\non, c\nonce\\\nived \nin l\\\niber\\\nty a\\\nnd d\\\nedic\\\nated \nto t\\\nhe p\\\nropo\\\nsiti\\\non t\\\nhat \nall \nmen \nare c\nreat\\\ned e\\\nqual.\nNow \nwe a\\\nre e\\\nngag\\\ned in\na gr\\\neat \ncivil\nwar, \ntest\\\ning w\nheth\\\ner t\\\nhat n\nation\nor a\\\nny n\\\nation\nso c\\\nonce\\\nived \nand \nso d\\\nedic\\\nated \ncan \nlong \nendu\\\nre. \nWe a\\\nre m\\\net on\na gr\\\neat b\nattl\\\nefie\\\nld of\nthat \nwar. \nWe h\\\nave \ncome \nto d\\\nedic\\\nate a\nport\\\nion \nof t\\\nhat \nfield\nas a \nfinal\nrest\\\ning-\\\nplace\nfor \nthose\nwho \nhere \ngave \ntheir\nlives\nthat \nthat \nnati\\\non m\\\night \nlive.\nIt is\nalto\\\ngeth\\\ner f\\\nitti\\\nng a\\\nnd p\\\nroper\nthat \nwe s\\\nhould\ndo t\\\nhis. \nBut \nin a \nlarg\\\ner s\\\nense,\nwe c\\\nannot\ndedi\\\ncate,\nwe c\\\nannot\ncons\\\necra\\\nte, \nwe c\\\nannot\nhall\\\now t\\\nhis g\nroun\\\nd. T\\\nhe b\\\nrave \nmen, \nlivi\\\nng a\\\nnd d\\\nead \nwho s\ntrug\\\ngled \nhere \nhave \ncons\\\necra\\\nted \nit f\\\nar a\\\nbove \nour \npoor \npower\nto a\\\ndd or\ndetr\\\nact. \nThe \nworld\nwill \nlitt\\\nle n\\\note \nnor \nlong \nreme\\\nmber \nwhat \nwe s\\\nay h\\\nere, \nbut \nit c\\\nan n\\\never \nforg\\\net w\\\nhat \nthey \ndid \nhere.\nIt is\nfor \nus t\\\nhe l\\\niving\nrath\\\ner to\nbe d\\\nedic\\\nated \nhere \nto t\\\nhe u\\\nnfin\\\nished\nwork \nwhich\nthey \nwho f\nought\nhere \nhave \nthus \nfar \nso n\\\nobly \nadva\\\nnced.\nIt is\nrath\\\ner f\\\nor us\nto be\nhere \ndedi\\\ncated\nto t\\\nhe g\\\nreat \ntask \nrema\\\nining\nbefo\\\nre u\\\ns--t\\\nhat \nfrom \nthese\nhono\\\nred \ndead \nwe t\\\nake i\nncre\\\nased \ndevo\\\ntion \nto t\\\nhat \ncause\nfor \nwhich\nthey \ngave \nthe \nlast \nfull \nmeas\\\nure \nof d\\\nevot\\\nion-\\\n-that\nwe h\\\nere h\nighly\nreso\\\nlve \nthat \nthese\ndead \nshall\nnot \nhave \ndied \nin v\\\nain, \nthat \nthis \nnati\\\non u\\\nnder \nGod \nshall\nhave \na new\nbirth\nof f\\\nreed\\\nom, \nand \nthat \ngove\\\nrnme\\\nnt of\nthe p\neopl\\\ne, by\nthe p\neopl\\\ne, f\\\nor t\\\nhe p\\\neople\nshall\nnot p\nerish\nfrom \nthe e\narth.\n-- P\\\nres. \nAbra\\\nham L\ninco\\\nln, \n19 N\\\novem\\\nber \n1863 \n"
# Tests both abbreviations and abbreviations=
def test_abbreviations
abbr = [" Pres. Abraham Lincoln\n", " Pres. Abraham Lincoln\n"]
@format_o = Text::Format.new
assert_equal([], @format_o.abbreviations)
@format_o.abbreviations = [ 'foo', 'bar' ]
assert_equal([ 'foo', 'bar' ], @format_o.abbreviations)
assert_equal(abbr[0], @format_o.format(abbr[0]))
@format_o.extra_space = true
assert_equal(abbr[1], @format_o.format(abbr[0]))
@format_o.abbreviations = [ "Pres" ]
assert_equal([ "Pres" ], @format_o.abbreviations)
assert_equal(abbr[0], @format_o.format(abbr[0]))
@format_o.extra_space = false
assert_equal(abbr[0], @format_o.format(abbr[0]))
end
# Tests both body_indent and body_indent=
def test_body_indent
@format_o = Text::Format.new
assert_equal(0, @format_o.body_indent)
@format_o.body_indent = 7
assert_equal(7, @format_o.body_indent)
@format_o.body_indent = -3
assert_equal(3, @format_o.body_indent)
@format_o.body_indent = "9"
assert_equal(9, @format_o.body_indent)
@format_o.body_indent = "-2"
assert_equal(2, @format_o.body_indent)
assert_match(/^ [^ ]/, @format_o.format(GETTYSBURG).split("\n")[1])
end
# Tests both columns and columns=
def test_columns
@format_o = Text::Format.new
assert_equal(72, @format_o.columns)
@format_o.columns = 7
assert_equal(7, @format_o.columns)
@format_o.columns = -3
assert_equal(3, @format_o.columns)
@format_o.columns = "9"
assert_equal(9, @format_o.columns)
@format_o.columns = "-2"
assert_equal(2, @format_o.columns)
@format_o.columns = 40
assert_equal(40, @format_o.columns)
assert_match(/this continent$/,
@format_o.format(GETTYSBURG).split("\n")[1])
end
# Tests both extra_space and extra_space=
def test_extra_space
@format_o = Text::Format.new
assert_equal(false, @format_o.extra_space)
@format_o.extra_space = true
assert_equal(true, @format_o.extra_space)
end
# Tests both first_indent and first_indent=
def test_first_indent
@format_o = Text::Format.new
assert_equal(4, @format_o.first_indent)
@format_o.first_indent = 7
assert_equal(7, @format_o.first_indent)
@format_o.first_indent = -3
assert_equal(3, @format_o.first_indent)
@format_o.first_indent = "9"
assert_equal(9, @format_o.first_indent)
@format_o.first_indent = "-2"
assert_equal(2, @format_o.first_indent)
assert_match(/^ [^ ]/, @format_o.format(GETTYSBURG).split("\n")[0])
end
def test_format_style
@format_o = Text::Format.new
assert_equal(Text::Format::LEFT_ALIGN, @format_o.format_style)
assert_match(/^November 1863$/, @format_o.format(GETTYSBURG).split("\n")[-1])
@format_o.format_style = Text::Format::RIGHT_ALIGN
assert_equal(Text::Format::RIGHT_ALIGN, @format_o.format_style)
assert_match(/^ +November 1863$/, @format_o.format(GETTYSBURG).split("\n")[-1])
@format_o.format_style = Text::Format::RIGHT_FILL
assert_equal(Text::Format::RIGHT_FILL, @format_o.format_style)
assert_match(/^November 1863 +$/, @format_o.format(GETTYSBURG).split("\n")[-1])
@format_o.format_style = Text::Format::JUSTIFY
assert_equal(Text::Format::JUSTIFY, @format_o.format_style)
assert_match(/^of freedom, and that government of the people, by the people, for the$/, @format_o.format(GETTYSBURG).split("\n")[-3])
assert_raises(ArgumentError) { @format_o.format_style = 33 }
end
def test_tag_paragraph
@format_o = Text::Format.new
assert_equal(false, @format_o.tag_paragraph)
@format_o.tag_paragraph = true
assert_equal(true, @format_o.tag_paragraph)
assert_not_equal(@format_o.paragraphs([GETTYSBURG, GETTYSBURG]),
Text::Format.new.paragraphs([GETTYSBURG, GETTYSBURG]))
end
def test_tag_text
@format_o = Text::Format.new
assert_equal([], @format_o.tag_text)
assert_equal(@format_o.format(GETTYSBURG),
Text::Format.new.format(GETTYSBURG))
@format_o.tag_paragraph = true
@format_o.tag_text = ["Gettysburg Address", "---"]
assert_not_equal(@format_o.format(GETTYSBURG), Text::Format.new.format(GETTYSBURG))
assert_not_equal(@format_o.paragraphs([GETTYSBURG, GETTYSBURG]), Text::Format.new.paragraphs([GETTYSBURG, GETTYSBURG]))
assert_not_equal(@format_o.paragraphs([GETTYSBURG, GETTYSBURG, GETTYSBURG]), Text::Format.new.paragraphs([GETTYSBURG, GETTYSBURG, GETTYSBURG]))
end
def test_justify?
@format_o = Text::Format.new
assert_equal(false, @format_o.justify?)
@format_o.format_style = Text::Format::RIGHT_ALIGN
assert_equal(false, @format_o.justify?)
@format_o.format_style = Text::Format::RIGHT_FILL
assert_equal(false, @format_o.justify?)
@format_o.format_style = Text::Format::JUSTIFY
assert_equal(true, @format_o.justify?)
# The format testing is done in _format_style
end
def test_left_align?
@format_o = Text::Format.new
assert_equal(true, @format_o.left_align?)
@format_o.format_style = Text::Format::RIGHT_ALIGN
assert_equal(false, @format_o.left_align?)
@format_o.format_style = Text::Format::RIGHT_FILL
assert_equal(false, @format_o.left_align?)
@format_o.format_style = Text::Format::JUSTIFY
assert_equal(false, @format_o.left_align?)
# The format testing is done in _format_style
end
def test_left_margin
@format_o = Text::Format.new
assert_equal(0, @format_o.left_margin)
@format_o.left_margin = -3
assert_equal(3, @format_o.left_margin)
@format_o.left_margin = "9"
assert_equal(9, @format_o.left_margin)
@format_o.left_margin = "-2"
assert_equal(2, @format_o.left_margin)
@format_o.left_margin = 7
assert_equal(7, @format_o.left_margin)
ft = @format_o.format(GETTYSBURG).split("\n")
assert_match(/^ {11}Four score/, ft[0])
assert_match(/^ {7}November/, ft[-1])
end
def test_hard_margins
@format_o = Text::Format.new
assert_equal(false, @format_o.hard_margins)
@format_o.hard_margins = true
@format_o.columns = 5
@format_o.first_indent = 0
@format_o.format_style = Text::Format::RIGHT_FILL
assert_equal(true, @format_o.hard_margins)
assert_equal(FIVE_COL, @format_o.format(GETTYSBURG))
@format_o.split_rules |= Text::Format::SPLIT_CONTINUATION
assert_equal(Text::Format::SPLIT_CONTINUATION_FIXED, @format_o.split_rules)
assert_equal(FIVE_CNF, @format_o.format(GETTYSBURG))
@format_o.split_rules = Text::Format::SPLIT_CONTINUATION
assert_equal(Text::Format::SPLIT_CONTINUATION, @format_o.split_rules)
assert_equal(FIVE_CNT, @format_o.format(GETTYSBURG))
end
# Tests both nobreak and nobreak_regex, since one is only useful
# with the other.
def test_nobreak
@format_o = Text::Format.new
assert_equal(false, @format_o.nobreak)
assert_equal(true, @format_o.nobreak_regex.empty?)
@format_o.nobreak = true
@format_o.nobreak_regex = { %r{this} => %r{continent} }
@format_o.columns = 77
assert_equal(true, @format_o.nobreak)
assert_equal({ %r{this} => %r{continent} }, @format_o.nobreak_regex)
assert_match(/^this continent/,
@format_o.format(GETTYSBURG).split("\n")[1])
end
def test_right_align?
@format_o = Text::Format.new
assert_equal(false, @format_o.right_align?)
@format_o.format_style = Text::Format::RIGHT_ALIGN
assert_equal(true, @format_o.right_align?)
@format_o.format_style = Text::Format::RIGHT_FILL
assert_equal(false, @format_o.right_align?)
@format_o.format_style = Text::Format::JUSTIFY
assert_equal(false, @format_o.right_align?)
# The format testing is done in _format_style
end
def test_right_fill?
@format_o = Text::Format.new
assert_equal(false, @format_o.right_fill?)
@format_o.format_style = Text::Format::RIGHT_ALIGN
assert_equal(false, @format_o.right_fill?)
@format_o.format_style = Text::Format::RIGHT_FILL
assert_equal(true, @format_o.right_fill?)
@format_o.format_style = Text::Format::JUSTIFY
assert_equal(false, @format_o.right_fill?)
# The format testing is done in _format_style
end
def test_right_margin
@format_o = Text::Format.new
assert_equal(0, @format_o.right_margin)
@format_o.right_margin = -3
assert_equal(3, @format_o.right_margin)
@format_o.right_margin = "9"
assert_equal(9, @format_o.right_margin)
@format_o.right_margin = "-2"
assert_equal(2, @format_o.right_margin)
@format_o.right_margin = 7
assert_equal(7, @format_o.right_margin)
ft = @format_o.format(GETTYSBURG).split("\n")
assert_match(/^ {4}Four score.*forth on$/, ft[0])
assert_match(/^November/, ft[-1])
end
def test_tabstop
@format_o = Text::Format.new
assert_equal(8, @format_o.tabstop)
@format_o.tabstop = 7
assert_equal(7, @format_o.tabstop)
@format_o.tabstop = -3
assert_equal(3, @format_o.tabstop)
@format_o.tabstop = "9"
assert_equal(9, @format_o.tabstop)
@format_o.tabstop = "-2"
assert_equal(2, @format_o.tabstop)
end
def test_text
@format_o = Text::Format.new
assert_equal([], @format_o.text)
@format_o.text = "Test Text"
assert_equal("Test Text", @format_o.text)
@format_o.text = ["Line 1", "Line 2"]
assert_equal(["Line 1", "Line 2"], @format_o.text)
end
def test_new
@format_o = Text::Format.new { |fo| fo.text = "Test 1, 2, 3" }
assert_equal("Test 1, 2, 3", @format_o.text)
@format_o = Text::Format.new(:columns => 79)
assert_equal(79, @format_o.columns)
@format_o = Text::Format.new(:columns => 80) { |fo| fo.text = "Test 4, 5, 6" }
assert_equal("Test 4, 5, 6", @format_o.text)
assert_equal(80, @format_o.columns)
@format_o = Text::Format.new(:text => "Test A, B, C")
assert_equal("Test A, B, C", @format_o.text)
@format_o = Text::Format.new(:text => "Test X, Y, Z") { |fo| fo.columns = -5 }
assert_equal("Test X, Y, Z", @format_o.text)
assert_equal(5, @format_o.columns)
end
def test_center
@format_o = Text::Format.new
ct = @format_o.center(GETTYSBURG.split("\n")).split("\n")
assert_match(/^ Four score and seven years ago our fathers brought forth on this/, ct[0])
assert_match(/^ not perish from the earth./, ct[-3])
end
def test_expand
@format_o = Text::Format.new
assert_equal(" ", @format_o.expand("\t "))
@format_o.tabstop = 4
assert_equal(" ", @format_o.expand("\t "))
end
def test_unexpand
@format_o = Text::Format.new
assert_equal("\t ", @format_o.unexpand(" "))
@format_o.tabstop = 4
assert_equal("\t ", @format_o.unexpand(" "))
end
def test_space_only
assert_equal("", Text::Format.new.format(" "))
assert_equal("", Text::Format.new.format("\n"))
assert_equal("", Text::Format.new.format(" "))
assert_equal("", Text::Format.new.format(" \n"))
assert_equal("", Text::Format.new.paragraphs("\n"))
assert_equal("", Text::Format.new.paragraphs(" "))
assert_equal("", Text::Format.new.paragraphs(" "))
assert_equal("", Text::Format.new.paragraphs(" \n"))
assert_equal("", Text::Format.new.paragraphs(["\n"]))
assert_equal("", Text::Format.new.paragraphs([" "]))
assert_equal("", Text::Format.new.paragraphs([" "]))
assert_equal("", Text::Format.new.paragraphs([" \n"]))
end
def test_splendiferous
h = nil
test = "This is a splendiferous test"
@format_o = Text::Format.new(:columns => 6, :left_margin => 0, :indent => 0, :first_indent => 0)
assert_match(/^splendiferous$/, @format_o.format(test))
@format_o.hard_margins = true
assert_match(/^lendif$/, @format_o.format(test))
h = Object.new
@format_o.split_rules = Text::Format::SPLIT_HYPHENATION
class << h
def hyphenate_to(word, size)
return [nil, word] if size < 2
[word[0 ... size], word[size .. -1]]
end
end
@format_o.hyphenator = h
assert_match(/^ferous$/, @format_o.format(test))
h = Object.new
class << h
def hyphenate_to(word, size, formatter)
return [nil, word] if word.size < formatter.columns
[word[0 ... size], word[size .. -1]]
end
end
@format_o.hyphenator = h
assert_match(/^ferous$/, @format_o.format(test))
end
def test_encephelogram
hy = nil
begin
require 'text/hyphen'
hy = Text::Hyphen.new
rescue LoadError
begin
require 'rubygems'
require 'text/hyphen'
hy = Text::Hyphen.new
rescue LoadError
begin
require 'tex/hyphen'
hy = TeX::Hyphen.new
rescue LoadError
print 'S'
return true
end
end
end
tx = "something pancakes electroencephalogram"
fo = Text::Format.new(:body_indent => 15,
:columns => 30,
:hard_margins => true,
:split_rules => Text::Format::SPLIT_HYPHENATION,
:hyphenator => hy,
:text => tx)
res = fo.paragraphs
exp = <<-EOS
something pancakes elec-
troencephalo-
gram
EOS
exp.chomp!
assert_equal(exp, res)
end
end
text-format-1.0.0/Rakefile 0000644 0001750 0001750 00000006054 11600332303 014747 0 ustar ondrej ondrej #! /usr/bin/env rake
$LOAD_PATH.unshift('lib')
require 'rubygems'
require 'rake/gempackagetask'
require 'text/format'
require 'archive/tar/minitar'
require 'zlib'
DISTDIR = "text-format-#{Text::Format::VERSION}"
TARDIST = "../#{DISTDIR}.tar.gz"
DATE_RE = %r<(\d{4})[./-]?(\d{2})[./-]?(\d{2})(?:[\sT]?(\d{2})[:.]?(\d{2})[:.]?(\d{2})?)?>
if ENV['RELEASE_DATE']
year, month, day, hour, minute, second = DATE_RE.match(ENV['RELEASE_DATE']).captures
year ||= 0
month ||= 0
day ||= 0
hour ||= 0
minute ||= 0
second ||= 0
ReleaseDate = Time.mktime(year, month, day, hour, minute, second)
else
ReleaseDate = nil
end
task :test do |t|
require 'test/unit/testsuite'
require 'test/unit/ui/console/testrunner'
runner = Test::Unit::UI::Console::TestRunner
$LOAD_PATH.unshift('tests')
$stderr.puts "Checking for test cases:" if t.verbose
Dir['tests/tc_*.rb'].each do |testcase|
$stderr.puts "\t#{testcase}" if t.verbose
load testcase
end
suite = Test::Unit::TestSuite.new("Text::Format")
ObjectSpace.each_object(Class) do |testcase|
suite << testcase.suite if testcase < Test::Unit::TestCase
end
runner.run(suite)
end
spec = eval(File.read("text-format.gemspec"))
spec.version = Text::Format::VERSION
desc "Build the RubyGem for Text::Format"
task :gem => [ :test ]
Rake::GemPackageTask.new(spec) do |g|
g.need_tar = false
g.need_zip = false
g.package_dir = ".."
end
desc "Build a Text::Format .tar.gz distribution."
task :tar => [ TARDIST ]
file TARDIST => [ :test ] do |t|
current = File.basename(Dir.pwd)
Dir.chdir("..") do
begin
files = Dir["#{current}/**/*"].select { |dd| dd !~ %r{(?:/CVS/?|~$)} }
files.map! do |dd|
ddnew = dd.gsub(/^#{current}/, DISTDIR)
mtime = ReleaseDate || File.stat(dd).mtime
if File.directory?(dd)
{ :name => ddnew, :mode => 0755, :dir => true, :mtime => mtime }
else
if dd =~ %r{bin/}
mode = 0755
else
mode = 0644
end
data = File.read(dd)
{ :name => ddnew, :mode => mode, :data => data, :size => data.size,
:mtime => mtime }
end
end
ff = File.open(t.name.gsub(%r{^\.\./}o, ''), "wb")
gz = Zlib::GzipWriter.new(ff)
tw = Archive::Tar::Minitar::Writer.new(gz)
files.each do |entry|
if entry[:dir]
tw.mkdir(entry[:name], entry)
else
tw.add_file_simple(entry[:name], entry) { |os| os.write(entry[:data]) }
end
end
ensure
tw.close if tw
gz.close if gz
end
end
end
task TARDIST => [ :test ]
desc "Build the RDoc documentation for Text::Format"
task :docs do
require 'rdoc/rdoc'
rdoc_options = %w(--title Text::Format --main README --line-numbers)
files = FileList[*%w(README ChangeLog Install bin/**/*.rb lib/**/*.rb)]
rdoc_options += files.to_a
RDoc::RDoc.new.document(rdoc_options)
end
desc "Build everything."
task :default => [ :tar, :gem ]
text-format-1.0.0/pre-setup.rb 0000644 0001750 0001750 00000002222 11600332303 015544 0 ustar ondrej ondrej require 'rdoc/rdoc'
##
# Build the rdoc documentation. Also, try to build the RI documentation.
#
def build_rdoc(options)
RDoc::RDoc.new.document(options)
rescue RDoc::RDocError => e
$stderr.puts e.message
rescue Exception => e
$stderr.puts "Couldn't build RDoc documentation\n#{e.message}"
end
def build_ri(files)
RDoc::RDoc.new(files)
rescue RDoc::RDocError => e
$stderr.puts e.message
rescue Exception => e
$stderr.puts "Couldn't build Ri documentation\n#{e.message}"
end
def run_tests(test_list)
return if test_list.empty?
require 'test/unit/ui/console/testrunner'
$:.unshift "lib"
test_list.each do |test|
next if File.directory?(test)
require test
end
tests = []
ObjectSpace.each_object { |o| tests << o if o.kind_of?(Class) }
tests.delete_if { |o| !o.ancestors.include?(Test::Unit::TestCase) }
tests.delete_if { |o| o == Test::Unit::TestCase }
tests.each { |test| Test::Unit::UI::Console::TestRunner.run(test) }
$:.shift
end
rdoc = %w(--main README --line-numbers
--title Text::Format)
ri = %w(--ri-site --merge)
dox = %w(README ChangeLog lib)
build_rdoc rdoc + dox
build_ri ri + dox
#run_tests []
text-format-1.0.0/ToDo 0000644 0001750 0001750 00000000533 11600332303 014066 0 ustar ondrej ondrej Text::Format To Do
==================
* Margin markers: the ability to place markers in the margin when
formatting.
* Line numbering: the ability to number lines in the margin when
formatting, including numering lines by step (every fifth line, etc.).
* Email attribution quoting reformatting.
* Proportional width support for GUI formatting.
text-format-1.0.0/lib/ 0000755 0001750 0001750 00000000000 11600332303 014043 5 ustar ondrej ondrej text-format-1.0.0/lib/text/ 0000755 0001750 0001750 00000000000 11600332303 015027 5 ustar ondrej ondrej text-format-1.0.0/lib/text/format.rb 0000644 0001750 0001750 00000112572 11600332303 016654 0 ustar ondrej ondrej # :title: Text::Format
# :main: Text::Format
#--
# Text::Format for Ruby
# Version 1.0.0
#
# Copyright (c) 2002 - 2005 Austin Ziegler
#
# $Id: format.rb,v 1.5 2005/04/20 01:43:55 austin Exp $
#++
unless defined?(Text)
module Text; end
end
# = Introduction
#
# Text::Format provides the ability to nicely format fixed-width text with
# knowledge of the writeable space (number of columns), margins, and
# indentation settings.
#
# Copyright:: Copyright (c) 2002 - 2005 by Austin Ziegler
# Version:: 1.0.0
# Based On:: Perl
# Text::Format[http://search.cpan.org/author/GABOR/Text-Format0.52/lib/Text/Format.pm],
# Copyright (c) 1998 Gábor Egressy
# Licence:: Ruby's, Perl Artistic, or GPL version 2 (or later)
#
class Text::Format
VERSION = '1.0.0'
SPACES_RE = %r{\s+}mo.freeze
NEWLINE_RE = %r{\n}o.freeze
TAB = "\t".freeze
NEWLINE = "\n".freeze
# Global common English abbreviations. More can be added with
# #abbreviations.
ABBREV = %w(Mr Mrs Ms Jr Sr Dr)
# Formats text flush to the left margin with a visual and physical
# ragged right margin.
#
# >A paragraph that is<
# >left aligned.<
LEFT_ALIGN = :left
# Formats text flush to the right margin with a visual ragged left
# margin. The actual left margin is padded with spaces from the
# beginning of the line to the start of the text such that the right
# margin will be flush.
#
# >A paragraph that is<
# > right aligned.<
RIGHT_ALIGN = :right
# Formats text flush to the left margin with a visual ragged right
# margin. The line is padded with spaces from the end of the text to the
# right margin.
#
# >A paragraph that is<
# >right filled. <
RIGHT_FILL = :fill
# Formats the text flush to both the left and right margins. The last
# line will not be justified if it consists of a single word (it will be
# treated as +RIGHT_FILL+ in this case). Spacing between words is
# increased to ensure that the textg is flush with both margins.
#
# |A paragraph that|
# |is justified.|
#
# |A paragraph that is|
# |justified. |
JUSTIFY = :justify
# When #hard_margins is enabled, a word that extends over the right
# margin will be split at the number of characters needed. This is
# similar to how characters wrap on a terminal. This is the default
# split mechanism when #hard_margins is enabled.
#
# repre
# senta
# ion
SPLIT_FIXED = 1
# When #hard_margins is enabled, a word that extends over the right
# margin will be split at one less than the number of characters needed
# with a C-style continuation character (\). If the word cannot be split
# using the rules of SPLIT_CONTINUATION, and the word will not fit
# wholly into the next line, then SPLIT_FIXED will be used.
#
# repr\
# esen\
# tati\
# on
SPLIT_CONTINUATION = 2
# When #hard_margins is enabled, a word that extends over the right
# margin will be split according to the hyphenator specified by the
# #hyphenator object; if there is no hyphenation library supplied, then
# the hyphenator of Text::Format itself is used, which is the same as
# SPLIT_CONTINUATION. See #hyphenator for more information about
# hyphenation libraries. The example below is valid with either
# TeX::Hyphen or Text::Hyphen. If the word cannot be split using the
# hyphenator's rules, and the word will not fit wholly into the next
# line, then SPLIT_FIXED will be used.
#
# rep-
# re-
# sen-
# ta-
# tion
#
SPLIT_HYPHENATION = 4
# When #hard_margins is enabled, a word that extends over the right
# margin will be split at one less than the number of characters needed
# with a C-style continuation character (\). If the word cannot be split
# using the rules of SPLIT_CONTINUATION, then SPLIT_FIXED will be used.
SPLIT_CONTINUATION_FIXED = SPLIT_CONTINUATION | SPLIT_FIXED
# When #hard_margins is enabled, a word that extends over the right
# margin will be split according to the hyphenator specified by the
# #hyphenator object; if there is no hyphenation library supplied, then
# the hyphenator of Text::Format itself is used, which is the same as
# SPLIT_CONTINUATION. See #hyphenator for more information about
# hyphenation libraries. The example below is valid with either
# TeX::Hyphen or Text::Hyphen. If the word cannot be split using the
# hyphenator's rules, then SPLIT_FIXED will be used.
SPLIT_HYPHENATION_FIXED = SPLIT_HYPHENATION | SPLIT_FIXED
# Attempts to split words according to the rules of the supplied
# hyphenator (e.g., SPLIT_HYPHENATION); if the word cannot be split
# using these rules, then the rules of SPLIT_CONTINUATION will be
# followed. In all cases, if the word cannot be split using either
# SPLIT_HYPHENATION or SPLIT_CONTINUATION, and the word will not fit
# wholly into the next line, then SPLIT_FIXED will be used.
SPLIT_HYPHENATION_CONTINUATION = SPLIT_HYPHENATION | SPLIT_CONTINUATION
# Attempts to split words according to the rules of the supplied
# hyphenator (e.g., SPLIT_HYPHENATION); if the word cannot be split
# using these rules, then the rules of SPLIT_CONTINUATION will be
# followed. In all cases, if the word cannot be split using either
# SPLIT_HYPHENATION or SPLIT_CONTINUATION, then SPLIT_FIXED will be
# used.
SPLIT_ALL = SPLIT_HYPHENATION | SPLIT_CONTINUATION | SPLIT_FIXED
# Words forcibly split by Text::Format will be stored as split words.
# This class represents a word forcibly split.
class SplitWord
# The word that was split.
attr_reader :word
# The first part of the word that was split.
attr_reader :first
# The remainder of the word that was split.
attr_reader :rest
def initialize(word, first, rest)
@word = word
@first = first
@rest = rest
end
end
# Indicates punctuation characters that terminates a sentence, as some
# English typesetting rules indicate that sentences should be followed
# by two spaces. This is an archaic rule, but is supported with
# #extra_space. This is the default set of terminal punctuation
# characters. Additional terminal punctuation may be added to the
# formatting object through #terminal_punctuation.
TERMINAL_PUNCTUATION = %q(.?!)
# Indicates quote characters that may follow terminal punctuation under
# the current formatting rules. This satisfies the English formatting
# rule that indicates that sentences terminated inside of quotes should
# have the punctuation inside of the quoted text, not outside of the
# terminal quote. Additional terminal quotes may be added to the
# formatting object through #terminal_quotes. See TERMINAL_PUNCTUATION
# for more information.
TERMINAL_QUOTES = %q('")
# This method returns the regular expression used to detect the end of a
# sentence under the current definition of TERMINAL_PUNCTUATION,
# #terminal_punctuation, TERMINAL_QUOTES, and #terminal_quotes.
def __sentence_end_re
%r{[#{TERMINAL_PUNCTUATION}#{self.terminal_punctuation}][#{TERMINAL_QUOTES}#{self.terminal_quotes}]?$}
end
private :__sentence_end_re
# Returns a regular expression for a set of characters (at least one
# non-whitespace followed by at least one space) of the specified size
# followed by one or more of any character.
RE_BREAK_SIZE = lambda { |size| %r[((?:\S+\s+){#{size}})(.+)] }
# Compares the formatting rules, excepting #hyphenator, of two
# Text::Format objects. Generated results (e.g., #split_words) are not
# compared.
def ==(o)
(@text == o.text) and
(@columns == o.columns) and
(@left_margin == o.left_margin) and
(@right_margin == o.right_margin) and
(@hard_margins == o.hard_margins) and
(@split_rules == o.split_rules) and
(@first_indent == o.first_indent) and
(@body_indent == o.body_indent) and
(@tag_text == o.tag_text) and
(@tabstop == o.tabstop) and
(@format_style == o.format_style) and
(@extra_space == o.extra_space) and
(@tag_paragraph == o.tag_paragraph) and
(@nobreak == o.nobreak) and
(@terminal_punctuation == o.terminal_punctuation) and
(@terminal_quotes == o.terminal_quotes) and
(@abbreviations == o.abbreviations) and
(@nobreak_regex == o.nobreak_regex)
end
# The default text to be manipulated. Note that value is optional, but
# if the formatting functions are called without values, this text is
# what will be formatted.
#
# *Default*:: []
# Used in:: All methods
attr_accessor :text
# The total width of the format area. The margins, indentation, and text
# are formatted into this space. Any value provided is silently
# converted to a positive integer.
#
# COLUMNS
# <-------------------------------------------------------------->
# <-----------><------><---------------------------><------------>
# left margin indent text is formatted into here right margin
#
# *Default*:: 72
# Used in:: #format, #paragraphs, #center
attr_accessor :columns
def columns=(col) #:nodoc:
@columns = col.to_i.abs
end
# The number of spaces used for the left margin. The value provided is
# silently converted to a positive integer value.
#
# columns
# <-------------------------------------------------------------->
# <-----------><------><---------------------------><------------>
# LEFT MARGIN indent text is formatted into here right margin
#
# *Default*:: 0
# Used in:: #format, #paragraphs, #center
attr_accessor :left_margin
def left_margin=(left) #:nodoc:
@left_margin = left.to_i.abs
end
# The number of spaces used for the right margin. The value provided is
# silently converted to a positive integer value.
#
# columns
# <-------------------------------------------------------------->
# <-----------><------><---------------------------><------------>
# left margin indent text is formatted into here RIGHT MARGIN
#
# *Default*:: 0
# Used in:: #format, #paragraphs, #center
attr_accessor :right_margin
def right_margin=(right) #:nodoc:
@right_margin = right.to_i.abs
end
# The number of spaces to indent the first line of a paragraph. The
# value provided is silently converted to a positive integer value.
#
# columns
# <-------------------------------------------------------------->
# <-----------><------><---------------------------><------------>
# left margin INDENT text is formatted into here right margin
#
# *Default*:: 4
# Used in:: #format, #paragraphs
attr_accessor :first_indent
def first_indent=(first) #:nodoc:
@first_indent = first.to_i.abs
end
# The number of spaces to indent all lines after the first line of a
# paragraph. The value provided is silently converted to a positive
# integer value.
#
# columns
# <-------------------------------------------------------------->
# <-----------><------><---------------------------><------------>
# left margin INDENT text is formatted into here right margin
#
# *Default*:: 0
# Used in:: #format, #paragraphs
attr_accessor :body_indent
def body_indent=(body) #:nodoc:
@body_indent = body.to_i.abs
end
# Normally, words larger than the format area will be placed on a line
# by themselves. Setting this value to +true+ will force words larger
# than the format area to be split into one or more "words" each at most
# the size of the format area. The first line and the original word will
# be placed into #split_words. Note that this will cause the output to
# look *similar* to a #format_style of JUSTIFY. (Lines will be filled as
# much as possible.)
#
# *Default*:: +false+
# Used in:: #format, #paragraphs
attr_accessor :hard_margins
# An array of words split during formatting if #hard_margins is set to
# +true+.
# #split_words << Text::Format::SplitWord.new(word, first, rest)
attr_reader :split_words
# The object responsible for hyphenating. It must respond to
# #hyphenate_to(word, size) or #hyphenate_to(word, size, formatter) and
# return an array of the word split into two parts (e.g., [part1,
# part2]; if there is a hyphenation mark to be applied,
# responsibility belongs to the hyphenator object. The size is the
# MAXIMUM size permitted, including any hyphenation marks.
#
# If the #hyphenate_to method has an arity of 3, the current formatter
# (+self+) will be provided to the method. This allows the hyphenator to
# make decisions about the hyphenation based on the formatting rules.
#
# #hyphenate_to should return [nil, word] if the word cannot be
# hyphenated.
#
# *Default*:: +self+ (SPLIT_CONTINUATION)
# Used in:: #format, #paragraphs
attr_accessor :hyphenator
def hyphenator=(h) #:nodoc:
h ||= self
raise ArgumentError, "#{h.inspect} is not a valid hyphenator." unless h.respond_to?(:hyphenate_to)
arity = h.method(:hyphenate_to).arity
raise ArgumentError, "#{h.inspect} must have exactly two or three arguments." unless arity.between?(2, 3)
@hyphenator = h
@hyphenator_arity = arity
end
# Specifies the split mode; used only when #hard_margins is set to
# +true+. Allowable values are:
#
# * +SPLIT_FIXED+
# * +SPLIT_CONTINUATION+
# * +SPLIT_HYPHENATION+
# * +SPLIT_CONTINUATION_FIXED+
# * +SPLIT_HYPHENATION_FIXED+
# * +SPLIT_HYPHENATION_CONTINUATION+
# * +SPLIT_ALL+
#
# *Default*:: Text::Format::SPLIT_FIXED
# Used in:: #format, #paragraphs
attr_accessor :split_rules
def split_rules=(s) #:nodoc:
raise ArgumentError, "Invalid value provided for #split_rules." if ((s < SPLIT_FIXED) or (s > SPLIT_ALL))
@split_rules = s
end
# Indicates whether sentence terminators should be followed by a single
# space (+false+), or two spaces (+true+). See #abbreviations for more
# information.
#
# *Default*:: +false+
# Used in:: #format, #paragraphs
attr_accessor :extra_space
# Defines the current abbreviations as an array. This is only used if
# extra_space is turned on.
#
# If one is abbreviating "President" as "Pres." (abbreviations =
# ["Pres"]), then the results of formatting will be as illustrated in
# the table below:
#
# abbreviations
# extra_space | #include?("Pres") | not #include?("Pres")
# ------------+-------------------+----------------------
# true | Pres. Lincoln | Pres. Lincoln
# false | Pres. Lincoln | Pres. Lincoln
# ------------+-------------------+----------------------
# extra_space | #include?("Mrs") | not #include?("Mrs")
# true | Mrs. Lincoln | Mrs. Lincoln
# false | Mrs. Lincoln | Mrs. Lincoln
#
# Note that abbreviations should not have the terminal period as part of
# their definitions.
#
# This automatic abbreviation handling *will* cause some issues with
# uncommon sentence structures. The two sentences below will not be
# formatted correctly:
#
# You're in trouble now, Mr.
# Just wait until your father gets home.
#
# Under no circumstances (because Mr is a predefined abbreviation) will
# this ever be separated by two spaces.
#
# *Default*:: []
# Used in:: #format, #paragraphs
attr_accessor :abbreviations
# Specifies additional punctuation characters that terminate a sentence,
# as some English typesetting rules indicate that sentences should be
# followed by two spaces. This is an archaic rule, but is supported with
# #extra_space. This is added to the default set of terminal punctuation
# defined in TERMINAL_PUNCTUATION.
#
# *Default*:: ""
# Used in:: #format, #paragraphs
attr_accessor :terminal_punctuation
# Specifies additional quote characters that may follow
# terminal punctuation under the current formatting rules. This
# satisfies the English formatting rule that indicates that sentences
# terminated inside of quotes should have the punctuation inside of the
# quoted text, not outside of the terminal quote. This is added to the
# default set of terminal quotes defined in TERMINAL_QUOTES.
#
# *Default*:: ""
# Used in:: #format, #paragraphs
attr_accessor :terminal_quotes
# Indicates whether the formatting of paragraphs should be done with
# tagged paragraphs. Useful only with #tag_text.
#
# *Default*:: +false+
# Used in:: #format, #paragraphs
attr_accessor :tag_paragraph
# The text to be placed before each paragraph when #tag_paragraph is
# +true+. When #format is called, only the first element (#tag_text[0])
# is used. When #paragraphs is called, then each successive element
# (#tag_text[n]) will be used once, with corresponding paragraphs. If
# the tag elements are exhausted before the text is exhausted, then the
# remaining paragraphs will not be tagged. Regardless of indentation
# settings, a blank line will be inserted between all paragraphs when
# #tag_paragraph is +true+.
#
# The Text::Format package provides three number generators,
# Text::Format::Alpha, Text::Format::Number, and Text::Format::Roman to
# assist with the numbering of paragraphs.
#
# *Default*:: []
# Used in:: #format, #paragraphs
attr_accessor :tag_text
# Indicates whether or not the non-breaking space feature should be
# used.
#
# *Default*:: +false+
# Used in:: #format, #paragraphs
attr_accessor :nobreak
# A hash which holds the regular expressions on which spaces should not
# be broken. The hash is set up such that the key is the first word and
# the value is the second word.
#
# For example, if +nobreak_regex+ contains the following hash:
#
# { %r{Mrs?\.?} => %r{\S+}, %r{\S+} => %r{(?:[SJ])r\.?} }
#
# Then "Mr. Jones", "Mrs Jones", and "Jones Jr." would not be broken. If
# this simple matching algorithm indicates that there should not be a
# break at the current end of line, then a backtrack is done until there
# are two words on which line breaking is permitted. If two such words
# are not found, then the end of the line will be broken *regardless*.
# If there is a single word on the current line, then no backtrack is
# done and the word is stuck on the end.
#
# *Default*:: {}
# Used in:: #format, #paragraphs
attr_accessor :nobreak_regex
# Indicates the number of spaces that a single tab represents. Any value
# provided is silently converted to a positive integer.
#
# *Default*:: 8
# Used in:: #expand, #unexpand,
# #paragraphs
attr_accessor :tabstop
def tabstop=(tabs) #:nodoc:
@tabstop = tabs.to_i.abs
end
# Specifies the format style. Allowable values are:
# *+LEFT_ALIGN+
# *+RIGHT_ALIGN+
# *+RIGHT_FILL+
# *+JUSTIFY+
#
# *Default*:: Text::Format::LEFT_ALIGN
# Used in:: #format, #paragraphs
attr_accessor :format_style
def format_style=(fs) #:nodoc:
raise ArgumentError, "Invalid value provided for format_style." unless [LEFT_ALIGN, RIGHT_ALIGN, RIGHT_FILL, JUSTIFY].include?(fs)
@format_style = fs
end
# Indicates that the format style is left alignment.
#
# *Default*:: +true+
# Used in:: #format, #paragraphs
def left_align?
@format_style == LEFT_ALIGN
end
# Indicates that the format style is right alignment.
#
# *Default*:: +false+
# Used in:: #format, #paragraphs
def right_align?
@format_style == RIGHT_ALIGN
end
# Indicates that the format style is right fill.
#
# *Default*:: +false+
# Used in:: #format, #paragraphs
def right_fill?
@format_style == RIGHT_FILL
end
# Indicates that the format style is full justification.
#
# *Default*:: +false+
# Used in:: #format, #paragraphs
def justify?
@format_style == JUSTIFY
end
# The formatting object itself can be used as a #hyphenator, where the
# default implementation of #hyphenate_to implements the conditions
# necessary to properly produce SPLIT_CONTINUATION.
def hyphenate_to(word, size)
if (size - 2) < 0
[nil, word]
else
[word[0 .. (size - 2)] + "\\", word[(size - 1) .. -1]]
end
end
# Splits the provided word so that it is in two parts, word[0 ..
# (size - 1)] and word[size .. -1].
def split_word_to(word, size)
[word[0 .. (size - 1)], word[size .. -1]]
end
# Formats text into a nice paragraph format. The text is separated into
# words and then reassembled a word at a time using the settings of this
# Format object.
#
# If +text+ is +nil+, then the value of #text will be worked on.
def format_one_paragraph(text = nil)
text ||= @text
text = text[0] if text.kind_of?(Array)
# Convert the provided paragraph to a list of words.
words = text.split(SPACES_RE).reverse.reject { |ww| ww.nil? or ww.empty? }
text = []
# Find the maximum line width and the initial indent string.
# TODO 20050114 - allow the left and right margins to be specified as
# strings. If they are strings, then we need to use the sizes of the
# strings. Also: allow the indent string to be set manually and
# indicate whether the indent string will have a following space.
max_line_width = @columns - @first_indent - @left_margin - @right_margin
indent_str = ' ' * @first_indent
first_line = true
if words.empty?
line = []
line_size = 0
extra_space = false
else
line = [ words.pop ]
line_size = line[-1].size
extra_space = __add_extra_space?(line[-1])
end
while next_word = words.pop
next_word.strip! unless next_word.nil?
new_line_size = (next_word.size + line_size) + 1
if extra_space
if (line[-1] !~ __sentence_end_re)
extra_space = false
end
end
# Increase the width of the new line if there's a sentence
# terminator and we are applying extra_space.
new_line_size += 1 if extra_space
# Will the word fit onto the current line? If so, simply append it
# to the end of the line.
if new_line_size <= max_line_width
if line.empty?
line << next_word
else
if extra_space
line << " #{next_word}"
else
line << " #{next_word}"
end
end
else
# Forcibly wrap the line if nonbreaking spaces are turned on and
# there is a condition where words must be wrapped. If we have
# returned more than one word, readjust the word list.
line, next_word = __wrap_line(line, next_word) if @nobreak
if next_word.kind_of?(Array)
if next_word.size > 1
words.push(*(next_word.reverse))
next_word = words.pop
else
next_word = next_word[0]
end
next_word.strip! unless next_word.nil?
end
# Check to see if the line needs to be hyphenated. If a word has a
# hyphen in it (e.g., "fixed-width"), then we can ALWAYS wrap at
# that hyphenation, even if #hard_margins is not turned on. More
# elaborate forms of hyphenation will only be performed if
# #hard_margins is turned on. If we have returned more than one
# word, readjust the word list.
line, new_line_size, next_word = __hyphenate(line, line_size, next_word, max_line_width)
if next_word.kind_of?(Array)
if next_word.size > 1
words.push(*(next_word.reverse))
next_word = words.pop
else
next_word = next_word[0]
end
next_word.strip! unless next_word.nil?
end
text << __make_line(line, indent_str, max_line_width, next_word.nil?) unless line.nil?
if first_line
first_line = false
max_line_width = @columns - @body_indent - @left_margin - @right_margin
indent_str = ' ' * @body_indent
end
if next_word.nil?
line = []
new_line_size = 0
else
line = [ next_word ]
new_line_size = next_word.size
end
end
line_size = new_line_size
extra_space = __add_extra_space?(next_word) unless next_word.nil?
end
loop do
break if line.nil? or line.empty?
line, line_size, ww = __hyphenate(line, line_size, ww, max_line_width)#if @hard_margins
text << __make_line(line, indent_str, max_line_width, ww.nil?)
line = ww
ww = nil
end
if (@tag_paragraph and (not text.empty?))
if @tag_cur.nil? or @tag_cur.empty?
@tag_cur = @tag_text[0]
end
fchar = /(\S)/o.match(text[0])[1]
white = text[0].index(fchar)
unless @tag_cur.nil?
if ((white - @left_margin - 1) > @tag_cur.size) then
white = @tag_cur.size + @left_margin
text[0].gsub!(/^ {#{white}}/, "#{' ' * @left_margin}#{@tag_cur}")
else
text.unshift("#{' ' * @left_margin}#{@tag_cur}\n")
end
end
end
text.join('')
end
alias format format_one_paragraph
# Considers each element of text (provided or internal) as a paragraph.
# If #first_indent is the same as #body_indent, then paragraphs will be
# separated by a single empty line in the result; otherwise, the
# paragraphs will follow immediately after each other. Uses #format to
# do the heavy lifting.
#
# If +to_wrap+ responds to #split, then it will be split into an array
# of elements by calling #split with the value of +split_on+. The
# default value of split_on is $/, or the default record separator,
# repeated twice (e.g., /\n\n/).
def paragraphs(to_wrap = nil, split_on = /(#{$/}){2}/o)
to_wrap = @text if to_wrap.nil?
if to_wrap.respond_to?(:split)
to_wrap = to_wrap.split(split_on)
else
to_wrap = [to_wrap].flatten
end
if ((@first_indent == @body_indent) or @tag_paragraph) then
p_end = NEWLINE
else
p_end = ''
end
cnt = 0
ret = []
to_wrap.each do |tw|
@tag_cur = @tag_text[cnt] if @tag_paragraph
@tag_cur = '' if @tag_cur.nil?
line = format(tw)
ret << "#{line}#{p_end}" if (not line.nil?) and (line.size > 0)
cnt += 1
end
ret[-1].chomp! unless ret.empty?
ret.join('')
end
# Centers the text, preserving empty lines and tabs.
def center(to_center = nil)
to_center = @text if to_center.nil?
to_center = [to_center].flatten
tabs = 0
width = @columns - @left_margin - @right_margin
centered = []
to_center.each do |tc|
s = tc.strip
tabs = s.count(TAB)
tabs = 0 if tabs.nil?
ct = ((width - s.size - (tabs * @tabstop) + tabs) / 2)
ct = (width - @left_margin - @right_margin) - ct
centered << "#{s.rjust(ct)}\n"
end
centered.join('')
end
# Replaces all tab characters in the text with #tabstop spaces.
def expand(to_expand = nil)
to_expand = @text if to_expand.nil?
tmp = ' ' * @tabstop
changer = lambda do |text|
res = text.split(NEWLINE_RE)
res.collect! { |ln| ln.gsub!(/\t/o, tmp) }
res.join(NEWLINE)
end
if to_expand.kind_of?(Array)
to_expand.collect { |te| changer[te] }
else
changer[to_expand]
end
end
# Replaces all occurrences of #tabstop consecutive spaces with a tab
# character.
def unexpand(to_unexpand = nil)
to_unexpand = @text if to_unexpand.nil?
tmp = / {#{@tabstop}}/
changer = lambda do |text|
res = text.split(NEWLINE_RE)
res.collect! { |ln| ln.gsub!(tmp, TAB) }
res.join(NEWLINE)
end
if to_unexpand.kind_of?(Array)
to_unexpand.collect { |tu| changer[tu] }
else
changer[to_unexpand]
end
end
# Return +true+ if the word may have an extra space added after it. This
# will only be the case if #extra_space is +true+ and the word is not an
# abbreviation.
def __add_extra_space?(word)
return false unless @extra_space
word = word.gsub(/\.$/o, '') unless word.nil?
return false if ABBREV.include?(word)
return false if @abbreviations.include?(word)
true
end
private :__add_extra_space?
def __make_line(line, indent, width, last = false) #:nodoc:
line_size = line.inject(0) { |ls, el| ls + el.size }
lmargin = " " * @left_margin
fill = " " * (width - line_size) if right_fill? and (line_size <= width)
unless last
if justify? and (line.size > 1)
spaces = width - line_size
word_spaces = spaces / (line.size / 2)
spaces = spaces % (line.size / 2) if word_spaces > 0
line.reverse.each do |word|
next if (word =~ /^\S/o)
word.sub!(/^/o, " " * word_spaces)
next unless (spaces > 0)
word.sub!(/^/o, " ")
spaces -= 1
end
end
end
line = "#{lmargin}#{indent}#{line.join('')}#{fill}\n" unless line.empty?
if right_align? and (not line.nil?)
line.sub(/^/o, " " * (@columns - @right_margin - (line.size - 1)))
else
line
end
end
# private :__make_line
def __hyphenate(line, line_size, next_word, width) #:nodoc:
return [ line, line_size, next_word ] if line.nil? or line.empty?
rline = line.dup
rsize = line_size
rnext = []
rnext << next_word.dup unless next_word.nil?
loop do
break if rnext.nil? or rline.nil?
if rsize == width
break
elsif rsize > width
word = rline.pop
size = width - rsize + word.size
if (size < 1)
rnext.unshift word
next
end
first = rest = nil
# TODO: Add the check to see if the word contains a hyphen to
# split on automatically.
# Does the word already have a hyphen in it? If so, try to use
# that to split the word.
# if word.index('-') < size
# first = word[0 ... word.index("-")]
# rest = word[word.index("-") .. -1]
# end
if @hard_margins
if first.nil? and (@split_rules & SPLIT_HYPHENATION) == SPLIT_HYPHENATION
if @hyphenator_arity == 2
first, rest = @hyphenator.hyphenate_to(word, size)
else
first, rest = @hyphenator.hyphenate_to(word, size, self)
end
end
if first.nil? and (@split_rules & SPLIT_CONTINUATION) == SPLIT_CONTINUATION
first, rest = self.hyphenate_to(word, size)
end
if first.nil?
if (@split_rules & SPLIT_FIXED) == SPLIT_FIXED
first, rest = split_word_to(word, size)
elsif (not rest.nil? and (rest.size > size))
first, rest = split_word_to(word, size)
end
end
else
first = word if first.nil?
end
if first.nil?
rest = word
else
rsize = rsize - word.size + first.size
if rline.empty?
rline << first
else
rsize += 1
rline << " #{first}"
end
@split_words << SplitWord.new(word, first, rest)
end
rnext.unshift rest unless rest.nil?
break
else
break if rnext.empty?
word = rnext.shift.dup
size = width - rsize - 1
if (size <= 0)
rnext.unshift word
break
end
first = rest = nil
# TODO: Add the check to see if the word contains a hyphen to
# split on automatically.
# Does the word already have a hyphen in it? If so, try to use
# that to split the word.
# if word.index('-') < size
# first = word[0 ... word.index("-")]
# rest = word[word.index("-") .. -1]
# end
if @hard_margins
if (@split_rules & SPLIT_HYPHENATION) == SPLIT_HYPHENATION
if @hyphenator_arity == 2
first, rest = @hyphenator.hyphenate_to(word, size)
else
first, rest = @hyphenator.hyphenate_to(word, size, self)
end
end
if first.nil? and (@split_rules & SPLIT_CONTINUATION) == SPLIT_CONTINUATION
first, rest = self.hyphenate_to(word, size)
end
if first.nil?
if (@split_rules & SPLIT_FIXED) == SPLIT_FIXED
first, rest = split_word_to(word, size)
elsif (not rest.nil? and (rest.size > width))
first, rest = split_word_to(word, size)
end
end
else
first = word if first.nil?
end
# The word was successfully split. Does it fit?
unless first.nil?
if (rsize + first.size) < width
@split_words << SplitWord.new(word, first, rest)
rsize += first.size + 1
rline << " #{first}"
else
rest = word
end
else
rest = word unless rest.nil?
end
rnext.unshift rest
break
end
end
[ rline, rsize, rnext ]
end
private :__hyphenate
# The line must be broken. Typically, this is done by moving the last
# word on the current line to the next line. However, it may be possible
# that certain combinations of words may not be broken (see
# #nobreak_regex for more information). Therefore, it may be necessary
# to move multiple words from the current line to the next line. This
# function does this.
def __wrap_line(line, next_word)
no_break = false
word_index = line.size - 1
@nobreak_regex.each_pair do |first, second|
if line[word_index] =~ first and next_word =~ second
no_break = true
end
end
# If the last word and the next word aren't to be broken, and the line
# has more than one word in it, then we need to go back by words to
# ensure that we break as allowed.
if no_break and word_index.nonzero?
word_index -= 1
while word_index.nonzero?
no_break = false
@nobreak_regex.each_pair { |first, second|
if line[word_index] =~ first and line[word_index + 1] =~ second
no_break = true
end
}
break unless no_break
word_index -= 1
end
if word_index.nonzero?
words = line.slice!(word_index .. -1)
words << next_word
end
end
[line, words]
end
private :__wrap_line
# Create a Text::Format object. Accepts an optional hash of construction
# options (this will be changed to named paramters in Ruby 2.0). After
# the initial object is constructed (with either the provided or default
# values), the object will be yielded (as +self+) to an optional block
# for further construction and operation.
def initialize(options = {}) #:yields self:
@text = options[:text] || []
@columns = options[:columns] || 72
@tabstop = options[:tabstop] || 8
@first_indent = options[:first_indent] || 4
@body_indent = options[:body_indent] || 0
@format_style = options[:format_style] || LEFT_ALIGN
@left_margin = options[:left_margin] || 0
@right_margin = options[:right_margin] || 0
@extra_space = options[:extra_space] || false
@tag_paragraph = options[:tag_paragraph] || false
@tag_text = options[:tag_text] || []
@abbreviations = options[:abbreviations] || []
@terminal_punctuation = options[:terminal_punctuation] || ""
@terminal_quotes = options[:terminal_quotes] || ""
@nobreak = options[:nobreak] || false
@nobreak_regex = options[:nobreak_regex] || {}
@hard_margins = options[:hard_margins] || false
@split_rules = options[:split_rules] || SPLIT_FIXED
@hyphenator = options[:hyphenator] || self
@hyphenator_arity = @hyphenator.method(:hyphenate_to).arity
@tag_cur = ""
@split_words = []
yield self if block_given?
end
end
text-format-1.0.0/lib/text/format/ 0000755 0001750 0001750 00000000000 11600332303 016317 5 ustar ondrej ondrej text-format-1.0.0/lib/text/format/alpha.rb 0000644 0001750 0001750 00000003673 11600332303 017742 0 ustar ondrej ondrej # Provides a numbering object that will produce letters. Accepts four
# options for numbering that will control how the letters are presented
# when given as #[](index). This numbering object will only provide 26
# values ("a" .. "z") unless :wrap is +true+.
#
# :transform:: The symbol representing the method to be called on
# the letter. This must be a method that does not
# require any arguments.
# :postfix:: The value that will be appended to the letter
# presented by #[]. Defaults to +nil+.
# :prefix:: The value that will be prepended to the letter
# presented by #[]. Defaults to +nil+.
# :wrap:: If +true+, then indexes will be wrapped from "z"
# to "a".
#
# a1 = Text::Format::Alpha.new(:postfix => ".")
# puts a1[0] # => "a."
# puts a1[1] # => "b.
# puts a1[27] # => ""
#
# a2 = Text::Format::Alpha.new(:prefix => "A.")
# puts a2[0] # => "A.a"
# puts a2[1] # => "A.b"
# puts a2[27] # => ""
#
# a3 = Text::Format::Alpha.new(:transform => :upcase)
# puts a3[0] # => "A"
# puts a3[1] # => "B"
# puts a3[27] # => ""
#
# a4 = Text::Format::Alpha.new(:wrap => true)
# puts a4[0] # => "a"
# puts a4[27] # => "b"
class Text::Format::Alpha
def [](index)
if @wrap
ltr = (?a + (index % 26)).chr
elsif index.between?(0, 25)
ltr = (?a + index).chr
else
ltr = nil
end
if ltr
if @transform
"#{@prefix}#{ltr.send(transform)}#{@postfix}"
else
"#{@prefix}#{ltr}#{@postfix}"
end
else
""
end
end
def initialize(options = {}) #:yields self:
@transform = options[:transform] || nil
@wrap = options[:wrap] || false
@postfix = options[:postfix] || nil
@prefix = options[:prefix] || nil
end
end
text-format-1.0.0/lib/text/format/number.rb 0000644 0001750 0001750 00000002375 11600332303 020143 0 ustar ondrej ondrej # Provides a numbering object that will produce numbers. Accepts three
# parameters for numbering that will control how the numbers are presented
# when given as #[](index).
#
# :offset:: The number to add to the index in order to produce
# the proper index. This is because #tag_text indexes
# from 0, not 1. This defaults to 1.
# :postfix:: The value that will be appended to the number
# presented by #[]. Defaults to +nil+.
# :prefix:: The value that will be prepended to the number
# presented by #[]. Defaults to +nil+.
#
# n1 = Text::Format::Number.new(:postfix => ".")
# puts n1[0] # => "1."
# puts n1[1] # => "2.
#
# n2 = Text::Format::Number.new(:prefix => "2.")
# puts n2[0] # => "2.1"
# puts n2[1] # => "2.2"
#
# n3 = Text::Format::Number.new(:offset => 3)
# puts n3[0] # => "3"
# puts n3[1] # => "4"
class Text::Format::Number
def [](index)
"#{@prefix}#{index + @offset}#{@postfix}"
end
def initialize(options = {}) #:yields self:
@offset = options[:offset].to_i || 1
@postfix = options[:postfix] || nil
@prefix = options[:prefix] || nil
end
end
text-format-1.0.0/lib/text/format/roman.rb 0000644 0001750 0001750 00000005232 11600332303 017762 0 ustar ondrej ondrej # Provides a numbering object that will produce numbers. Accepts three
# parameters for numbering that will control how the numbers are presented
# when given as #[](index).
#
# :offset:: The number to add to the index in order to produce
# the proper index. This is because #tag_text indexes
# from 0, not 1. This defaults to 1. Any value less
# than 1 will be set to 1 (because Romans did not know
# about zero or negative numbers).
# :lower:: Renders the Roman numerals in lowercase if +true+.
# Defaults to +false+.
# :postfix:: The value that will be appended to the number
# presented by #[]. Defaults to +nil+.
# :prefix:: The value that will be prepended to the number
# presented by #[]. Defaults to +nil+.
#
# r1 = Text::Format::Roman.new(:postfix => ".")
# puts r1[0] # => "I."
# puts r1[8] # => "IX.
#
# r2 = Text::Format::Roman.new(:prefix => "M.")
# puts r2[0] # => "M.I"
# puts r2[8] # => "M.IX"
#
# r3 = Text::Format::Roman.new(:offset => 3)
# puts r3[0] # => "III"
# puts r3[9] # => "XII"
#
# r4 = Text::Format::Roman.new(:offset => 0)
# puts r4[0] # => "I"
# puts r4[8] # => "IX"
#
# r5 = Text::Format::Roman.new(:lower => true)
# puts r5[0] # => "i"
# puts r5[8] # => "ix"
class Text::Format::Roman
def [](index)
roman = ""
index += @offset
# Do 1,000s
roman << "M" * (index / 1000)
index %= 1000
# Do 900s
roman << "CM" * (index / 900)
index %= 900
# Do 500s
roman << "D" * (index / 500)
index %= 500
# Do 400s
roman << "CD" * (index / 400)
index %= 400
# Do 100s
roman << "C" * (index / 100)
index %= 100
# Do 90s
roman << "XC" * (index / 90)
index %= 90
# Do 50s
roman << "L" * (index / 50)
index %= 50
# Do 40s
roman << "XL" * (index / 40)
index %= 40
# Do 10s
roman << "X" * (index / 10)
index %= 10
# Do 9s
roman << "IX" * (index / 9)
index %= 9
# Do 5s
roman << "V" * (index / 5)
index %= 5
# Do 4s
roman << "IV" * (index / 4)
index %= 4
# Do 1s
roman << "I" * index
roman.downcase! if @lower
"#{@prefix}#{roman}#{@postfix}"
end
def initialize(options = {})
@offset = options[:offset].to_i || 1
@lower = options[:lower] || false
@postfix = options[:postfix] || nil
@prefix = options[:prefix] || nil
@offset = 1 if @offset < 1
end
end
text-format-1.0.0/Changelog 0000644 0001750 0001750 00000010606 11600332303 015112 0 ustar ondrej ondrej == Text::Format 1.0.0
* Changed installer: added a .gem package.
* Changed installer: moving to a variant of setup.rb by Minero Aoki.
* Fixed significant problems with #hard_margin wrapping and fallback issues,
eliminating all known possibilities for an infinite loop in wrapping. Some
of the formatting changes involved with this result in different and more
subtle wrapping and splitting of words; please read the full documentation
for details.
* Clarified the API for #hyphenate_to (delineated the return value required if
the hyphenator cannot hyphenate the word to the specified size).
* Changed a number of public and private API calls to work better. As long as
the constants provided by Text::Format have been used (and not direct access
to the constant values), there will be no issues presented by most of these
changes.
* Changed the initialization of the Text::Format object. The documentation has
also been updated to be correct. Note that this will mean that some uses of
Text::Format will not work, as Text::Format.new now yields +self+ if a block
is given instead of evaluating the block with Object#instance_eval.
* Added text numbering generators (Text::Format::Alpha, Text::Format::Number,
and Text::Format::Roman) to work with #tag_paragraphs and #tag_text to
generate numbered paragraphs.
* #nobreak_regex must be a hash of regular expressions, not strings that are
converted to regular expressions. This Perlism has finally been removed.
* The performance has been improved; the number of times that lines are joined
together and then split apart has been reduced.
* Changed the dependency to Text::Hyphen from TeX::Hyphen.
* Added auto-split capabilities to #paragraphs. See the updated documentation.
== Text::Format 0.64
* Fixed a bug where a NoMethod exception would be raised if #paragraphs was
called with either (" ") or ([" "]).
== Text::Format 0.63
* Fixed a bug where a crash would occur when a hyphenator returned nil instead
of "".
== Text::Format 0.62
* Modified the API for hyphenators. Previously, a hyphenator could only be
defined as an object containing a method #hyphenate_to with the signature:
#hyphenate_to(word, size)
Now, the #hyphenate_to method may be the above signature or:
#hyphenate_to(word, size, formatter)
So that the hyphenator may access information about the formatting object,
if necessary. Thanks to Tim Bates for suggesting a case where this would be
useful.
* Fixed a bug for strings matching /\A\s*\Z/ raising a NameError.
* Fixed a test case that failed uner 1.6.8. The following no longer works:
l, m1, m2 = /((?:\S+\s+){11})(.+)/.match(line)
This has been replaced with an explicit use of l[1] and l[2]. Thanks to Tim
Bates for finding this problem.
* Changed installer to Phil Thomson's install-package wrapper.
== Text::Format 0.61
* Fixed a problem with the installer. Note that Text::Format is no longer case
sensitive for require purposes. It will be required as:
require 'text/format'
Versions earlier than 0.60 were case-sensitive. Please be aware of this if
you are installing Text::Format over an older version. It may not replace
the existing library in the way that you expect.
== Text::Format 0.60
* Added Symbol equivalents for the Hash initialization. Hash initialization
has been modified so that values are set as follows (Symbols are highest
priority; strings are middle; defaults are lowest):
@columns = arg[:columns] || arg['columns'] || @columns
* Fixed a problem with Text::Format::RIGHT_FILL handling where a single word
is larger than #columns.
* Removed Comparable mixin (<=> doesn't make sense; == does).
* Added #hard_margins, #split_rules, #hyphenator, and #split_words. Text
formatted with #hard_margins will have words larger than #columns split
forcibly. Words forcibly split will be placed into #split_words. See the
documentation for important information on how this feature works.
== Text::Format 0.52.2
* Fixed the ordering of #<=> in cases of Boolean values.
* Fixed #expand and #unexpand Array handling.
* Added a Changelog.
== Text::Format 0.52.1
* Fixed a problem when tabs aren't counted properly.
* Changed #abbreviations from Hash to Array to better suit Ruby's
capabilities.
* Fixed problems with the way that Array arguments are handled in calls to the
major object types.
== Text::Format 0.52
* Initial release
$Id: Changelog,v 1.6 2005/06/24 19:49:09 austin Exp $
text-format-1.0.0/Install 0000644 0001750 0001750 00000000265 11600332303 014631 0 ustar ondrej ondrej Installing this package is as simple as:
% ruby setup.rb
Alternatively, you can use the RubyGem version of Text::Format available as
text-format-1.0.0.gem from the usual sources.
text-format-1.0.0/metadata.yml 0000644 0001750 0001750 00000003373 11600332303 015606 0 ustar ondrej ondrej --- !ruby/object:Gem::Specification
rubygems_version: 0.8.10
specification_version: 1
name: text-format
version: !ruby/object:Gem::Version
version: 1.0.0
date: 2005-06-24
summary: Text::Format formats fixed-width text nicely.
require_paths:
- lib
email: austin@rubyforge.org
homepage: http://rubyforge.org/projects/text-format
rubyforge_project: text-format
description: "Text::Format is provides the ability to nicely format fixed-width text with
knowledge of the writeable space (number of columns), margins, and indentation
settings. Text::Format can work with either TeX::Hyphen or Text::Hyphen to
hyphenate words when formatting."
autorequire: text/format
default_executable:
bindir: bin
has_rdoc: true
required_ruby_version: !ruby/object:Gem::Version::Requirement
requirements:
-
- ">"
- !ruby/object:Gem::Version
version: 0.0.0
version:
platform: ruby
authors:
- Austin Ziegler
files:
- Changelog
- Install
- lib
- metaconfig
- pre-setup.rb
- Rakefile
- README
- setup.rb
- tests
- ToDo
- lib/text
- lib/text/format
- lib/text/format.rb
- lib/text/format/alpha.rb
- lib/text/format/number.rb
- lib/text/format/roman.rb
- tests/tc_text_format.rb
- tests/testall.rb
test_files:
- tests/tc_text_format.rb
rdoc_options:
- "--title"
- Text::Format
- "--main"
- README
- "--line-numbers"
extra_rdoc_files:
- README
- Changelog
- Install
executables: []
extensions: []
requirements: []
dependencies:
- !ruby/object:Gem::Dependency
name: text-hyphen
version_requirement:
version_requirements: !ruby/object:Gem::Version::Requirement
requirements:
-
- "~>"
- !ruby/object:Gem::Version
version: 1.0.0
version: text-format-1.0.0/setup.rb 0000644 0001750 0001750 00000071372 11600332303 014774 0 ustar ondrej ondrej #
# setup.rb
#
# Copyright (c) 2000-2004 Minero Aoki
#
# This program is free software.
# You can distribute/modify this program under the terms of
# the GNU LGPL, Lesser General Public License version 2.1.
#
unless Enumerable.method_defined?(:map) # Ruby 1.4.6
module Enumerable
alias map collect
end
end
unless File.respond_to?(:read) # Ruby 1.6
def File.read(fname)
open(fname) {|f|
return f.read
}
end
end
def File.binread(fname)
open(fname, 'rb') {|f|
return f.read
}
end
# for corrupted windows stat(2)
def File.dir?(path)
File.directory?((path[-1,1] == '/') ? path : path + '/')
end
class SetupError < StandardError; end
def setup_rb_error(msg)
raise SetupError, msg
end
#
# Config
#
if arg = ARGV.detect {|arg| /\A--rbconfig=/ =~ arg }
ARGV.delete(arg)
require arg.split(/=/, 2)[1]
$".push 'rbconfig.rb'
else
require 'rbconfig'
end
def multipackage_install?
FileTest.directory?(File.dirname($0) + '/packages')
end
class ConfigItem
def initialize(name, template, default, desc)
@name = name.freeze
@template = template
@value = default
@default = default.dup.freeze
@description = desc
end
attr_reader :name
attr_reader :description
attr_accessor :default
alias help_default default
def help_opt
"--#{@name}=#{@template}"
end
def value
@value
end
def eval(table)
@value.gsub(%r<\$([^/]+)>) { table[$1] }
end
def set(val)
@value = check(val)
end
private
def check(val)
setup_rb_error "config: --#{name} requires argument" unless val
val
end
end
class BoolItem < ConfigItem
def config_type
'bool'
end
def help_opt
"--#{@name}"
end
private
def check(val)
return 'yes' unless val
unless /\A(y(es)?|n(o)?|t(rue)?|f(alse))\z/i =~ val
setup_rb_error "config: --#{@name} accepts only yes/no for argument"
end
(/\Ay(es)?|\At(rue)/i =~ value) ? 'yes' : 'no'
end
end
class PathItem < ConfigItem
def config_type
'path'
end
private
def check(path)
setup_rb_error "config: --#{@name} requires argument" unless path
path[0,1] == '$' ? path : File.expand_path(path)
end
end
class ProgramItem < ConfigItem
def config_type
'program'
end
end
class SelectItem < ConfigItem
def initialize(name, template, default, desc)
super
@ok = template.split('/')
end
def config_type
'select'
end
private
def check(val)
unless @ok.include?(val.strip)
setup_rb_error "config: use --#{@name}=#{@template} (#{val})"
end
val.strip
end
end
class PackageSelectionItem < ConfigItem
def initialize(name, template, default, help_default, desc)
super name, template, default, desc
@help_default = help_default
end
attr_reader :help_default
def config_type
'package'
end
private
def check(val)
unless File.dir?("packages/#{val}")
setup_rb_error "config: no such package: #{val}"
end
val
end
end
class ConfigTable_class
def initialize(items)
@items = items
@table = {}
items.each do |i|
@table[i.name] = i
end
ALIASES.each do |ali, name|
@table[ali] = @table[name]
end
@script_extensions = ['rb']
end
attr_accessor :script_extensions
include Enumerable
def each(&block)
@items.each(&block)
end
def key?(name)
@table.key?(name)
end
def lookup(name)
@table[name] or raise ArgumentError, "no such config item: #{name}"
end
def add(item)
@items.push item
@table[item.name] = item
end
def remove(name)
item = lookup(name)
@items.delete_if {|i| i.name == name }
@table.delete_if {|name, i| i.name == name }
item
end
def new
dup()
end
def savefile
'.config'
end
def load
begin
t = dup()
File.foreach(savefile()) do |line|
k, v = *line.split(/=/, 2)
t[k] = v.strip
end
t
rescue Errno::ENOENT
setup_rb_error $!.message + "#{File.basename($0)} config first"
end
end
def save
@items.each {|i| i.value }
File.open(savefile(), 'w') {|f|
@items.each do |i|
f.printf "%s=%s\n", i.name, i.value if i.value
end
}
end
def [](key)
lookup(key).eval(self)
end
def []=(key, val)
lookup(key).set val
end
end
c = ::Config::CONFIG
rubypath = c['bindir'] + '/' + c['ruby_install_name']
major = c['MAJOR'].to_i
minor = c['MINOR'].to_i
teeny = c['TEENY'].to_i
version = "#{major}.#{minor}"
# ruby ver. >= 1.4.4?
newpath_p = ((major >= 2) or
((major == 1) and
((minor >= 5) or
((minor == 4) and (teeny >= 4)))))
if c['rubylibdir']
# V < 1.6.3
_stdruby = c['rubylibdir']
_siteruby = c['sitedir']
_siterubyver = c['sitelibdir']
_siterubyverarch = c['sitearchdir']
elsif newpath_p
# 1.4.4 <= V <= 1.6.3
_stdruby = "$prefix/lib/ruby/#{version}"
_siteruby = c['sitedir']
_siterubyver = "$siteruby/#{version}"
_siterubyverarch = "$siterubyver/#{c['arch']}"
else
# V < 1.4.4
_stdruby = "$prefix/lib/ruby/#{version}"
_siteruby = "$prefix/lib/ruby/#{version}/site_ruby"
_siterubyver = _siteruby
_siterubyverarch = "$siterubyver/#{c['arch']}"
end
libdir = '-* dummy libdir *-'
stdruby = '-* dummy rubylibdir *-'
siteruby = '-* dummy site_ruby *-'
siterubyver = '-* dummy site_ruby version *-'
parameterize = lambda {|path|
path.sub(/\A#{Regexp.quote(c['prefix'])}/, '$prefix')\
.sub(/\A#{Regexp.quote(libdir)}/, '$libdir')\
.sub(/\A#{Regexp.quote(stdruby)}/, '$stdruby')\
.sub(/\A#{Regexp.quote(siteruby)}/, '$siteruby')\
.sub(/\A#{Regexp.quote(siterubyver)}/, '$siterubyver')
}
libdir = parameterize.call(c['libdir'])
stdruby = parameterize.call(_stdruby)
siteruby = parameterize.call(_siteruby)
siterubyver = parameterize.call(_siterubyver)
siterubyverarch = parameterize.call(_siterubyverarch)
if arg = c['configure_args'].split.detect {|arg| /--with-make-prog=/ =~ arg }
makeprog = arg.sub(/'/, '').split(/=/, 2)[1]
else
makeprog = 'make'
end
common_conf = [
PathItem.new('prefix', 'path', c['prefix'],
'path prefix of target environment'),
PathItem.new('bindir', 'path', parameterize.call(c['bindir']),
'the directory for commands'),
PathItem.new('libdir', 'path', libdir,
'the directory for libraries'),
PathItem.new('datadir', 'path', parameterize.call(c['datadir']),
'the directory for shared data'),
PathItem.new('mandir', 'path', parameterize.call(c['mandir']),
'the directory for man pages'),
PathItem.new('sysconfdir', 'path', parameterize.call(c['sysconfdir']),
'the directory for man pages'),
PathItem.new('stdruby', 'path', stdruby,
'the directory for standard ruby libraries'),
PathItem.new('siteruby', 'path', siteruby,
'the directory for version-independent aux ruby libraries'),
PathItem.new('siterubyver', 'path', siterubyver,
'the directory for aux ruby libraries'),
PathItem.new('siterubyverarch', 'path', siterubyverarch,
'the directory for aux ruby binaries'),
PathItem.new('rbdir', 'path', '$siterubyver',
'the directory for ruby scripts'),
PathItem.new('sodir', 'path', '$siterubyverarch',
'the directory for ruby extentions'),
PathItem.new('rubypath', 'path', rubypath,
'the path to set to #! line'),
ProgramItem.new('rubyprog', 'name', rubypath,
'the ruby program using for installation'),
ProgramItem.new('makeprog', 'name', makeprog,
'the make program to compile ruby extentions'),
SelectItem.new('shebang', 'all/ruby/never', 'ruby',
'shebang line (#!) editing mode'),
BoolItem.new('without-ext', 'yes/no', 'no',
'does not compile/install ruby extentions')
]
class ConfigTable_class # open again
ALIASES = {
'std-ruby' => 'stdruby',
'site-ruby-common' => 'siteruby', # For backward compatibility
'site-ruby' => 'siterubyver', # For backward compatibility
'bin-dir' => 'bindir',
'bin-dir' => 'bindir',
'rb-dir' => 'rbdir',
'so-dir' => 'sodir',
'data-dir' => 'datadir',
'ruby-path' => 'rubypath',
'ruby-prog' => 'rubyprog',
'ruby' => 'rubyprog',
'make-prog' => 'makeprog',
'make' => 'makeprog'
}
end
multipackage_conf = [
PackageSelectionItem.new('with', 'name,name...', '', 'ALL',
'package names that you want to install'),
PackageSelectionItem.new('without', 'name,name...', '', 'NONE',
'package names that you do not want to install')
]
if multipackage_install?
ConfigTable = ConfigTable_class.new(common_conf + multipackage_conf)
else
ConfigTable = ConfigTable_class.new(common_conf)
end
module MetaConfigAPI
def eval_file_ifexist(fname)
instance_eval File.read(fname), fname, 1 if File.file?(fname)
end
def config_names
ConfigTable.map {|i| i.name }
end
def config?(name)
ConfigTable.key?(name)
end
def bool_config?(name)
ConfigTable.lookup(name).config_type == 'bool'
end
def path_config?(name)
ConfigTable.lookup(name).config_type == 'path'
end
def value_config?(name)
case ConfigTable.lookup(name).config_type
when 'bool', 'path'
true
else
false
end
end
def add_config(item)
ConfigTable.add item
end
def add_bool_config(name, default, desc)
ConfigTable.add BoolItem.new(name, 'yes/no', default ? 'yes' : 'no', desc)
end
def add_path_config(name, default, desc)
ConfigTable.add PathItem.new(name, 'path', default, desc)
end
def set_config_default(name, default)
ConfigTable.lookup(name).default = default
end
def remove_config(name)
ConfigTable.remove(name)
end
def add_script_extension(ext)
ConfigTable.script_extensions << ext
end
end
#
# File Operations
#
module FileOperations
def mkdir_p(dirname, prefix = nil)
dirname = prefix + File.expand_path(dirname) if prefix
$stderr.puts "mkdir -p #{dirname}" if verbose?
return if no_harm?
# does not check '/'... it's too abnormal case
dirs = File.expand_path(dirname).split(%r<(?=/)>)
if /\A[a-z]:\z/i =~ dirs[0]
disk = dirs.shift
dirs[0] = disk + dirs[0]
end
dirs.each_index do |idx|
path = dirs[0..idx].join('')
Dir.mkdir path unless File.dir?(path)
end
end
def rm_f(fname)
$stderr.puts "rm -f #{fname}" if verbose?
return if no_harm?
if File.exist?(fname) or File.symlink?(fname)
File.chmod 0777, fname
File.unlink fname
end
end
def rm_rf(dn)
$stderr.puts "rm -rf #{dn}" if verbose?
return if no_harm?
Dir.chdir dn
Dir.foreach('.') do |fn|
next if fn == '.'
next if fn == '..'
if File.dir?(fn)
verbose_off {
rm_rf fn
}
else
verbose_off {
rm_f fn
}
end
end
Dir.chdir '..'
Dir.rmdir dn
end
def move_file(src, dest)
File.unlink dest if File.exist?(dest)
begin
File.rename src, dest
rescue
File.open(dest, 'wb') {|f| f.write File.binread(src) }
File.chmod File.stat(src).mode, dest
File.unlink src
end
end
def install(from, dest, mode, prefix = nil)
$stderr.puts "install #{from} #{dest}" if verbose?
return if no_harm?
realdest = prefix ? prefix + File.expand_path(dest) : dest
realdest = File.join(realdest, File.basename(from)) if File.dir?(realdest)
str = File.binread(from)
if diff?(str, realdest)
verbose_off {
rm_f realdest if File.exist?(realdest)
}
File.open(realdest, 'wb') {|f|
f.write str
}
File.chmod mode, realdest
File.open("#{objdir_root()}/InstalledFiles", 'a') {|f|
if prefix
f.puts realdest.sub(prefix, '')
else
f.puts realdest
end
}
end
end
def diff?(new_content, path)
return true unless File.exist?(path)
new_content != File.binread(path)
end
def command(str)
$stderr.puts str if verbose?
system str or raise RuntimeError, "'system #{str}' failed"
end
def ruby(str)
command config('rubyprog') + ' ' + str
end
def make(task = '')
command config('makeprog') + ' ' + task
end
def extdir?(dir)
File.exist?(dir + '/MANIFEST')
end
def all_files_in(dirname)
Dir.open(dirname) {|d|
return d.select {|ent| File.file?("#{dirname}/#{ent}") }
}
end
REJECT_DIRS = %w(
CVS SCCS RCS CVS.adm .svn
)
def all_dirs_in(dirname)
Dir.open(dirname) {|d|
return d.select {|n| File.dir?("#{dirname}/#{n}") } - %w(. ..) - REJECT_DIRS
}
end
end
#
# Main Installer
#
module HookUtils
def run_hook(name)
try_run_hook "#{curr_srcdir()}/#{name}" or
try_run_hook "#{curr_srcdir()}/#{name}.rb"
end
def try_run_hook(fname)
return false unless File.file?(fname)
begin
instance_eval File.read(fname), fname, 1
rescue
setup_rb_error "hook #{fname} failed:\n" + $!.message
end
true
end
end
module HookScriptAPI
def get_config(key)
@config[key]
end
alias config get_config
def set_config(key, val)
@config[key] = val
end
#
# srcdir/objdir (works only in the package directory)
#
#abstract srcdir_root
#abstract objdir_root
#abstract relpath
def curr_srcdir
"#{srcdir_root()}/#{relpath()}"
end
def curr_objdir
"#{objdir_root()}/#{relpath()}"
end
def srcfile(path)
"#{curr_srcdir()}/#{path}"
end
def srcexist?(path)
File.exist?(srcfile(path))
end
def srcdirectory?(path)
File.dir?(srcfile(path))
end
def srcfile?(path)
File.file? srcfile(path)
end
def srcentries(path = '.')
Dir.open("#{curr_srcdir()}/#{path}") {|d|
return d.to_a - %w(. ..)
}
end
def srcfiles(path = '.')
srcentries(path).select {|fname|
File.file?(File.join(curr_srcdir(), path, fname))
}
end
def srcdirectories(path = '.')
srcentries(path).select {|fname|
File.dir?(File.join(curr_srcdir(), path, fname))
}
end
end
class ToplevelInstaller
Version = '3.3.1'
Copyright = 'Copyright (c) 2000-2004 Minero Aoki'
TASKS = [
[ 'all', 'do config, setup, then install' ],
[ 'config', 'saves your configurations' ],
[ 'show', 'shows current configuration' ],
[ 'setup', 'compiles ruby extentions and others' ],
[ 'install', 'installs files' ],
[ 'clean', "does `make clean' for each extention" ],
[ 'distclean',"does `make distclean' for each extention" ]
]
def ToplevelInstaller.invoke
instance().invoke
end
@singleton = nil
def ToplevelInstaller.instance
@singleton ||= new(File.dirname($0))
@singleton
end
include MetaConfigAPI
def initialize(ardir_root)
@config = nil
@options = { 'verbose' => true }
@ardir = File.expand_path(ardir_root)
end
def inspect
"#<#{self.class} #{__id__()}>"
end
def invoke
run_metaconfigs
case task = parsearg_global()
when nil, 'all'
@config = load_config('config')
parsearg_config
init_installers
exec_config
exec_setup
exec_install
else
@config = load_config(task)
__send__ "parsearg_#{task}"
init_installers
__send__ "exec_#{task}"
end
end
def run_metaconfigs
eval_file_ifexist "#{@ardir}/metaconfig"
end
def load_config(task)
case task
when 'config'
ConfigTable.new
when 'clean', 'distclean'
if File.exist?(ConfigTable.savefile)
then ConfigTable.load
else ConfigTable.new
end
else
ConfigTable.load
end
end
def init_installers
@installer = Installer.new(@config, @options, @ardir, File.expand_path('.'))
end
#
# Hook Script API bases
#
def srcdir_root
@ardir
end
def objdir_root
'.'
end
def relpath
'.'
end
#
# Option Parsing
#
def parsearg_global
valid_task = /\A(?:#{TASKS.map {|task,desc| task }.join '|'})\z/
while arg = ARGV.shift
case arg
when /\A\w+\z/
setup_rb_error "invalid task: #{arg}" unless valid_task =~ arg
return arg
when '-q', '--quiet'
@options['verbose'] = false
when '--verbose'
@options['verbose'] = true
when '-h', '--help'
print_usage $stdout
exit 0
when '-v', '--version'
puts "#{File.basename($0)} version #{Version}"
exit 0
when '--copyright'
puts Copyright
exit 0
else
setup_rb_error "unknown global option '#{arg}'"
end
end
nil
end
def parsearg_no_options
unless ARGV.empty?
setup_rb_error "#{task}: unknown options: #{ARGV.join ' '}"
end
end
alias parsearg_show parsearg_no_options
alias parsearg_setup parsearg_no_options
alias parsearg_clean parsearg_no_options
alias parsearg_distclean parsearg_no_options
def parsearg_config
re = /\A--(#{ConfigTable.map {|i| i.name }.join('|')})(?:=(.*))?\z/
@options['config-opt'] = []
while i = ARGV.shift
if /\A--?\z/ =~ i
@options['config-opt'] = ARGV.dup
break
end
m = re.match(i) or setup_rb_error "config: unknown option #{i}"
name, value = *m.to_a[1,2]
@config[name] = value
end
end
def parsearg_install
@options['no-harm'] = false
@options['install-prefix'] = ''
while a = ARGV.shift
case a
when /\A--no-harm\z/
@options['no-harm'] = true
when /\A--prefix=(.*)\z/
path = $1
path = File.expand_path(path) unless path[0,1] == '/'
@options['install-prefix'] = path
else
setup_rb_error "install: unknown option #{a}"
end
end
end
def print_usage(out)
out.puts 'Typical Installation Procedure:'
out.puts " $ ruby #{File.basename $0} config"
out.puts " $ ruby #{File.basename $0} setup"
out.puts " # ruby #{File.basename $0} install (may require root privilege)"
out.puts
out.puts 'Detailed Usage:'
out.puts " ruby #{File.basename $0} "
out.puts " ruby #{File.basename $0} [] []"
fmt = " %-24s %s\n"
out.puts
out.puts 'Global options:'
out.printf fmt, '-q,--quiet', 'suppress message outputs'
out.printf fmt, ' --verbose', 'output messages verbosely'
out.printf fmt, '-h,--help', 'print this message'
out.printf fmt, '-v,--version', 'print version and quit'
out.printf fmt, ' --copyright', 'print copyright and quit'
out.puts
out.puts 'Tasks:'
TASKS.each do |name, desc|
out.printf fmt, name, desc
end
fmt = " %-24s %s [%s]\n"
out.puts
out.puts 'Options for CONFIG or ALL:'
ConfigTable.each do |item|
out.printf fmt, item.help_opt, item.description, item.help_default
end
out.printf fmt, '--rbconfig=path', 'rbconfig.rb to load',"running ruby's"
out.puts
out.puts 'Options for INSTALL:'
out.printf fmt, '--no-harm', 'only display what to do if given', 'off'
out.printf fmt, '--prefix=path', 'install path prefix', '$prefix'
out.puts
end
#
# Task Handlers
#
def exec_config
@installer.exec_config
@config.save # must be final
end
def exec_setup
@installer.exec_setup
end
def exec_install
@installer.exec_install
end
def exec_show
ConfigTable.each do |i|
printf "%-20s %s\n", i.name, i.value
end
end
def exec_clean
@installer.exec_clean
end
def exec_distclean
@installer.exec_distclean
end
end
class ToplevelInstallerMulti < ToplevelInstaller
include HookUtils
include HookScriptAPI
include FileOperations
def initialize(ardir)
super
@packages = all_dirs_in("#{@ardir}/packages")
raise 'no package exists' if @packages.empty?
end
def run_metaconfigs
eval_file_ifexist "#{@ardir}/metaconfig"
@packages.each do |name|
eval_file_ifexist "#{@ardir}/packages/#{name}/metaconfig"
end
end
def init_installers
@installers = {}
@packages.each do |pack|
@installers[pack] = Installer.new(@config, @options,
"#{@ardir}/packages/#{pack}",
"packages/#{pack}")
end
with = extract_selection(config('with'))
without = extract_selection(config('without'))
@selected = @installers.keys.select {|name|
(with.empty? or with.include?(name)) \
and not without.include?(name)
}
end
def extract_selection(list)
a = list.split(/,/)
a.each do |name|
setup_rb_error "no such package: #{name}" unless @installers.key?(name)
end
a
end
def print_usage(f)
super
f.puts 'Inluded packages:'
f.puts ' ' + @packages.sort.join(' ')
f.puts
end
#
# multi-package metaconfig API
#
attr_reader :packages
def declare_packages(list)
raise 'package list is empty' if list.empty?
list.each do |name|
raise "directory packages/#{name} does not exist"\
unless File.dir?("#{@ardir}/packages/#{name}")
end
@packages = list
end
#
# Task Handlers
#
def exec_config
run_hook 'pre-config'
each_selected_installers {|inst| inst.exec_config }
run_hook 'post-config'
@config.save # must be final
end
def exec_setup
run_hook 'pre-setup'
each_selected_installers {|inst| inst.exec_setup }
run_hook 'post-setup'
end
def exec_install
run_hook 'pre-install'
each_selected_installers {|inst| inst.exec_install }
run_hook 'post-install'
end
def exec_clean
rm_f ConfigTable.savefile
run_hook 'pre-clean'
each_selected_installers {|inst| inst.exec_clean }
run_hook 'post-clean'
end
def exec_distclean
rm_f ConfigTable.savefile
run_hook 'pre-distclean'
each_selected_installers {|inst| inst.exec_distclean }
run_hook 'post-distclean'
end
#
# lib
#
def each_selected_installers
Dir.mkdir 'packages' unless File.dir?('packages')
@selected.each do |pack|
$stderr.puts "Processing the package `#{pack}' ..." if @options['verbose']
Dir.mkdir "packages/#{pack}" unless File.dir?("packages/#{pack}")
Dir.chdir "packages/#{pack}"
yield @installers[pack]
Dir.chdir '../..'
end
end
def verbose?
@options['verbose']
end
def no_harm?
@options['no-harm']
end
end
class Installer
FILETYPES = %w( bin lib ext data )
include HookScriptAPI
include HookUtils
include FileOperations
def initialize(config, opt, srcroot, objroot)
@config = config
@options = opt
@srcdir = File.expand_path(srcroot)
@objdir = File.expand_path(objroot)
@currdir = '.'
end
def inspect
"#<#{self.class} #{File.basename(@srcdir)}>"
end
#
# Hook Script API base methods
#
def srcdir_root
@srcdir
end
def objdir_root
@objdir
end
def relpath
@currdir
end
#
# configs/options
#
def no_harm?
@options['no-harm']
end
def verbose?
@options['verbose']
end
def verbose_off
begin
save, @options['verbose'] = @options['verbose'], false
yield
ensure
@options['verbose'] = save
end
end
#
# TASK config
#
def exec_config
exec_task_traverse 'config'
end
def config_dir_bin(rel)
end
def config_dir_lib(rel)
end
def config_dir_ext(rel)
extconf if extdir?(curr_srcdir())
end
def extconf
opt = @options['config-opt'].join(' ')
command "#{config('rubyprog')} #{curr_srcdir()}/extconf.rb #{opt}"
end
def config_dir_data(rel)
end
#
# TASK setup
#
def exec_setup
exec_task_traverse 'setup'
end
def setup_dir_bin(rel)
all_files_in(curr_srcdir()).each do |fname|
adjust_shebang "#{curr_srcdir()}/#{fname}"
end
end
def adjust_shebang(path)
return if no_harm?
tmpfile = File.basename(path) + '.tmp'
begin
File.open(path, 'rb') {|r|
first = r.gets
return unless File.basename(config('rubypath')) == 'ruby'
return unless File.basename(first.sub(/\A\#!/, '').split[0]) == 'ruby'
$stderr.puts "adjusting shebang: #{File.basename(path)}" if verbose?
File.open(tmpfile, 'wb') {|w|
w.print first.sub(/\A\#!\s*\S+/, '#! ' + config('rubypath'))
w.write r.read
}
move_file tmpfile, File.basename(path)
}
ensure
File.unlink tmpfile if File.exist?(tmpfile)
end
end
def setup_dir_lib(rel)
end
def setup_dir_ext(rel)
make if extdir?(curr_srcdir())
end
def setup_dir_data(rel)
end
#
# TASK install
#
def exec_install
rm_f 'InstalledFiles'
exec_task_traverse 'install'
end
def install_dir_bin(rel)
install_files collect_filenames_auto(), "#{config('bindir')}/#{rel}", 0755
end
def install_dir_lib(rel)
install_files ruby_scripts(), "#{config('rbdir')}/#{rel}", 0644
end
def install_dir_ext(rel)
return unless extdir?(curr_srcdir())
install_files ruby_extentions('.'),
"#{config('sodir')}/#{File.dirname(rel)}",
0555
end
def install_dir_data(rel)
install_files collect_filenames_auto(), "#{config('datadir')}/#{rel}", 0644
end
def install_files(list, dest, mode)
mkdir_p dest, @options['install-prefix']
list.each do |fname|
install fname, dest, mode, @options['install-prefix']
end
end
def ruby_scripts
collect_filenames_auto().select {|n| /\.(#{ConfigTable.script_extensions.join('|')})\z/ =~ n }
end
# picked up many entries from cvs-1.11.1/src/ignore.c
reject_patterns = %w(
core RCSLOG tags TAGS .make.state
.nse_depinfo #* .#* cvslog.* ,* .del-* *.olb
*~ *.old *.bak *.BAK *.orig *.rej _$* *$
*.org *.in .*
)
mapping = {
'.' => '\.',
'$' => '\$',
'#' => '\#',
'*' => '.*'
}
REJECT_PATTERNS = Regexp.new('\A(?:' +
reject_patterns.map {|pat|
pat.gsub(/[\.\$\#\*]/) {|ch| mapping[ch] }
}.join('|') +
')\z')
def collect_filenames_auto
mapdir((existfiles() - hookfiles()).reject {|fname|
REJECT_PATTERNS =~ fname
})
end
def existfiles
all_files_in(curr_srcdir()) | all_files_in('.')
end
def hookfiles
%w( pre-%s post-%s pre-%s.rb post-%s.rb ).map {|fmt|
%w( config setup install clean ).map {|t| sprintf(fmt, t) }
}.flatten
end
def mapdir(filelist)
filelist.map {|fname|
if File.exist?(fname) # objdir
fname
else # srcdir
File.join(curr_srcdir(), fname)
end
}
end
def ruby_extentions(dir)
Dir.open(dir) {|d|
ents = d.select {|fname| /\.#{::Config::CONFIG['DLEXT']}\z/ =~ fname }
if ents.empty?
setup_rb_error "no ruby extention exists: 'ruby #{$0} setup' first"
end
return ents
}
end
#
# TASK clean
#
def exec_clean
exec_task_traverse 'clean'
rm_f ConfigTable.savefile
rm_f 'InstalledFiles'
end
def clean_dir_bin(rel)
end
def clean_dir_lib(rel)
end
def clean_dir_ext(rel)
return unless extdir?(curr_srcdir())
make 'clean' if File.file?('Makefile')
end
def clean_dir_data(rel)
end
#
# TASK distclean
#
def exec_distclean
exec_task_traverse 'distclean'
rm_f ConfigTable.savefile
rm_f 'InstalledFiles'
end
def distclean_dir_bin(rel)
end
def distclean_dir_lib(rel)
end
def distclean_dir_ext(rel)
return unless extdir?(curr_srcdir())
make 'distclean' if File.file?('Makefile')
end
#
# lib
#
def exec_task_traverse(task)
run_hook "pre-#{task}"
FILETYPES.each do |type|
if config('without-ext') == 'yes' and type == 'ext'
$stderr.puts 'skipping ext/* by user option' if verbose?
next
end
traverse task, type, "#{task}_dir_#{type}"
end
run_hook "post-#{task}"
end
def traverse(task, rel, mid)
dive_into(rel) {
run_hook "pre-#{task}"
__send__ mid, rel.sub(%r[\A.*?(?:/|\z)], '')
all_dirs_in(curr_srcdir()).each do |d|
traverse task, "#{rel}/#{d}", mid
end
run_hook "post-#{task}"
}
end
def dive_into(rel)
return unless File.dir?("#{@srcdir}/#{rel}")
dir = File.basename(rel)
Dir.mkdir dir unless File.dir?(dir)
prevdir = Dir.pwd
Dir.chdir dir
$stderr.puts '---> ' + rel if verbose?
@currdir = rel
yield
Dir.chdir prevdir
$stderr.puts '<--- ' + rel if verbose?
@currdir = File.dirname(rel)
end
end
if $0 == __FILE__
begin
if multipackage_install?
ToplevelInstallerMulti.invoke
else
ToplevelInstaller.invoke
end
rescue SetupError
raise if $DEBUG
$stderr.puts $!.message
$stderr.puts "Try 'ruby #{$0} --help' for detailed usage."
exit 1
end
end
text-format-1.0.0/README 0000644 0001750 0001750 00000001172 11600332303 014156 0 ustar ondrej ondrej Text::Format 1.0.0
==================
Text::Format is provides the ability to nicely format fixed-width text with
knowledge of the writeable space (number of columns), margins, and indentation
settings. Text::Format can work with either TeX::Hyphen or Text::Hyphen to
hyphenate words when formatting.
This is release 1.0, containing both feature enhancements and bug fixes over
the previous version, 0.64.
Text::Format is originally based on the Perl library of the same name by Gábor
Egressy. It is copyright 2002 - 2005 by Austin Ziegler and is licenced under
Ruby's licence. It is also available under the Perl Artistic licence.