関数型!イカ娘
(この記事は partake.in の為に書かれました。TeX マクロ初心者なので識者の皆様方のツッコミ等歓迎します。)
奥村先生まで侵略されてるじゃなイカ!フッフッフッ、むこうから侵略されに来るとは好都合でゲソ!ついでに日本の TeX 界もいっしょに侵略してやるでゲソ!
関数作らなイカ?
まずは関数*1の定義でゲソ。関数を定義するには \def を使うでゲソ。
\def\incursion#1#2{#1 を #2 が侵略したでゲソ!} \incursion{海の家 れもん}{イカ娘} \end
これに適当な名前を付けて保存して、pTeX に掛ければ DVI が完成するでゲソ。これは素の TeX なので pLaTeX じゃなくて pTeX を使うでゲソ。
海の家 れもん を イカ娘 が侵略したでゲソ
と出力されていたら成功でゲソ。簡単じゃなイカ?
再帰しなイカ?
\newcount\cnt \def\ika#1{ \cnt = #1 \advance \cnt by -1 \ifnum#1 = 0 イカ娘! \else 侵略!\expandafter\ika\number\cnt \fi } \ika{6}
\newcount<名前> でカウンタを定義、<名前> = <数> で代入できるでゲソ。足し算は \advance <名前> by <数>、値は \number を使えば参照できるんじゃなイカ? \ifnum は if 文の仲間で \ifnum<名前1><演算子><名前2> とすれば数値を比較できるでゲソ。
ところで、ここに出てくる \expandafter ってなんでゲソ?試しに外してみるでゲソ!
\newcount\cnt \def\ika#1{ \cnt = #1 \advance \cnt by -1 \ifnum#1 = 0 イカ娘! \else 侵略!\ika{\number\cnt} \fi } \ika{6} \end
出力結果は…
侵略!侵略!侵略!侵略!侵略!イカ娘!
一回分足りないでゲソ!!
\expandafter が無いと、\ika{\number\cnt} の展開結果は
\cnt = \number\cnt \advance \cnt by -1 \ifnum\number\cnt = 0 イカ娘! \else 侵略!\ika{\number\cnt} \fi
になるでゲソ。#1 の部分が \number\cnt になってるじゃイカ? \ika を展開する前に \number\cnt を展開したいでゲソ……。そんな時は \expandafter を付けてみるでゲソ!
\expandafter\ika{\number\cnt}
これじゃダメでゲソ。\expandafter は \ika を読み飛ばして次のトークンを評価するでゲソ。\ika の次のトークンは { なので \ika を飛ばして { を評価して \ika に戻ってくるだけなので最初と同じでゲソ。
正しくはこうやるでゲソ!
\expandafter\ika\number\cnt
これなら、 \ika を飛ばして \number を評価、\number は引数を要求して \number\cnt が評価された後 \ika{評価済みの\number\cnt} になるでゲソ*2。
…… \ika をムシするとは良い度胸じゃなイカ!?
*1:本当の名前はマクロでゲソ……。私の天敵のマグロみたいで恐ろしいので名前を変えてやったでゲソ!
*2: http://oku.edu.mie-u.ac.jp/tex/mod/forum/discuss.php?d=58&parent=317
Google Calendar API を Ruby から操作したい
Rubygems の gcalapi を使えば Google Calendar API を簡単に叩けます。使い方は他にもいろいろ載ってるのでここでは触れません。
使ってみて、ちょっと困ったのが、gcalapi は イベント UID *1が読めない事。
Google Calendar から送られてくるデータに、ちゃんと UID は入っているけど、gcalapi gem 側でそれを認識していないのが原因だということが分かりました。とりあえず、てっとっりばやく修正するには、
module GoogleCalendar class Event attr_accessor :uid end Event::ATTRIBUTES_MAP["uid"] = { "element" => "gCal:uid", "attribute" => "value" } end
等とすれば認識されるようになります。オープンクラス便利ですね。他のパラメータも同様に Event::ATTRIBUTES_MAP を書き換えて、アクセサを定義すれば認識されるようになります。*2
レンタルサーバ等で gitosis を使う
gitosis の使い方の記事はいろいろある*1ようですが、gitosis 用のユーザを作らず一般ユーザ権限のみで運用する方法について書いた記事が無いようなので、その場合の方法、注意点等を軽く書いておきます。
gitosis は ~/.ssh/authorized_keys を管理用リポジトリの post-update hook を使って自動的に書き換えることでユーザ管理を実現しています。したがって、gitosis を使うには OpenSSH 形式の ~/.ssh/authorized_keys が使える事が大前提です。また、公開鍵認証以外でのログイン手段が無い場合、authorized_keys が壊れた場合に対処ができなくなるので危険です*2。諦めましょう。
インストール
Git と Python あたりのインストールは済んでいるものとします。
リポジトリから gitosis を取ってきてインストールします:
$ git clone git://eagain.net/gitosis.git $ cd gitosis $ python setup.py install --user
インストール先は ~/.local/ になるので、~/.local/bin に PATH を通しておいてください。
gitosis 初期設定
gitosis 管理用の鍵ペアを用意し gitosis を初期化します:
$ gitosis-init < id_rsa.pub
gitosis の仕組み上、authorized_keys へ通常のログイン用に登録された鍵を併用するとちょっと面倒かもしれません。
管理用のリポジトリ ~/repositories/gitosis-admin.git の post-update hook に実行権限を付けておきます:
chmod 755 ~/repositories/gitosis-admin.git/hooks/post-update
後は gitosis-admin.git を clone してきて設定をするのですが……、
えーと、力尽きたので、後の作業は http://progit.org/book/ja/ch4-7.html を見てください。
gitosis の仕組み
gitosis の設定後の authorized_keys の中身は
### autogenerated by gitosis, DO NOT EDIT command="gitosis-serve user1",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa AAAAB3(略) user1 command="gitosis-serve user2",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa AAAAB3(略) user2
のようになっています。command オプションが指定されているため、この鍵で認証された場合はユーザがクライアント側で指定したコマンドを無視し、その代わりに command オプションで指定された gitosis-serve user1 が実行されます。
クライアントが指定したコマンドは環境変数 SSH_ORIGINAL_COMMAND に格納されているので、gitosis-serve はその環境変数を解釈してアクセス制御をしています*3。
ありがちな問題?
鍵を流用した場合
gitosis 管理用に鍵ペアを用意せず、通常のログインに使う鍵を流用した場合
$ git clone hoge@example.org:gitosis-admin.git Initialized empty Git repository in /home/fuga/gitosis-admin/.git/ fatal: 'gitosis-admin.git' does not appear to be a git repository fatal: The remote end hung up unexpectedly
のようなエラーに見舞われることがあります。これは、gitosis 経由でリポジトリにアクセスしていないため発生します*4。
この場合は、単に、
git clone hoge@example.org:repositories/gitosis-admin.git
のように、直接リポジトリにアクセスしてしまえば良いでしょう。
PATHが通せない場合
大抵 ~/.bashrc か ~/.ssh/environment あたりに書いておけば良いと思いますが、
PATH が通せない場合は gitosis をフルパスで指定する必要があるので、スクリプトを手で弄る必要があります。
gitosis/ssh.py 中に
def generateAuthorizedKeys(keys): TEMPLATE=('command="gitosis-serve %(user)s",no-port-forwarding,' +'no-X11-forwarding,no-agent-forwarding,no-pty %(key)s') yield COMMENT for (user, key) in keys: yield TEMPLATE % dict(user=user, key=key)
という部分があるので、gitosis-serve をフルパスに修正します。例えば /home/hoge/.local/bin/gitosis-serve の場合、
def generateAuthorizedKeys(keys): TEMPLATE=('command="/home/hoge/.local/bin/gitosis-serve %(user)s",no-port-forwarding,' +'no-X11-forwarding,no-agent-forwarding,no-pty %(key)s') yield COMMENT for (user, key) in keys: yield TEMPLATE % dict(user=user, key=key)
とします。もう一箇所は、gitosis/templates/admin/hooks/post-update 中の gitosis-run-hook を、やはりフルパスに修正します。
前:
#!/bin/sh set -e gitosis-run-hook post-update git-update-server-info
後:
#!/bin/sh set -e /home/hoge/.local/bin/gitosis-run-hook post-update git-update-server-info
*1:http://progit.org/book/ja/ch4-7.html
*2:gitosis 用ユーザを作る理由の一つでしょう
*3:git がリポジトリへアクセスする方法については http://progit.org/book/ja/ch9-6.html を参照してください
*4:同じ鍵に対して、gitosis 経由でアクセスするものと、通常のログイン用の両方の設定があるので