# The LaTeX class. # Note that methods with a ! in them work like the * versions of the LaTeX # functions, and methods with a ? in them do not print a newline. # Alternatively, you can use _star and _suppress, if you prefer a more # English-like syntax. class LaTeX def initialize() @nesting = 0 @indent = " " end # Allows the user to change the default indenting (default is two spaces # per nesting) attr_accessor :indent # Return the string for a newline def newline() return "\\\n" end # Return the string for a newline that won't break a page def newline!() return "\\*\n" end # Return a string for the LaTeX symbol def latex() return "\\LaTeX" end # Return a string for a comment, ended with a carriage-return def comment(comment) return "% #{comment}\n" end # Let % be an alternative way to specify a comment alias_method :%, :comment #, # Return an indented string, terminated by a newline if it isn't a comment # that is already newline-terminated def indent(str) s = indent?(str) if not s =~ /^\s*%.*\n/ then s << "\n" end return s end # Return an indented string that is never newline-terminated def indent?(str) s = "" @nesting.times do s << @indent end s << str return s end # Create a new LaTeX command def newcommand(cmd, func) method_missing("newcommand", "\\#{cmd}", func) end # Print a LaTeX command using the rules specified above def method_missing(symbol, *args) symbol = symbol.to_s.gsub('!', '*') symbol = symbol.to_s.gsub('_star', '*') nl = !(symbol =~ /(\?|_suppress)\*$/) symbol = symbol.gsub('\?', '') symbol = symbol.gsub('_suppress', '') s = "" if block_given? then s << __begin__(symbol, *args) << __gen_newline__(nl) nesting_tmp = @nesting @nesting = @nesting.succ s << proc.call() @nesting = nesting_tmp s << __end__(symbol) << __gen_newline__(nl) else s << indent?("\\#{symbol}#{__arg_list__(args)}#{__gen_newline__(nl)}") end return s end alias_method :__cmd__, :method_missing alias_method :__env__, :method_missing # Return the arguments of a LaTeX function; Use an array to specify # optional arguments def __arg_list__(args) s = "" args.each do |arg| case arg when Array s << "[" arg.each do |a| s << "#{a}," end s.chop! s << "]" else s << "{#{arg}}" end end return s end # Return a newline if nl is true, otherwise return an empty string def __gen_newline__(nl) return nl ? "\n" : "" end def __begin__(symbol, *args) return indent?("\\begin{#{symbol}}#{__arg_list__(args)}") end def __end__(symbol) return indent?("\\end{#{symbol}}") end end if __FILE__ == $0 then l = LaTeX.new s = l.documentclass("article") + l.newcommand("foo", l.latex) + l.newenvironment("myitemize", l.__begin__("itemize"), l.__end__("itemize")) + l.document { l.title("#{l.LARGE?} This is a test") + l.author("Me") + l.date() + l.maketitle() + l.section("Writing #{l.foo_suppress} documents in Ruby") { l.indent(l % "This is a comment.") + l.indent("I can put text here.") } + l.section("More about #{l.foo_suppress} and Ruby") { l.myitemize { l.item?(["a)"]) + "This is item a.\n" + l.item?(["b)"]) + "This is item b.\n" } } } puts s end