require 'fileutils'
require 'rdoc/markup/to_html_crossref'
require 'rdoc/markup/mathml_wrapper'

##
#<b>Note that Japanese and English are described in parallel.</b>
#
#== TeX の数式を MathML に変換
#
#TeX で記述された数式を MathML に変換します.
#インラインで表示したい場合, TeX の数式を以下のように $ ... $ でくくって
#記述してください. $ の
#前後には半角空白を一文字以上入れて下さい.
#(なお, "$ID: ... $" や "$LOG: ... $
#といった, CVS のキーワードとして
#用いられている書き方は数式として扱われません.)
#
#  インラインで表示する数式は $ f(x) = x^2 + 1 $ のように記述します.
#  ($ の前後に空白をお忘れなく).
#
#ブロックで表示する場合, 以下のように \[ と
#\] とでくくって記述してください. \[, は必ず行頭に記述してください.
#
#  \[
#     \sum_{i=1}^nf_n(x)
#  \]
#
#数式を複数行で表示する場合には, 改行する部分に "\] \[" を記述してください.
#
# \[
#     d\zeta/dt + J(\psi,\zeta) = Ra \; dT/dx + \nabla\zeta, \] \[
#     dT/dt + J(\psi,T) - d\psi/dx = \nabla T,               \] \[
#     \nabla\psi = \zeta
# \]
#
#TeX の数式から MathML 変換には
#<b>Ruby 用 MathML ライブラリのバージョン 0.8</b> を使用しています.
#このライブラリは{ひらくの工房}[http://www.hinet.mydns.jp/~hiraku/]
#にて公開されています. 使用できる TeX コマンドの詳細に関しても
#こちらのサイトを参照してください.
#
#作成されたドキュメントを閲覧する際には MathML に対応した
#ブラウザを使用する必要が
#あります. {MathML 日本語情報}[http://washitake.com/MathML/] 
#や {MathML Software - Browsers}[http://www.w3.org/Math/Software/mathml_software_cat_browsers.html]
#などを参照してください.
#
#
#== TeX is converted to MathML
#
#TeX formula is converted to MathML.
#When inline display, TeX formula should be bundled by $ ... $
#as follows. 
#One or more normal-width blank is necessary before and behind "$".
#(The format of CVS keywords, that is "$ID: ... $" or
#"$LOG: ... $ etc. is ignored.)
#
#  Inline formula is $ f(x) = x^2 + 1 $ .
#
#When block display, TeX formula should be bundled by \[ ... \]
#as follows. 
#Describe \[ at the head of line.
#
#  \[
#     \sum_{i=1}^nf_n(x)
#  \]
#
#To write equations across multiple lines, describe "\] \["
#as follows.
#
# \[
#     d\zeta/dt + J(\psi,\zeta) = Ra \; dT/dx + \nabla\zeta, \] \[
#     dT/dt + J(\psi,T) - d\psi/dx = \nabla T,               \] \[
#     \nabla\psi = \zeta
# \]
#
#<b>MathML library for Ruby version 0.8</b> is needed to
#convert TeX formula to MathML.
#This library is available from {Bottega of Hiraku (JAPANESE only)}[http://www.hinet.mydns.jp/~hiraku/].
#See this site about available TeX commands.
#
#When you browse generated documents, you need to use 
#browers that can handle MathML.
#See {MathML Software - Browsers}[http://www.w3.org/Math/Software/mathml_software_cat_browsers.html], etc.
#
#
#== \newcommand, \newenvironment の使用方法
#
#\newcommand や \newenvironment 命令によるマクロを使用するには,
#Ruby のロードパス以下に '<b><tt>mathml/macro</tt></b>' ディレクトリを
#作成し, そのディレクトリ以下にマクロ命令を記したファイルを置いてください.
#ファイル名は問いません.
#
#例えば, '<tt>/usr/lib/ruby/1.8</tt>' が Ruby のロードパスである場合,
#'<tt>/usr/lib/ruby/1.8/mathml</tt>' および
#'<tt>/usr/lib/ruby/1.8/mathml/macro</tt>' ディレクトリを作成し,
#そのディレクトリ以下に, 'D6math.sty' というファイルを作成します
#(前述したようにこのファイル名は何でも構いません). そのファイル内に
#以下のような \newcommand 命令を記述しておくことで, '<b>\DP{}{}</b>'
#(偏微分を簡単に記述するためのマクロ) コマンドが使用可能になります.
#
#    \newcommand{\DP}[2]{\frac{\partial #1}{\partial #2}}
#
#地球流体電脳倶楽部で提供している {TeX マクロ (通称: 電脳スタイル)}[http://www.gfd-dennou.org/library/cc-env/TeXmacro/dennou/SIGEN.htm]
#に含まれる 'D6math.sty' を Ruby 用 Mathml ライブラリで使用できるように
#修正したパッケージを libmathml-macro-dennou-ruby[http://www.gfd-dennou.org/library/cc-env/libmathml-macro-dennou-ruby/debian/stable/] として
#提供しています. サンプルとして利用してみてください.
#
#
#== Usage of \newcommand and \newenvironment
#
#If you want to use macros defined by \newcommand and 
#\newenvironment commands, make '<b><tt>mathml/macro</tt></b>' directory
#under load paths of Ruby, and prepare a file that macro commands are 
#described in the directory. A name of the file is free.
#
#For example, if your load path of Ruby is '<tt>/usr/lib/ruby/1.8</tt>',
#you should make '<tt>/usr/lib/ruby/1.8/mathml</tt>' and
#'<tt>/usr/lib/ruby/1.8/mathml/macro</tt>' directories,
#and make 'D6math.sty' file (already mentioned, the file name is free).
#When you describe a following \newcommand command, you can use
#'<b>\DP{}{}</b>' (a macro for partial differentiations) command.
#
#    \newcommand{\DP}[2]{\frac{\partial #1}{\partial #2}}
#
#As a sample, please use libmathml-macro-dennou-ruby[http://www.gfd-dennou.org/library/cc-env/libmathml-macro-dennou-ruby/debian/stable/].
#The original style file is 'D6math.sty' in {TeX macro (Dennou style)}[http://www.gfd-dennou.org/library/cc-env/TeXmacro/dennou/SIGEN.htm].
#libmathml-macro-dennou-ruby is a reconfigured package for Mathml library for Ruby.
#
#
class RDoc::Markup::ToXHtmlTexParser < RDoc::Markup::ToHtmlCrossref

  attr_accessor :context
  attr_reader   :block_exceptions

  ##
  # We need to record the html path of our caller so we can generate
  # correct relative paths for any hyperlinks that we find

  def initialize(from_path, context, show_hash, mathml=nil)
    super(from_path, context, show_hash)
    @mathml = mathml

    if @mathml
      # TeX inline form
      @markup.add_special(/(\$(.*?)[^\\]\$)/im, :TEXINLINE)

      # TeX inline delimiter
      @markup.add_special(/(\\\$)/im, :TEXINLINEDELIMITER)

      # TeX block form
      @markup.add_special(/(\\\[(.+?)\\\])/im, :TEXBLOCK)
    end

    @block_exceptions = []
    if @markup
      @block_exceptions << {
        'name'     => :texblockform,
        'start'    => Regexp.new("^\\\\\\["),
        'end'      => Regexp.new("\\\\\\]$"),
        'replaces' => []
      }
      @block_exceptions[0]['replaces'] << {
        'from' => Regexp.new("\\\\\\\\"),
        'to'   => "\\\\\\\\\\\\\\\\",
      }
    end

  end

  def file_location
    if @context.context.parent
      class_or_method = @context.context.name
    end
    context = @context.context
    while context.parent
      context = context.parent
    end
    location = context.file_relative_name
    if class_or_method
      location += "#"+class_or_method
    end
    return location
  end

  ##
  # TEXINLINE pattern $...$ is converted to MathML format
  # when --mathml option is given.
  #
  def handle_special_TEXINLINE(special)
    text = special.text
    return text unless @mathml
    raw_text = text.scan(/^.*?\$/).to_s.sub(/\$$/, '')
    return text if text =~ /^.*?\$[A-Z]\w+:/  # CVS keywords are skipped
    text.sub!(/^.*?\$/, '')
    text.sub!(/\$$/, '')
    tex = MathMLWrapper.new
    mathml, stat = tex.parse(text)
    if !(stat == 0)
      $stderr.puts "Warning: in #{file_location}, following TeX commands can not be converted to MathML\n\n",
      "    #{text}\n\n"
    end
    return raw_text + mathml
  end

  ##
  # TEXINLINEDELIMITER pattern "\$" is converted to single dollar "$"
  # when --mathml option is given.
  #
  def handle_special_TEXINLINEDELIMITER(special)
    text = special.text
    return text unless @mathml
    return text.gsub(/\\\$/, '$')
  end

  ##
  # TEXBLOCK pattern \[...\] is converted to MathML format
  # when --mathml option is given.
  #
  def handle_special_TEXBLOCK(special)
    text = special.text
    return text unless @mathml
    text.sub!(/^\\\[/, '')
    text.sub!(/\\\]$/, '')
    tex = MathMLWrapper.new
    mathml, stat = tex.parse(text, true)
    if !(stat == 0)
      $stderr.puts "Warning: in #{file_location}, following TeX commands can not be converted to MathML\n\n",
      "    #{text}\n\n"
    end
    return mathml
  end

end
