おれおれマークダウンのブロックの扱い

今まではブロックの種類ごとにクラスを作っていたのですが、いちいち作るのもめんどうなので、全部まとめることにしました。最初はコードを表示していただけだったんですよね。

main.rb
class Code < BlockState
  HEADER = '<pre style="overflow-x: scroll;padding: 1px 1px 1px 3px;border:1px solid black;margin-top: 0;"><code>'
  FOOTER = "</code></pre>"

  def start
    if !filename.nil? then
      printf "<div style=\"border: 1px solid black;padding-left: 3px;margin-bottom: 0;\">#{filename}</div>"
    end
    printf self.class::HEADER
  end

  attr_accessor :comp_lang, :filename

  def process(line)
    line.gsub!('&', "&amp;")
    line.gsub!('<', "&lt;")
    line.gsub!('>', "&gt;")
    puts line
  end
end

それを$LaTeX$、Ruby、PlantUMLのコードをソースと共に処理するようにしたら、ぐちゃぐちゃになってしまいました。

```{math, echo=true, eval=true}
e=mc^2
```

Ruby
```{ruby, echo=true, eval=true}
puts "test"
puts "test"
```

```{lib, include=false}
x = "xxx"
```

```{ruby}
puts x
```

```{PlantUML}
@startuml
Hello <|-- World
@enduml
```
e=mc^2
$$e=mc^2 $$

Ruby

puts "test"
puts "test"
test
test
puts x
xxx
@startuml
Hello <|-- World
@enduml
HelloWorld

たんにコードを表示するときにはMarkdownふうに、もうちょっと複雑になった場合にはRのチャンクふうに書けるようにしました。とりあえず、これでスッキリ。

def parse_option(str)
  puts str
  lang = nil
  name = nil
  options = {"echo"=>true, "eval"=>true, "include"=>true}
  s = StringScanner.new(str)
  lang = s.scan(/\w+/)
  s.scan(/\s+/)
  name = s.scan(/\w+/)
  while !s.eos?
    s.scan(/ *, */)
    option = s.scan(/\w+/)
    s.scan(/ *= */)
    value = s.scan(/\w+/)
    if value.casecmp("false") == 0 then
      options[option] = false
    end
  end
  return lang, name, options
end

def process_block(block)
  lang = nil
  name = nil
  options = {}
  if md = block.header.match(/^ *([^{: ]+)(:([^ ]*))?/) then
    lang = md[1]
    name = md[3]
    options = {"echo"=>true, "eval"=>false, "include"=>true}
  elsif md = block.header.match(/^ *{(.*)}/) then
    lang, name, options = parse_option(md[1])
  end
  puts block.header
  p options

  if lang == "lib" then
    $lib = $lib << "\n" << block.buffer
  end

  if options["include"] then
    if options["echo"] then
      if !name.nil? then
       printf "<div style=\"border: 1px solid black;padding-left: 3px;margin-bottom: 0;\">#{name}</div>"
      end
      print '<pre style="overflow-x: scroll;padding: 1px 1px 1px 3px;border:1px solid black;margin-top: 0;"><code>'
      buffer = block.buffer.gsub('&', "&amp;")
      buffer.gsub!('<', "&lt;")
      buffer.gsub!('>', "&gt;")
      puts buffer
      puts "</code></pre>"
    end

    if options["eval"] then
      print '<div style="overflow-x: scroll;padding: 1px 1px 1px 3px;border:1px solid black;margin-top: 0;">'
      print "<div background='red'>実行結果</div>"
      if lang == "math" then
        print "$$"
        print block.buffer
        print "$$"
      elsif lang == "ruby" then
        print "<pre>"
        print eval($lib + block.buffer)
        print "</pre>"
      elsif lang == "PlantUML" then
        Open3.popen3("java -jar /mnt/d/app/plantuml.jar -pipe -svg -charset UTF-8") do |i, o, e, w|
          i.write block.buffer
          i.close
          o.each do |l| puts l end
          e.each do |l| printf("<!-- stderr: %s -->\n", l) end
          printf("<!-- thread: %s -->\n", w.value)
        end
      end
      print "</div>"
    end
  end
end

コメント

このブログの人気の投稿

五十音配列付き新下駄配列

WSLでの親指シフトはどうやらMozcで実現可能と気がつくまで

親指シフト新下駄配列の可能性