はじめに
卒業研究の一環として,研究室で使われているPDFを作るためのRakefileを,Runbookの形式で書かく.
-
Patrick Blesi, Github, runbook
ここでは書き換えの過程とできたものの使い方を書く.
実行環境
- MacBook Air
- MacOS High Sierra(バージョン 10.13.3)
- Rubyバージョン 2.7.0
Runbookとは
手順を明確にし一つ一つのステップを踏みながら進んでいくプログラム.
RubyのDSLの一つとして段階的に自動化を書いていくことができる.
なぜRakeじゃなくてRunbook?
私のように初心者でCUIを使うことにまだ慣れていない人間からすれば,Rakefileを実行すると勝手に処理が進み何をしているのかがわからなくなる.そこでRunbookを使うことにより手順が明確になり自分が何をしているのかがわかるようになる.
また,Rakefileでは実行途中でおかしく思っても止めることを最初からプログラムに書いていないと難しい,しかし,Runbookであれば細かく分かれた手順の中で毎回ユーザーに入力を求めて続けるかを選ぶことが出来る.
プログラムの概要
Runbookの基本
基本はタイトル,セクション,ステップからなるプログラムで,ステップの中にプログラムを書いていく.
Runbookのコマンドにスタートのための雛形があるのでそれをインストールしてRunbookの基本を確かめる.
> runbook generate runbook my_first_runbook
これによりディレクトリ内にmy_first_runbook.rbが生成される.
require "runbook"
runbook = Runbook.book "My First Runbook" do
description <<-DESC
This is a runbook that...
DESC
section "SECTION" do
step "STEP" do
# Add statements here
end
end
end
if __FILE__ == $0
Runbook::Runner.new(runbook).run
else
runbook
end
実行すると下図のように続けるかを聞かれるだけのものが実行される.
> runbook exec my_first_runbook.rb
Executing My First Runbook...
Description:
This is a runbook that...
Section 1: SECTION
Step 1.1: STEP
Continue? (enter "h" for help) [c,s,j,P,e,h]
> runbook exec my_first_runbook.rb
Executing My First Runbook...
Description:
This is a runbook that...
Section 1: SECTION
Step 1.1: STEP
Continue? (enter "h" for help) [c,s,j,P,e,h] c
>> Continue to execute this step
> runbook exec my_first_runbook.rb
Executing My First Runbook...
Description:
This is a runbook that...
Section 1: SECTION
Step 1.1: STEP
Continue? Continue to execute this step
RakefileをRunbookに移植
研究室使われているRakefileの構成は主に
- orgファイルの読み込み
- latexに変換
- report用の形式にlatexを変更
- platexを用いてPDFの作成
の四つなので,これらをステップとしてRunbookを書く.
Runbook.book "Make PDF" do
description <<-DESC
This is a make PDF from org
DESC
section "Make pdf" do
step "Load org file"
step "Make tex file"
step "Load and Convert tex file"
step "Make pdf"
end
end
実行結果
> runbook exec make_pdf.rb
Executing Make PDF...
Description:
This is a make PDF from org
Section 1: Make pdf
Step 1.1: Load org file
Continue? Continue to execute this step
Step 1.2: Make tex file
Continue? Continue to execute this step
Step 1.3: Load and Convert tex file
Continue? Continue to execute this step
Step 1.4: Make pdf
雛形ができたのでこれに中身を足していく.
セクションをlatexを作るものとPDFに変換するものに分けたほうが止めやすいと思ったのでそのようにし,中身を足す.
require "./convert"
require "colorize"
Runbook.book "Make PDF" do
description <<-DESC
This is a make PDF from org
DESC
section "Make latex" do
$t_file = "report"
step "Load org file" do
note "Load org file"
ruby_command do
$file = Dir.glob("*.org")[0].match(/(.*).org/)[1]
puts "your org file is " + $file.red + "."
end
end
step "Make tex file" do
note "Make tex file"
ruby_command do
system "emacs #{$file}.org --batch -f org-latex-export-to-latex --kill"
end
end
step "Load and Convert tex file" do
ruby_command do
$lines = File.readlines("#{$file}.tex")
$lines = convert_thesis($lines)
File.open("#{$t_file}.tex", "w") do |f|
$lines.each { |line| f.print line }
end
end
end
section "Make PDF" do
step "Make pdf" do
note "Make pdf"
ruby_command do
commands = ["platex #{$t_file}.tex",
"bibtex #{$t_file}.tex",
"platex #{$t_file}.tex",
"dvipdfmx #{$t_file}.dvi"]
commands.each { |com| system com }
end
end
end
end
これで,"Load org file" でディレクトリ内のorgファイルを読み込み,latexに変換しPDFを作るRunbookのプログラムができた.
-
convert.rb
は"Load and Convert tex file"内で使っている,convert_thesis
の関数を使うためのプログラム.内容はorgから作成したlatexをレポート用の雛形に変換するものである.
def convert_thesis(lines)
head = <<'EOS'
\documentclass[a4j,twocolumn]{jsarticle}
\usepackage[dvipdfmx]{graphicx}
\usepackage{url}
\setlength{\textheight}{275mm}
\headheight 5mm
\topmargin -30mm
\textwidth 185mm
\oddsidemargin -15mm
\evensidemargin -15mm
\pagestyle{empty}
\begin{document}
\title{}
\author{学科 \hspace{5mm} 学籍番号 \hspace{5mm} your name}
\date{}
\maketitle
EOS
head2 = <<'EOS'
{\small\setlength\baselineskip{15pt} % 参考文献は小さめの文字で行間を詰めてある
\begin{thebibliography}{9}
\bibitem{}
\end{thebibliography}
}
\end{document}
EOS
new_line = [head]
lines[31..-1].each do |line|
new_line << line
end
new_line.each do |line|
line.gsub!('\end{document}', head2)
line.gsub!('\tableofcontents', "")
end
return new_line
end
指摘
研究室メンバーからの指摘
- orgファイルが複数ある場合選べるようにしたい.
- ディレクトリ内にできたファイル(.auxや.div)が自分で変更することがないのに残っていて見にくいので消したり,まとめたりして欲しい.
orgの選択を"Load org file"のなかで出来るようにする.
require "./convert"
require "colorize"
Runbook.book "Make PDF" do
...
$t_file = "report"
step "Load org file" do
note "Load org file"
ruby_command do
str = Dir.glob("*.org")
str.each do |name|
puts "your org file is " + name.red + " ? (y or n)"
res = $stdin.gets.chomp
if res == "y"
$file = name.match(/(.*).org/)[1]
break
elsif res == "n"
if name == str[str.size - 1]
puts "This directory not have the objective file".red
exit
end
end
end
end
end
...
end
orgファイルの名前ををメッセージとしてターミナル上に表示し,"y"か"n"を入力することで選べるようにした.全て”n”なら強制終了する.
次に一番最後に"Move report"とし,できたレポートをreportというディレクトリを作り移動させるようにした.
require "./convert"
require "colorize"
Runbook.book "Make PDF" do
...
section "Make PDF" do
step "Make pdf" do
...
step "Move report" do
note "Move report"
ruby_command do
commands = ["mkdir report",
"mv -f #{$t_file}.* ./report",
"open ./report/#{$t_file}.pdf"]
commands.each { |com| system com }
end
end
end
end
教授からの指摘
- 入力をせずにノンストップで全てを実行できる方法が無いのかどうかを調べて確認しろとの指摘.
gem RunbookのGithubに載っているマニュアルに記述があった.
> runbook exec --auto my_runbook.rb
これで実行すると入力なしに最後まで実行できる.
使い方
Runbookの導入
gemでインストールする.gem install runbook
実行方法
runbook exec runbook.rb
とするとrunbook.rbが実行される.
- runbook.rbは自分のプログラム.
- プログラムのある場所のパスが分かればどのディレクトリでも実行可能