!Mac OS X-10.15.7 !ruby-2.7.1p83
make, antのruby版
前回のbundlerを少し思い出してください.
rake install:local
とすると自動的にhogehogeがinstallされましたよね.そこで使ったrakeというコマンドが今日のお題です.
rakeはmakeやantのruby版です.ちょっとした仕事をさせるときに便利なように作られています.典型的な例は,
task :default do
system 'rake -T'
exit
end
desc 'hello NAME'
task :hello do
name = ARGV[1]
puts "Hello #{name}!"
exit
end
です.これをRakefileにカキコして,
> rake
としてください.Rakefileが用意しているtask(仕事)が表示されます.qiitaとかmy_helpでoptionなしで打った時の説明とよく似ているでしょ.
さて今書いた,Rakefileの中身を見ていきましょう.
- descの後にはrake -Tとした時の説明文(description)
- :defaultはrakeが引数なしで呼ばれた時の動作,
- それ以外はoptionで呼ばれるtaskの名前
- taskの中には標準のruby言語で,動作を記述
です.':'で始まる変数はsymbolと呼ばれるクラスで,名前の代わりをしてくれます.今は何のこっちゃでしょうが,そのうち多用するようになります.
rakeはDSL(Domain Specific Language),つまり,その場に特有の言語を作っちゃおうという発想です.したがって純正のruby言語ではありませんが,ちょっとした仕事(task)を使いやすいように拡張されています.rakeの構文は,後で紹介するThorなどで使われています.
system call
一番Rakefileに記述することの多い関数はsystemです,私は.これはsystemコマンドを起動する関数です.なんでかっていうと,手でやる作業をそのまま記述するから.例えば,gitであげたり(push)引っ張ってきたりする(pull)ときのコマンドって覚えにくくないですか?慣れるまではそのためにweb立ち上げて検索して,色の変わってるサイト読んで,そして最後まで繰って,そのコマンドを打ち込みます.それが普通だと私も思ってたんですよ.でも,達人プログラマたちは違うんですよね.覚えがいいのではなく,忘れそうなことはうまくメモしておくんです.例えば,Rakefileに
desc 'git pull'
task :pull do
p comm = "git pull origin main"
system comm
exit
end
と書いたら,これだけでもだいぶ使いやすくなるでしょ.
さらに,pullを失敗しても,pushでうまくやればいいので,
desc 'git push'
task :push do
p comm = "git add -A"
system comm
p comm = "git commit -m \'hoge\'"
system comm
p comm = "git pull origin main"
system comm
p comm = "git push origin main"
system comm
exit
end
といつもやってる作業を覚える代わりに,Rakefileに覚えさせます.コツは,p commで命令(command)が何かをpしておくこと.
さらに,幾つもcopyしたのは,バレると友達から蔑まされるので,こそっと隠します.
desc 'git push'
task :push2 do
["git add -A",
"git commit -m \'hoge\'",
"git pull origin main",
"git push origin main"].each do |comm|
p comm #puts comm.green after require 'colorize'
system comm
end
exit
end
さらに,commがどこに書いてあるかわからなくなるので講義の方でやるcolorizeを使うと見やすくなります.そうこうするうちに,gitの微妙なところも覚えちゃいます.
command_line
systemで使える外部のコマンドは動作が遅いので,たいがい,より高速で動かせるようにrubyの組み込み関数にも用意されています.例えば,lsにワイルドカードを使って呼び出すのは,Dir.globで代替できます.これのいいのは,「最初の5個で試す」とかができること.
desc 'make list'
task :mk_list do
# system 'ls -1 ../members/*/README.org'
Dir.glob('../members/*/README.org')[0..4].each do |file|
p file
system "grep qiita_id #{file}"
end
exit
end
ここでorgのtableを作ろうとしているのですが,問題はsystemからの戻り値は出力ではなく,コマンドが成功したかどうかなんです.
なもんで,標準出力(stdout)などを取り出すのはcommand_lineというgemを使います.いつものように,
gem install command_line
としてください.これは,ruby 2.4以降だけで動作します.
require 'command_line/global'
desc 'make list'
task :mk_list do
targets = "../members/*/README.org"
# system "ls -1 #{targets}"
Dir.glob(targets)[0..5].each do |file|
p file
res = command_line "grep qiita_id #{file}"
p res.stdout
end
exit
end
とすると取り出せます.
さてここから情報を取り出して
# input
"../members/daddygongon/README.org"
"#+qiita_id: daddygongon\n"
=> # output
| daddygongon | daddygongon|
のような変換を行います.
いくつかの動作をつけ加えて最終的に,
require 'command_line/global'
desc 'make list'
task :mk_list do
targets = "../members/*/README.org"
i = 0
Dir.glob(targets).each do |file|
member = file.split('/')[2]
dd = {}
%i{qiita_id qiita_private}.each do |name|
res = command_line "grep #{name.to_s} #{file}"
res.stdout =~ /:\s*(.+)/ # regexp
dd[name] = $1.to_s
end
next if dd[:qiita_id] == ''
print " | [[https://qiita.com/#{dd[:qiita_id]}/private/#{dd[:qiita_private]}][#{member]}]]"
i += 1
puts "" if (i+1)%6==0
end
exit
end
としています.このようにして,filesから自動で情報抽出を行います.
regexpっと書いたところや,より一般的なデータ抽出の手法は来週説明します.
org to_html, to_platex
my_helpのところでemacs org-modeを紹介しました.qiita_orgではそれをqiitaへcommand lineから出力していたのですが,より一般的にはhtmlやlatexへ出力するcommandが用意されています.
c-c c-e ho # export as [h]tml, [o]ut
c-c c-e ll # export [l]atex, [l]atex
などでそれらのフォーマットへの変換ができます.c-cというのがmajor-modeへのcommandという意味だとわかってくるのでは?
ただこのままの出力では見にくいです.そこで,htmlではreadtheorgというformatをお勧めします.latexではheaderの書き換えを行い,必要なフォーマットにします.
html
htmlで出力するには,https://github.com/fniessen/org-html-themesを参照してください.readtheorgを推薦します.次のtheme-readtheorg.setupファイル
# -*- mode: org; -*-
#+HTML_HEAD: <link rel="stylesheet" type="text/css" href="https://fniessen.github.io/org-html-themes/styles/readtheorg/css/htmlize.css"/>
#+HTML_HEAD: <link rel="stylesheet" type="text/css" href="https://fniessen.github.io/org-html-themes/styles/readtheorg/css/readtheorg.css"/>
#+HTML_HEAD: <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
#+HTML_HEAD: <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
#+HTML_HEAD: <script type="text/javascript" src="https://fniessen.github.io/org-html-themes/styles/lib/js/jquery.stickytableheaders.min.js"></script>
#+HTML_HEAD: <script type="text/javascript" src="https://fniessen.github.io/org-html-themes/styles/readtheorg/js/readtheorg.js"></script>
を~/.emacs.d/org-mode/においてください.
#+SETUPFILE: ~/.emacs.d/org-mode/theme-readtheorg.setup
と書こうとしているorg-fileのheaderに書き加えてください.このあとexport hoすると出来上がりです.
latex
latexに関しては,使う必要がある人だけ以下の手順を試して見てください.
org-modeが用意しているlispを使うと相当複雑なことができます.でも,lispを覚える必要があるので少し面倒で,私の余命をかけるのはちょっとリスクがありそうです.そこで,先ほど紹介したRakefileにheaderを置き換える命令を追加します.例えば,中間審査のlatexファイルを使う例が,docs/latex_exampleにあります.
こういう繰り返し使うコマンドを,一発で実行できるのがrakeのいいところ.rakeに一括で処理させると無駄なファイルも一緒にやっちゃいます.でも,冗長な動作でかかってしまう時間を気にするよりも,codingやコマンドを思い出すのにかかるコストを節約することを心がけてください.特に,卒論ではたくさんの研究室でlatexを使ってはるでしょうから,ぜひ,試してみてください.それと,このexampleは西谷研独自に作ってきたものなので,もっといい手があれば教えてください.
- source ~/git_hub/ruby_docs/chart_style_ruby/c04_rake.org