質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.18%

標準添付ライブラリのRDocモジュールは、どこで、どのように、指定されたファイルを読み込んでいるのでしょうか?

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 675

tuvalu

score 124

独学でRubyを勉強しているものです。

少し面倒くさいと思われる質問です。
おもしろいと思われた方、おつきあい願えたらと思います。

textファイルを、htmlに変換する簡単なスクリプトを書いていたのですが、書いていると欲が出て来て、

見出しの記述 = マークは<h1></h1>、 == で<h2></h2>、(以降、====== <h6></h6>まであり)、に変換
と、
文字の装飾の記述 +word+ で太字、_word_ で斜体、+word+ でタイプ体に変換

くらいだけも、RDocのマークアップを取り入れられたらと思うようになりました。

original_text_file_name = File.basename($*[0]) #変換したい元のファイル名
original_file_extension_name = File.extname($*[0]) #変換したい元のファイルの拡張子

puts "実行中のRubyのスクリプトファイル:#{$0}"
puts "変換するファイル:#{original_text_file_name}"
puts "検出された拡張子:#{original_file_extension_name}"

if original_file_extension_name == '' #もし拡張子がなければ、
  html_file_name = original_text_file_name.concat('.html') #ただ単に`.html'を追加
else
  html_file_name = original_text_file_name.sub(original_file_extension_name, '.html') #拡張子を`html'に変換
end

begin
  puts "これらから #{html_file_name} を生成します。。"

  original_file = $*[0]


File.open(original_file) do |text|
  text.each_line do |line|
#汎用変換エリア
    line.gsub!(/&/, '&amp;')
    line.gsub!(/</, '&lt;')
    line.gsub!(/>/, '&gt;')
    line.gsub!(/"/, '&quot;')
    line.gsub!(/\//, '&frasl;')
    line.gsub!(/¥/, '&yen;')
    #line.gsub!(/\\/, '&#92;')
    line.gsub!(/#/, '&#35;')
    line.gsub!(/\n/, '<br>')
    line.gsub!(/\s/, '&nbsp;')
    line.gsub!(/\t/, '&nbsp;&nbsp;')
    #line.gsub!(/\bruby\b/i, "<b>#{$&}</b>")
#RDOC見出し変換エリア
    if line =~ /^={6}/ then
      line.sub!(/^={6}/, '<h6>').sub!(/<br>/, '</h6>')
    elsif line =~ /^={5}/ then
      line.sub!(/^={5}/, '<h5>').sub!(/<br>/, '</h5>')
    elsif line =~ /^={4}/ then
      line.sub!(/^={4}/, '<h4>').sub!(/<br>/, '</h4>')
    elsif line =~ /^={3}/ then
      line.sub!(/^={3}/, '<h3>').sub!(/<br>/, '</h3>')
    elsif line =~ /^={2}/ then
      line.sub!(/^={2}/, '<h2>').sub!(/<br>/, '</h2>')
    elsif line =~ /^={1}/ then
      line.sub!(/^={1}/, '<h1>').sub!(/<br>/, '</h1>')
    end
#RDOCリスト変換エリア
    if line =~ /^\*/ then
      line.sub!(/\*(&nbsp;)*/, '<li>').sub!(/<br>/, '</li>')
    elsif line =~ /^-/ then
      line.sub!(/\-(&nbsp;)*/, '<li>').sub!(/<br>/, '</li>')
    end
#RDOC装飾変換エリア
      line.sub!(/\*((.+?)[^,|(&nbsp;)])\*/, "<b>#{$1}</b>") if line =~ /\*((.+?)[^,|(&nbsp;)])\*/
      line.sub!(/\_((.+?)[^,|(&nbsp;)])\_/, "<em>#{$1}</em>") if line =~ /\_((.+?)[^,|(&nbsp;)])\_/
      line.sub!(/\+((.+?)[^,|(&nbsp;)])\+/, "<tt>#{$1}</tt>") if line =~ /\+((.+?)[^,|(&nbsp;)])\+/

    File.open(html_file_name, 'a') do |html|
      html.puts(line)
    end
  end
end
rescue => e
  puts "エラーが発生しました。"
  puts "エラー内容:#{e.message}"
ensure
  puts "プログラムを終了します。"
end

でも、こんなんじゃ、うまく動かないことがわかりました。
どうも、元々のファイルの読み方自体がなってないようです。
each_lineで一行ずつ扱うと、一行に、+word+ が2回あったりすると、$1などの組込変数に最初の1つしか格納されないからです。

そこで、ああ、いいお手本があるじゃないかと思い付き、RDocのソースコードを参考にしようと一通り目を通しました。

ところが、なさけないことに、ソースコードを追いかけてみましたが、わからずじまいでした。。
https://github.com/ruby/rdoc/blob/master/lib/rdoc/rdoc.rb
今まで、テキストなどでは、

filename = ARGV[0]
file = File.open(filename)
text = file.read
text.each_line do |line|
やりたい処理
end

みたいなやり方しか見たことがなく、他のファイルの読み込み方を知りません。
そしてRDocのソースコード中にこんな感じの記述を見つけられないのでした。。
レベルが低くて誠にすみませんが、このRDocは一体、どこで、どのように、指定されたファイルを読み込んでいるのでしょうか?
教えていただけたら嬉しいです!
また、記載したコードにについてダメなところを教えて頂けたらと思います。
面倒くさい質問だと思いますがよろしくお願い申し上げます!

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

0

ソースを検索すると 

  • lib/rdoc/encoding.rb
  • lib/rdoc/parser.rb

あたりで普通にファイルを読む処理がありますね。 https://github.com/ruby/rdoc/search?utf8=%E2%9C%93&q=open&type=

each_lineで一行ずつ扱うと、一行に、+word+ が2回あったりすると、$1などの組込変数に最初の1つしか格納されないからです。 

gsub使えばいいのではないかとおもうのですが。

追記

line.sub!(/\*((.+?)[^,|(&nbsp;)])\*/, "<b>#{$1}</b>") if line =~ /\*((.+?)[^,|(&nbsp;)])\*/

多分、最初は

line.sub!(/\*((.+?)[^,|(&nbsp;)])\*/, "<b>#{$1}</b>")

こう書いていて上手く置換が行われないので上記のコードにしたんじゃないかと想像します。sub/gsubの置換後の文字列に正規表現でキャプチャした結果を使いたい時は$1ではなく\1を使います。

https://docs.ruby-lang.org/ja/latest/class/String.html#I_GSUB--21の注意を参照

line.sub!(/\*((.+?)[^,|(&nbsp;)])\*/, "<b>\\1</b>")


(置換結果がダブルクオーテーションのリテラルになっているので\\になってるのに注意)

sub!をgsub!に変えれば、複数の*なんとか*があっても対応出来ます。

line.gsub!(/\*((.+?)[^,|(&nbsp;)])\*/, "<b>\\1</b>")

ただ、どのみちこれでも正規表現がおかしいので意図した結果にはなりませんが。

--

パーサ作るのは意外と大変なので、文法にこだわりがないのであればmarkdownなどの既存のフォーマット使った方がよいと思います。 

https://github.com/vmg/redcarpet

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/08/27 16:22

    ご回答ありがとうございます。
    頂いたご回答、1つづつ理解するのにお時間ください。
    理解でき次第連絡いたします!
    誠にありがとうございます!

    キャンセル

  • 2017/08/29 08:59

    追加のご指導までいただきありがとうございます。覚えます。
    ご回答をいただいてから、Rdocとにらめっこしてきましたが、
    ずいぶん見通せるようになってきました。どうみてもlib/rdoc/encoding.rb のあたりですよね。
    突破口がつかめれば、急にわかった気になってきました。ぼくが探せなかっただけで、特別変わったことをしている訳ではなかったんですね。ありがとうございます。
    あと、もう一つわかったことは、ご指摘の通り、簡単では無いことをしようとしていたんですね。
    プログラミング自体を独学で勉強して一年ちょっとになりますが、なにか簡単に実装できて、なにが簡単でないのかがわかっていない感じです。
    本当に勉強になりました。ありがとうございます!

    キャンセル

0

Rdocは読んでませんが、

line.gsub!(/\*(.+?)\*/) {"<b>#{$1}</b>"}


のように、ブロック付きのgsubを使えばいいと思います。
また、[^,|(&nbsp;)]の意図が不明ですが、これは、
, | ( & n b s p ; )のどれでも無い1文字」
という意味ですよ。

あと、1行ずつ読む必要は無く、ファイル全体を一気に変数に代入することもできます。
対象ファイルがギガバイト単位でなければ十分。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/08/29 09:04

    ご回答ありがとうございます。おっしゃる通りです。直します。
    正規表現に関してはトライアンドエラーみたいな感じで、やればやるどほ訳けがわかんなくなってしまっているのが実情です。。お恥ずかしい限りです。。もっとわかるようになりたいです。
    ありがとうございます!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.18%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • トップ
  • Rubyに関する質問
  • 標準添付ライブラリのRDocモジュールは、どこで、どのように、指定されたファイルを読み込んでいるのでしょうか?