Fun emath の更新を一旦中断することにしました

emath 修正パックの配布形態が変わった*1ことを受け、しばらく対応しておりました。しかしながら、もしかしたら、修正パックや実験版の配布形式が変わってしまうことも十分あり、私自身が修正パックを実際に試さないかぎり、表向けに nosrc.rpm ですら提供すべきでないという判断しました。

したがいまして、Vine Linux 向けに配布しておりました rpm や emath 関連ツールも更新を一旦中断しました。emath の rpm をはじめ、emathfigtoeps など、ご利用下さったみなさま、本当にありがとうございました。

"内蔵" ハードディスク Touro Desk 0S03001A (2TB) を購入(笑)

11 月 3 日真夜中から明け方のどこかで、主に使っているマシンのハードディスクが逝ってしまった。症状は、I/O error が起こり、読み書きすらできなくなる、/dev/sda が見えなくなる。また、BIOS でハードディスクが認識しないことも起こった。

壊れてしまったハードディスクは、Seagate 7200.11 500GB x 2。BTO でついてきたハードディスクとはいえ、わずか 3.25 年足らずで壊れてしまうなんて、思いもしなかった。最近、SMART による診断結果から、不良セクタが目立っていたことも気になっていたが、今思えば、書き込みの音が少々おかしかった気もする。

Seagete 7200.11 についてググってみると、最初から問題のあったハードディスクであったようです。

11 月 3 日という文化の日は、文化も堪能することもなく (^^、丸一日、マシンの復旧になってしまった。

"内蔵" ハードディスクを購入(笑)

まずは、午前中に近くのドスパラ千葉店に足を運び、新しい "内蔵" ハードディスクを調達してきた。そう、"内蔵" ハードディスクです(^^

ご存知の方も多いと思いますが、先日のタイでの大洪水 wikipedia:タイ大洪水 による大水害の影響で、今、内臓ハードディスクの相場がタイの大水害前に比べて 2〜3 倍くらいに高騰しています。タイといえば、世界第 2 位のハードディスク生産をしており、たとえば、Western Digital は、ハードディスクの生産の 6 割がタイで製造されている。タイの大水害前に生産されたハードディスクは、すでに大手ベンダなどに在庫確保されているようです。そのために、一般市場に出回るハードディスクは、品不足による価格高騰が起こっているようです。

ところが、(タイの大洪水前に生産された)外付けハードディスクは、まだショップに残っていることも多いようです。現にドスパラ千葉店では、HGST 製ハードディスク搭載の Touro Desk の価格が、たしかにそのままだった。

そこで、私は、"内蔵" ハードディスク Touro Desk 0S03001A (2TB) を購入しました (^^

さっそく、お好み焼きのへら(大、小)とドライバなどの工具を用意して…、以下、サウンドのみをお楽しみください!

「アタッ アタタタタターッ!
*「うわーっ ぐしゃ!
*「なんぼのもんじゃーっ!
ミス! munepiは すばやく
 みを かわした!
「アチョ ガスッ ビシュ」
*「う……。
「ズバババーン!
  かいしんの いちげき!
  外側ケースを やっつけた!

はい、内蔵ハードディスクが出てきました!こんなに頑丈に梱包された "内臓" ハードディスクを買ったのは初めてです(笑

私が買った "内臓" ハードディスク Touro Desk 0S03001A (2TB) は、SATA3 (6Gbps) 2TB 7200rpm でした。でも、このハードディスクを USB 2.0 でつなぐのは、転送速度の面でもったいない気がします。

ちなみに、Touro Desk を解体しながら検索していたら、やはり同じ事を考えている人がいました(w こちらの方は、解体方法を検証なさっておられます。私はバキッとやっちゃいましたけど(w

ddrescue

実行例は、wikipedia:Ddrescue に書かれているので、今回やったことを一言記します。

今回、dd で Windows パーティションがわずか 2.2GB/250GB しか抜き出せなかった。ダメもとで ddrescue を使って、一旦ファイルに書きだしてみたところ、1 err. のみだった。すでに壊れかけていたディスク状態だったので、たまたまうまく読み出せたのかもしれない。

$ sudo ddrescue /dev/sda1 sda1-win.img ddrescue-sda1-win.log

「わたしのやてふ環境」独り反省会

昨日開催された研究集会 TeX ユーザの集い 2011 http://oku.edu.mie-u.ac.jp/texconf11 で LT「わたしのやてふ環境」をやってしまいました。今日はその反省会を独りでやります*1

TeXユーザの集い 2011 に、発表時のスライド(PDF ファイル) http://oku.edu.mie-u.ac.jp/texconf11/presentations/yamamoto.pdf が公開されております。LT 中にやった(やろうとしていた(^^;;)Demonstration のスクリーンショットも挿入し、加筆したスライドとなっております。参加できなかった方にも伝わるような感じにしました。本記事と合わせてご覧ください。

LT で意識していたこと

  1. TeX を普通知っている人であれば、「どの方でも楽しんでいただける」
  2. Emacs を知っている人であれば、「あれこれツッコミどころ満載で、ニヤニヤしていただける」
  3. TeXnician の方であれば、「あのマクロはこんなアルゴリズムかな?と妄想していただける」

そんな思いで、ネタ仕込みに全力疾走しておりました。

TeX を知っている方であれば、おそらくどなたでも Knuth 巨匠を知っているでしょう。TeX 文章を書くとき、ほとんどの方は何らかのテキストエディタで入力するでしょうし、入力支援も利用している方も多いでしょう。そこで、単に Emacs というテキストエディタで、真面目に馬鹿で、実用性ゼロな、TeX デモンストレーションを仕込んだわけです。

「わたしのやてふ環境」は…、

YaTeX + Anything + Auto Complete Mode + auto-complete-yatex

です。文章で書くと、「ふつうのやてふ環境をベースに、Anything の統一的なインタフェースにより、既存の Emacs の操作性を革命的に変化させて、Auto Complete Mode による強力な動的補完とそのやてふ拡張を備えた環境です。」となります。なお、手元の OS は、VineSeed x86_64 または、Vine Linux 6 x86_64 です。

Vine Linux でお手軽にやてふ環境を構築

「わたしのやてふ環境」は、Vine Linux であれば比較的簡単に整えられます。apt-get コマンドを利用して、auto-install, auto-complete-mode, yatex パッケージをインストールします。

$ sudo apt-get install auto-install auto-complete-mode yatex
Anything

Anything は、M-x auto-install-batch から anything を選択してインストールできます。id:tomoya さんの もう初心者なんて言わせない、Anything で始まる Emacs 道。 - 日々、とんは語る。 が参考になるでしょう。

Auto Complete Mode

Auto Complete Mode は auto-complete-mode パッケージをインストールするだけで既に終わっております。

YaTeX

YaTeXyatex パッケージをインストールするだけで、ほぼ終わります。

が!!!、Anything の恩恵を授かるためには、1 つ重要な設定を修正しないといけません!vine-default-yatex.el で設定されている、やてふのデフォルト設定でもある begin/end 型環境のショートカットによる補完を無効にする必要があります。つまり、

(setq YaTeX-no-begend-shortcut t)

としないといけません。

実は、Vine Linux 5 がリリースされたとき、vine-default の仕組みを導入しましたが、そのとき yatex パッケージでは (setq YaTeX-no-begend-shortcut t) としていました。そう、私のやてふ設定をそのまま入れていました。ところが、多くのやてふユーザは、デフォルトのやてふのまま使っている方が多く、この設定が受け入れられませんでした*2

以来、begin/end 型環境は、vine-default-yatex でもやてふのデフォルトの挙動と同じく、「ショートカット」による補完にしております。もし Anything がいつの日か Emacs 標準装備になった暁には、やてふの設定も (setq YaTeX-no-begend-shortcut t) にしようと妄想しております (^^

auto-complete-yatex

auto-complete-yatex に書いております。とくに何も難しいことをやっておりません。

また、ac-source-yatex-user-candiates に登録する一例として、いくつかあげておきます。

(setq ac-source-yatex-user-candiates
      (list 
       ;; documentclasses and these options
       "jsarticle" "jsbook" "beamer" 
       "ltjarticle" "iamjatex"
       "Proof" "tombo" "mentuke" "cameraready"

       "Lbox[]{}" "Rbox[]{}" "Pbox{}" "DDbox[]{}" "TDbox{}{}"
       "ruby{}{}"
       "Hang"
       "ignorespaces"
       "phantom" "hphantom" "vphantom"
       "makeatletter" "makeatother"
       "textregistered"
       "setbox" "lower" "raise" "llap" "rlap" "smash"
       "hbox{}" "mbox{}" "fbox{}" "parbox[]{}"
       "fboxsep"
       "hspace*{}";; "hfil" "hfill" "hss" "hskip" 
       "vspace*{}";; "vfil" "vfill" "vss" "vskip" 
       "baselineskip" "onelineskip" "halflineskip"
       "subtitle" "jsubtitle" "esubtitle" 
       "nonumber"
       "noindent" "mathindent" "parindent" "hangindent" 
       "newpage" "Newpage"
       "fallingdotseq"
       "arraycolsep" "arraystretch"
       
       ;; around figure env.
       "figure*"
       "scalebox{1}{\\includegraphics{}}"
       "capwidth" "ecapwidth" 
       "capwidth\\columnwidth" "ecapwidth\\columnwidth" 
       "columnwidth" "textwidth"

       ;; around table env.
       "Hline"


       ;; for numbering macros
       "ENUM{1}" "ENUM{2}" "ENUM{3}" "ENUM{4}" "ENUM{5}" 
       "ENUM{6}" "ENUM{7}" "ENUM{8}" "ENUM{9}" 
       "Enum{1}" "Enum{2}" "Enum{3}" "Enum{4}" "Enum{5}" 
       "Enum{6}" "Enum{7}" "Enum{8}" "Enum{9}" 
       "MARU{1}" "MARU{2}" "MARU{3}" "MARU{4}" "MARU{5}" 
       "MARU{6}" "MARU{7}" "MARU{8}" "MARU{9}" 
       "maru{1}" "maru{2}" "maru{3}" "maru{4}" "maru{5}" 
       "maru{6}" "maru{7}" "maru{8}" "maru{9}" 
       "RN{1}" "RN{2}" "RN{3}" "RN{4}" "RN{5}" "RN{6}" "RN{7}" "RN{8}" "RN{9}" 
       
;; some templetes of preamble

;; some templetes of LaTeX environments
;; figure
"begin{figure}[tb]
\\begin{center}
 \\scalebox{1}{\\includegraphics{}}
\\end{center}
\\caption{}
\\label{}
\\end{figure}"

"begin{figure}[b]
\\leavevmode
\\hbox to \\hsize{%\\hss
 \\begin{minipage}{\\textwidth}
 \\capwidth\\textwidth
 \\begin{center}
  \\scalebox{1}{\\includegraphics{}}
 \\end{center}
 \\caption{}
 \\label{}
 \\end{minipage}\\hss
}%
\\end{figure}"

;; table
"begin{table}[tb]
\\caption{}
\\label{}
\\begin{center}
 \\scalebox{1}{\\includegraphics{}}
\\end{center}
\\end{table}"

"begin{table}[tb]
\\caption{}
\\label{}
\\begin{center}
 \\begin{tabular}{ccc}
 & & \\\\
 \\end{tabular}
\\end{center}
\\end{table}"

;; enumerate
"begin{itemize}
\\item 

\\end{itemize}"

;; enumerate
"begin{enumerate}
\\item 

\\end{enumerate}"

;; minipage
"begin{minipage}[b]{.49\\hsize}

\\end{minipage}"
"begin{minipage}{\\textwidth}

\\end{minipage}"

;; thebibliography
"begin{thebibliography}{99}
\\bibitem{}

\\end{thebibliography}"

;; frame for Beamer class
"begin{frame}{}

\\end{frame}"

"begin{frame}{}
\\begin{enumerate}
\\item 

\\end{enumerate}
\\end{frame}"

"begin{frame}{}
\\begin{itemize}
\\item 

\\end{itemize}
\\end{frame}"

"begin{frame}{}
\\begin{block}{}
\\begin{itemize}
\\item 

\\end{itemize}
\\end{block}
\\end{frame}"

"begin{frame}[fragile]{}{}

\\begin{lstlisting}

\\end{lstlisting}

\\end{frame}"


;; 行列
"left(
\\begin{array}{cc}
 & \\\\
 & \\\\
\\end{array}
\\right)"
"left(
\\begin{array}{ccc}
 & & \\\\
 & & \\\\
 & & \\\\
\\end{array}
\\right)"

;; cases
"begin{cases}
 & \\\\
 & \\\\
\\end{cases}"
	    ))

I am Just Another TeXnician. の元ネタは…、

JAPH = Just Another Perl Hacker(Just another Perl hacker - Wikipedia, the free encyclopedia)です。Just Another Perl Programmer の場合もあります。これは、perl コードで "Just Another Perl Hacker" だけを出力する文化です。

らくだのアスキーアート(AA)や世界地図の AA で、 "Just Another Perl Hacker" や "Hello World" の文字列を出力するなんて、面白すぎます*3

#!/usr/bin/env perl
 
undef$/;$_=<DATA>;y/ODA\n / /ds;@yoda=map{length}split;print chr
oct join('',splice(@yoda,0,3))-111 while@yoda;
__DATA__
         00O00O000O00O0000      000O         DD000000O0
        0DO0000000O0000O00     O00000        00O00000O0O
        0000      0O0         O00  O00       00D     0DO
         00O0     0O0        00D    000      DO0D00000D
          0O00    DOD       000000O00000     000  O00O
 DD0000D000O0     000      0O00O0000D00DO    0OD   D00O000D00O0
 00000DO00O0      000     000O        00D0   O0D    O00000O0DO0
  
 0O000   OD0D   O00O0   0000         DDDO000000      O00O000000
  0O000 O00DDO 00000   0O0D00        00O0O00000O    0O00O000000
   0O0O00OD00000DDD   00O  0D0       DDD     D0O    00O0D
    00000O00000000   O00    DO0      D00D00O000      00D00
     D0O00  O0000   000O000O00DO     000  00O0        0OD00
      O00    000   0O000D000O00O0    000   0D0O000000O00O00
       0      0   0O0D        0000   0O0    0O0000000O000O

そこで、TeX (LaTeX) でも同様なことで遊んでいる人がいるかと思って、ぐーぐる先生に聞いてみたところ、どうやらいないっぽいことが分かりました(分かっておりました)。いつの日か、このネタをやる機会を待っていたところ、たまたま今年の LT 枠がなかなか埋まらなかったこともあり、笑い役担当で実行委員自ら立候補した次第です。

Just Another TeXnician の中身は?

「Just Another」は、「ありきたりの、ありふれた、月並みな」という意味です。

そんな平凡な TeX つかいが、iamjatex.sty を書いてみたわけです。だから、実用性ゼロです(^^ そうそう、iamjatex.sty のライセンスは、public domain にすることにしますので、その代わりに、ぜひとも Just Another TeXnician 文化を TeX でも築けたらと思ったり、思わなかったり(笑

\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{iamjatex}
  [2011/10/16 v0.1 defines iamjatex (I am Just Another TeXnician) environment]

\newif\if@iamjatexdebug \@iamjatexdebugfalse
\DeclareOption{debug}{\@iamjatexdebugtrue}

\DeclareOption*{\PassOptionsToPackage{\CurrentOption}{iamjatex}}
\ProcessOptions\relax

%% take verbatim env. from latex.ltx
%% define iamjatex
\begingroup \catcode `|=0 \catcode `[= 1
\catcode`]=2 \catcode `\{=12 \catcode `\}=12
\catcode`\\=12 
|gdef|@xiamjatex#1\end{iamjatex}[|@iamjatex@aa[#1]|end[iamjatex]]
|endgroup
\def\@iamjatex{\trivlist \item\relax
  \if@minipage\else\vskip\parskip\fi
  \leftskip\@totalleftmargin\rightskip\z@skip
  \parindent\z@\parfillskip\@flushglue\parskip\z@skip
  \@@par
  \@tempswafalse
  \def\par{%
    \if@tempswa
      \leavevmode \null \@@par\penalty\interlinepenalty
    \else
      \@tempswatrue
      \ifhmode\@@par\penalty\interlinepenalty\fi
    \fi}%
  \let\do\@makeother \dospecials
  \obeylines \iamjatex@font \@noligs
  \hyphenchar\font\m@ne
  \everypar \expandafter{\the\everypar \unpenalty}%
}
\def\iamjatex{\@iamjatex \frenchspacing\@vobeyspaces \@xiamjatex}
\def\endiamjatex{\if@newlist \leavevmode\fi\endtrivlist}
\def\iamjatex@font{\normalfont\sffamily\Huge}

%% Don Knuth, H. Okumura AA: characters: #@%&X27/1:. 
\newif\if@iamjatexchar \@iamjatexcharfalse
\def\@iamjatex@aa#1{%
 \@iamjatexcharfalse
 \@tempcnta 65\relax
 \def\space{\ }%
 \@tfor\ch@r:=#1\do{%
   \def\@tempchar{X}%is a flag to output ``iamjatexchar''
   \ifx\ch@r\@tempchar\relax
     %%A-Z (65-90)
     \ifnum\@tempcnta>64\relax \ifnum\@tempcnta<91\relax \@iamjatexchartrue\fi\fi
     %%a-z (97-122)
     \ifnum\@tempcnta>96\relax \ifnum\@tempcnta<123\relax \@iamjatexchartrue\fi\fi
     \if@iamjatexchar
       \char\@tempcnta%
       \if@iamjatexdebug $_{(\number\@tempcnta)}$\fi
       \@iamjatexcharfalse
       \@tempcnta 65\relax
     \fi
     %%output \space if \@tempcnta is over 123
     \ifnum\@tempcnta>122\relax
       \if@iamjatexdebug \textvisiblespace\else\space\fi
       \@tempcnta 65\relax
     \fi
   \else
     %%1, 2, 7 are plus factors of \@tempcnta
     \def\@tempchar{1}%
     \ifx\ch@r\@tempchar\relax \advance\@tempcnta\@tempchar\fi
     \def\@tempchar{2}%
     \ifx\ch@r\@tempchar\relax \advance\@tempcnta\@tempchar\fi
     \def\@tempchar{7}%
     \ifx\ch@r\@tempchar\relax \advance\@tempcnta\@tempchar\fi
   \fi
 }%
}


\endinput
簡単な解説

\begin{iamjatex} ... \end{iamjatex} の実体は、基本的に verbatim 環境です。\begin{verbatim} から \end{verbatim} までの間にある文字列をごっそりと \@tfor で回して、あーだこーだとやっているだけにすぎません。

alphabetの出力に利用しているのは、\char'XX です。つまり、\char'65 が「A」、\char'66 が「B」、…、\char'90 が「Z」、\char'97が「a」、…、\char'122 が「z」を使っているだけです。アスキーアート中の数字を足し算していき、X がきたときの総和によって、どの文字を出力するか決めています。

これだけです!

当日に使っていた iamjatex.sty のバージョンは v0.1.1???

アスキーアートを自動で生成するツールを利用したものの、それはベースにすぎず、メッセージを一文字ずつ出力していくために、手作業で全部やらないといけないので、大変に時間がかかりました。

実は、Knuth 巨匠と奥村先生のアスキーアートを作成するのに膨大な時間がかかりまして、出力するメッセージを前日に修正したりしておりました。そのために、当日にタイプセットにかけていた iamjatex.sty のバージョンは、0.1.1 だったりします (^^ 早い話、若干ズルをしたわけです、ハイ!どこをズルしているのか、よーく目を凝らせば、分かるかと思います。

iamjatex.sty v0.1 と v0.1.1 との差分は…、考えてみてください(おぃ

Features???

iamjatex.sty は勢いで作ったので、技術的にとくにすごいことを何もしていません。全面的にアルゴリズムを変えてしまうのがよいでしょう。日本語対応もがんばればできるでしょう。もっと面白い TeX コードで書いてくれる人、待っています!私も暇なときに考えてみます。いや、ホント、実用性ゼロなんで、これ(^^;;

もっと魅力的で、Just Another TeXnician なコードを絶賛募集中です(笑

どうしてデモンストレーションの大部分が失敗したか?(苦笑

何十回もテストをしていたのに、あそこまでグダグダになるとは、想定外でした(^^

原因の一つは、プロジェクタに映したときの解像度が小さすぎたことです。これでは、Knuth 巨匠のお顔も全て表示されません(泣 また、奥村先生のお顔も全部表示できず、残念なことになってしまいました。

もうひとつの原因は、ヘッダにあったコマンド実行の記述が間違っていたことです。たぶん、LT 直前のテスト時に誤って「!」を消してしまったんだと思います。

-%# lualatex test && evince -f test.pdf
+%#! lualatex test && evince -f test.pdf

敢えて言うのであれば、最悪の自体に備えて、デモンストレーションをスクリーンショットした版のスライドも用意しておくべきでした (^^;;

「私は芸人じゃないです!」

大事なことなので、もう一度述べますね。

「私は芸人じゃないです!」

さいごに…、

私のこの LT は、何も技巧がなく、先人のみなさまの偉業を組み合わせただけにすぎません。

Knuth 巨匠、奥村先生、Emacs 開発者のみなさま、Anything をメンテナンスなさっておられる @rubikitch さん(id:rubikitch)、Auto Complete Mode 作者の松山さん、やてふ作者の広瀬さんをはじめ、すべての TeX/LaTeX に関わる方々、Emacs に関わる方々に、あらためて感謝いたします。

奥村先生、ご還暦おめでとうございます。懇親会で、赤ちゃんちゃんこをお召になられたとき、にっこりと笑顔な奥村先生のお顔が印象的でした*4

*1:TeXユーザの集い 2011 自体のレポートは、別途、書く予定です。

*2:vine-users:079475 yatexのコマンド補完 http://ml.vinelinux.org/vine-users/msg29470.html

*3:CPAN 以下にある JAPH があること自体、文化だという証拠です。 http://www.cpan.org/misc/japh

*4:奥村先生が twitpic に上げておられます! 一昨日の #texconf11 で18歳(52進)記念に赤いちゃんちゃんこを贈られ恥ずかしがっているところ@東大生研... on Twitpic

Vine Linux 6 で Redmine-1.2.1 を運用中

Ruby on Rails のアプリケーションは、rubygems のバージョンと gem たちのバージョンの組合せが絶妙なバランスなので、バージョン選定に非常に苦労します (^^;;

Redmine のインストール方法は、公式のドキュメントはじめ、たくさんありますので、そちらに譲るとしまして、ここでは rubygems のバージョンと gems の組み合わせをあげておくだけにとどめます。

Redmine-1.2.1 の場合は、ruby-1.8.7 に以下の gems の組み合わせで、運用できております。ちなみに、データベースは SQLite3 を使っております。

$ sudo gem install rubygems-update --no-rdoc --no-ri
$ sudo gem update --system 1.7.2
$ sudo gem install -v=0.8.7 rake --no-rdoc --no-ri
$ sudo gem install -v=1.1.0 rack --no-rdoc --no-ri
$ sudo gem install -v=2.3.11 rails --no-rdoc --no-ri
$ sudo gem install -v=0.4.2 i18n --no-rdoc --no-ri
$ sudo gem install sqlite3-ruby --no-rdoc --no-ri

たとえば、こんな感じで Vine Linux のプロジェクトを作って、自分の作業をチケットで登録します。

Vine Linux の開発作業もますます進むとよいですなー(^^ 仕事でも Redmine を活用したいな!おっし、やってやる!

\NabeAzz を作ってみた

ZR さんのブログであるマクロツータに、 日本で TeX できる人の数→(?) - マクロツイーター のような投稿がありました。その投稿の NabeAzz にひとりで大爆笑してしまいました。

以下の動作を行うマクロ \NabeAzz を作れ。

\NabeAzz{<整数n>} は 1 から n までの整数の 10 進表記を順に空白区切りで出力する。ただし、整数が「3 の倍数である」または「(その 10 進表記に)数字 3 を含む」場合は、フォントを「Computer Modern Funny Italic」の 12pt(または LaTeX の場合は \large)に変えて出力する。その他の条件は以下の通り。

  • 引数の <整数n> は正であり、かつ数字列で与えられると仮定してよい。想定外の引数を与えた場合の動作は何も規定しない。
  • 「Computer Modern Funny Italic」の TeX でのフォント名(TFM 名)は「cmfi10」である。LaTeX では「エンコーディング OT1、ファミリ cmfr、シリーズ m、シェープ it」に割り当てられている。

付帯条件:

  • フォーマットは plain TeX または LaTeX2e とする。
  • 使用フォーマットのユーザ命令、内部定義マクロ、TeX プリミティブの全てを自由に使える。
  • さらに外部パッケージを使用しても構わない。
  • シェル実行機能(\write18)は使用禁止。(←書き忘れてた ;-) )
  • 拡張エンジンの機能も使用可能である。ただし、「LuaTeX で Lua インタプリタを呼び出す」ことだけはダメ。;-)
  • 制限時間は実働で 24 時間とする。
  • あらゆる形態の参考文献を参照して構わない。ただし、「この問題の答えそのもの」および「TeX での FizzBuzz の実装そのもの」は除外する。


さて、あなたは TeX を使えますか……?

http://d.hatena.ne.jp/zrbabbler/20110815/1313398638

NabeAzz を TeX でやったらどうなるか面白そうなので、さっそくチャレンジしてみました。

NabeAzz.tex は、以下のとおりです。

%#!pdflatex NabeAzz
%#LPR acroread NabeAzz.pdf
\documentclass{article}

\makeatletter
\def\NabeAzz@font{\normalfont}%normal
\def\NabeAzz@h@font{%aho
  \usefont{OT1}{cmfr}{m}{it}\Large}%\large
\def\NabeAzz#1{%
  \@tempcnta\z@\relax%%loop counter
  \@whilenum \@tempcnta<#1 \do{%
    \advance\@tempcnta\@ne
    \@tempcntb\z@\relax
    %%case 1
    \chk@h@thr@@{\@tempcnta}{\@tempnuma}%
    \ifnum\@tempnuma=\@ne
      \@tempcntb\@ne\relax
    \fi
    %%case 2-1
    \@m@d{\@tempcnta}{3}{\@tempnuma}%
    \ifnum\@tempnuma=\z@
      \@tempcntb\@ne\relax
    \fi
    %%case 2-2
    %% \sum@@ight@digits{\@tempcnta}{\@tempnumb}%
    %% \@m@d{\@tempnumb}{3}{\@tempnuma}%
    %% \ifnum\@tempnuma=\z@
    %%   \@tempcntb\@ne\relax
    %% \fi
    %%output
    \ifnum \@tempcntb=\z@
      {\NabeAzz@font \number\@tempcnta}%
    \else
      {\NabeAzz@h@font \number\@tempcnta}%
    \fi
    \space
  }%
}

\newcount\@temp@m@dcntp
\newcount\@temp@m@dcntq
\newcount\@temp@m@dcntr

\def\@m@d#1#2#3{%%#1 % #2, return #3
  \@temp@m@dcntq#1\relax
  \@temp@m@dcntr#2\relax
  \ifnum \@temp@m@dcntq=\@temp@m@dcntr \@temp@m@dcntq\z@\relax\fi
  \@whilenum \@temp@m@dcntq>\@temp@m@dcntr \do{%
    \@temp@m@dcntp\@temp@m@dcntq\relax
    \divide \@temp@m@dcntp by \@temp@m@dcntr    % q = a/b
    \multiply \@temp@m@dcntp by -\@temp@m@dcntr %
    \advance \@temp@m@dcntp by \@temp@m@dcntq   % r = -bq + a
    \@temp@m@dcntr\@temp@m@dcntq\relax
    \@temp@m@dcntq\@temp@m@dcntp\relax          % q <-> r
  }%
  \edef#3{\the\@temp@m@dcntq}\relax
}

\def\chk@h@thr@@#1#2{%#1: integer < 10^{8}
  \edef\chk@h@thr@@@temp{\@ight@digits{#1}}%
  \expandafter\@chk@h@thr@@@ight@digits\chk@h@thr@@@temp{#2}}
\def\@chk@h@thr@@@ight@digits#1#2#3#4#5#6#7#8#9{%
  \ifnum #1=\thr@@ \def#9{\@ne}\relax \else
   \ifnum #2=\thr@@ \def#9{\@ne}\relax \else
    \ifnum #3=\thr@@ \def#9{\@ne}\relax \else
     \ifnum #4=\thr@@ \def#9{\@ne}\relax \else
      \ifnum #5=\thr@@ \def#9{\@ne}\relax \else
       \ifnum #6=\thr@@ \def#9{\@ne}\relax \else
        \ifnum #7=\thr@@ \def#9{\@ne}\relax \else
         \ifnum #8=\thr@@ \def#9{\@ne}\relax \else
          \def#9{\z@}\relax
         \fi\fi\fi\fi\fi\fi\fi\fi}

\def\sum@@ight@digits#1#2{%#1: integer < 10^{8}
  \edef\sum@@ight@digits@temp{\@ight@digits{#1}}%
  \expandafter\@sum@@ight@digits\sum@@ight@digits@temp{#2}}
\newcount\@sum@@ight@digitscnt
\def\@sum@@ight@digits#1#2#3#4#5#6#7#8#9{%
  \@sum@@ight@digitscnt#1\relax
  \advance \@sum@@ight@digitscnt #2
  \advance \@sum@@ight@digitscnt #3
  \advance \@sum@@ight@digitscnt #4
  \advance \@sum@@ight@digitscnt #5
  \advance \@sum@@ight@digitscnt #6
  \advance \@sum@@ight@digitscnt #7
  \advance \@sum@@ight@digitscnt #8
  %%
  \edef#9{\the\@sum@@ight@digitscnt}\relax
}

\def\@ight@digits#1{%
  \ifnum#1<10000000 0\fi
  \ifnum#1<1000000  0\fi
  \ifnum#1<100000   0\fi
  \ifnum#1<10000    0\fi
  \ifnum#1<1000     0\fi
  \ifnum#1<100      0\fi
  \ifnum#1<10       0\fi
  \number#1}

%%from /usr/share/texmf-dist/tex/latex/base/ot1cmfr.fd
\DeclareFontFamily{OT1}{cmfr}{\hyphenchar\font45 }
\DeclareFontShape{OT1}{cmfr}{m}{n}{%
      <->cmff10%
    }{}
\DeclareFontShape{OT1}{cmfr}{m}{it}{%
      <->cmfi10%
    }{}

\makeatother

\begin{document}
\noindent
\NabeAzz{99999}%% OK
%\NabeAzz{200000}%% OK
%\NabeAzz{999999}%%!!Fatal error occurred, no output PDF file produced!
\end{document}

\NabeAzz のアルゴリズムとおおざっぱなコードは、30 分くらいでできていたのですが、マクロの名前を整えたり、マクロの仕様をちょっと変えたり、「3 の倍数」判定法を試したり、time で時間を測ったり…など、色々とやっているうちに、3 時間にもなってしまいました (^^;;

ほかのアプローチやもっときれいなマクロを書けるかもしれませんが、\NabeAzz に関して、わたくしはひとまずこれくらいにしておきます。もっと美しいコード例がありましたら、ぜひとも教えてくださいませ。

いくつかいいわけを。

  • ZR さんの出題では、アホになる数字の場合に 12pt にせよという指示がありましたが、わたしは 14pt にしました。ZR さんは品がございますので、12pt になさっておられるのだと思いますが、やはりアホな数字ですから、ふざけてみました。
  • cmfr のついては、ot1cmfr.fd からとってきて、<-> にして逃げました。

「3 の倍数」判定法にしてみる

「3 の倍数」判定法は、「整数 n が 3 で割りきれるための必要十分条件は、n の各桁の数字の総和が 3 で割りきれる。」なのですが、これを \NabeAzz で使ってみると、直接 mod 3 するよりも、計算時間が増えました。手元の計算機環境と実行結果は以下のとおりです。

CPU Intel Core 2 Duo E8500 3.16GHz
MEM PC6400 DDR2 SDRAM 8GB (2GBx4)
OS Vine Linux 6.0 x86_64
TeX 環境 Vine Linux 6 の TeX Live 2009
$ pdflatex --version
pdfTeX 3.1415926-1.40.10-2.2 (Web2C 2009)
kpathsea version 5.0.0
Copyright 2009 Peter Breitenlohner (eTeX)/Han The Thanh (pdfTeX).
There is NO warranty.  Redistribution of this software is
covered by the terms of both the pdfTeX copyright and
the Lesser GNU General Public License.
For more information about these matters, see the file
named COPYING and the pdfTeX source.
Primary author of pdfTeX: Peter Breitenlohner (eTeX)/Han The Thanh (pdfTeX).
Compiled with libpng 1.2.46; using libpng 1.2.46
Compiled with zlib 1.2.5; using zlib 1.2.5
Compiled with poppler version 0.16.6

$ time pdflatex NabeAzz.tex

\NabeAzz{99999}
Case 2-1: 
real    0m8.016s    0m7.789s    0m7.946s
user    0m7.902s    0m7.619s    0m7.821s
sys     0m0.028s    0m0.039s    0m0.039s

Case 2-2: 
real    0m8.086s    0m8.320s    0m8.165s
user    0m7.965s    0m8.206s    0m8.073s
sys     0m0.034s    0m0.028s    0m0.028s

\NabeAzz{200000}
Case 2-1: 
real    0m42.150s    0m42.134s    0m42.315s
user    0m41.870s    0m41.858s    0m42.061s
sys     0m0.097s     0m0.105s     0m0.117s 

Case 2-2: 
real    0m57.169s    0m57.478s    0m56.738s
user    0m56.921s    0m57.129s    0m56.496s
sys     0m0.109s     0m0.124s     0m0.084s 

追記:あべのりさんに触発されて、\NabeAzz を変えてみた

あべのりさんが にっき♪ で、\NabeAzz をなんか適当やっていた*1。たしかに mod N を作らなければ、数行で終わりますね!

というわけで、上記の \@ight@digits を使わずに*2、区切り文字を入れて \ifx で順番に調べる方法に変えてみた*3。以下では \@m@d を、相変わらず使っているが、そこはご愛嬌ということで。

%#!pdflatex NabeAzz
%#LPR acroread NabeAzz.pdf
\documentclass{article}

\makeatletter
\newif\if@NabeAzz \@NabeAzzfalse

\def\NabeAzz@font{%
  \if@NabeAzz \usefont{OT1}{cmfr}{m}{it}\Large\else\normalfont\fi}

\def\NabeAzz#1{%
  \@tempcnta\z@\relax%%loop counter
  \@whilenum \@tempcnta<#1 \do{%
    \advance\@tempcnta\@ne
    %%case 1
    \expandafter\chk@NabeAzz\number\@tempcnta E%
    %%case 2
    \@m@d{\@tempcnta}{3}{\@tempnuma}%
    \ifnum\@tempnuma=\z@ \@NabeAzztrue\fi
    %%output
    {\NabeAzz@font \number\@tempcnta}%
    \space
  }%
}

\newif\if@NabeAzzEnd
\def\chk@NabeAzz#1{%
  \@NabeAzzfalse
  \@NabeAzzEndfalse
  \@chk@NabeAzz#1
}
\def\@chk@NabeAzz#1{%
  \@@chk@NabeAzz#1%
  \if@NabeAzzEnd\else\expandafter\@chk@NabeAzz\fi
}
\def\@@chk@NabeAzz#1{%
  \def\@tempa{#1}%
  \def\@tempb{E}%
  \ifx\@tempa\@tempb
    \@NabeAzzEndtrue
  \else
    \def\@tempb{3}%
    \ifx\@tempa\@tempb\@NabeAzztrue\fi
  \fi
}

\newcount\@temp@m@dcntp
\newcount\@temp@m@dcntq
\newcount\@temp@m@dcntr

\def\@m@d#1#2#3{%%#1 % #2
  \@temp@m@dcntq#1\relax
  \@temp@m@dcntr#2\relax
  \ifnum \@temp@m@dcntq=\@temp@m@dcntr \@temp@m@dcntq\z@\relax\fi
  \@whilenum \@temp@m@dcntq>\@temp@m@dcntr \do{%
    \@temp@m@dcntp\@temp@m@dcntq\relax
    \divide \@temp@m@dcntp by \@temp@m@dcntr    % q = a/b
    \multiply \@temp@m@dcntp by -\@temp@m@dcntr %
    \advance \@temp@m@dcntp by \@temp@m@dcntq   % r = -bq + a
    \@temp@m@dcntr\@temp@m@dcntq\relax
    \@temp@m@dcntq\@temp@m@dcntp\relax          % q <-> r
  }%
  \edef#3{\the\@temp@m@dcntq}\relax
}

%%from /usr/share/texmf-dist/tex/latex/base/ot1cmfr.fd
\DeclareFontFamily{OT1}{cmfr}{\hyphenchar\font45 }
\DeclareFontShape{OT1}{cmfr}{m}{n}{%
      <->cmff10%
    }{}
\DeclareFontShape{OT1}{cmfr}{m}{it}{%
      <->cmfi10%
    }{}
\makeatother

\begin{document}
\noindent
\NabeAzz{9999}
\end{document}

「3 の倍数と 3 が付く数字のときだけアホになります」wikipedia:渡辺鐘 でウケそうなのは、40 番までだと思う件

このアホになる数字の列を見て、40 番以降がツラいですねー。このあと、アホになる数字が 130 番台までまばらになるので、とたんにつまらなくなります。そのつぎに大きな山があるのが 300 番台ですが、さすがに 300 番台までこの芸を続けないでしょう。

3000 番台になると、もうアホになる数字ばっかりですよね\<(w

謝辞

というわけで、ZR さんの「\NabeAzz を作れ!」には、たいへん楽しませもらいました。ありがとうございました。

つぎは、Postscript で NabeAzz を(おぃ

*1:"適当" というのは、「適切」という意味ですヨ。

*2:実は、\@ight@digits っぽい処理って、「11」を「十一」とか、こーゆーときに使った以来だったんで、感慨深かったりしておりました。

*3:この方法だと、N が 10^{8} 以上のときも対応できる。しかし、N = 300000 くらいで、\NabeAzz{N} がすでに Fatal error occurred になるわけだが\<(w

auto-complete-mode パッケージを作ってみた

昨晩、VineSeed および Vine Linux 6 向けに http://cx4a.org/software/auto-complete/index.ja.html のパッケージを、auto-complete-mode パッケージとして put しました。すでに、リポジトリに反映されているので、すぐに試せます。

vine-default-auto-complete.el により、基本的な標準設定済みですので、とくに何も設定せずに利用可能です。

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Auto Complete Mode v1.3.1 の設定
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; (add-to-list 'load-path "/usr/share/emacs-23.3/site-lisp/auto-complete")
(require 'auto-complete-config)
(add-to-list 'ac-dictionary-directories 
	     "/usr/share/emacs-23.3/site-lisp/auto-complete/ac-dict")
(ac-config-default)

TeX と Auto Complete Mode との連携

■[Emacs][TeX][Vine] auto-complete.el にやてふ拡張を作ってみた [id:munepi:20090304:1236187280] もそのまま使えますが、世の中、同じようなことを考える人がたくさんいるもんです。auto-complete-latex.el を作っている方もおられますね。正直、私がやろうとしていた prefix により補完候補を絞り込む機能をほとんど実装しておられます。auto-complete-latex、オススメしておきます!いや、イチオシです。

auto-complete-yatex は…、気が向いたら更新するとしよう。 以下に晒しました。

https://gist.github.com/munepi/5298924

auto-complete-yatex.el の設定は、いたって簡単!以下の設定を追加するだけ。

;; ;; 必要であれば、以下のような感じで追加していく
;; (setq ac-source-yatex-user-candiates
;;       (list 
;; 	    "phantom" "hphantom" "vphantom"
;; 	    "makeatletter" "makeatother"
;; 	    ))
(require 'auto-complete-yatex)

auto-complete-yatex.el は、特別にたくさんの辞書を持っていないので、動作が軽いです。

何度も言いますが、auto-complete-latex、イチオシです。

wnn7egg との相性が悪い!?

wnn7egg を使っている環境で、Auto Complete Mode v1.3.1 を試したところ、日本語入力モードのときに、auto-complete-mode による補完が乱れてしまうみたいです。

とりあえず、toggle-input-method () に defadvice して、wnn7egg による日本語入力モードのときには auto-complete-mode を off にするようにしてみました。

(defadvice toggle-input-method (after wnn7egg-activate activate)
  (if wnn7-activate
      (global-auto-complete-mode 0) (global-auto-complete-mode 1)))

一言、言いたいことがあります!wnn7egg-activate が Not documented. ってどーゆーことー(笑

一般には、以下のようにしちゃってよいみたいです。

(defadvice toggle-input-method (after current-input-method activate)
  (if current-input-method
      (global-auto-complete-mode 0) (global-auto-complete-mode 1)))

Formatter Club 発足会に参加してきました

村上真雄さんから誘われて、Formatter Club 発足会のご案内 (CSS組版ブログ) に参加してきました。すでに、AH Formatter V6 の紹介 (CSS組版ブログ) から、Formatter Club 発足会のプレゼン資料などがリンクされています。個人的には、前田年昭さん(Line Lab.'s Web Page, East Asian Text Processing)、藤島雅宏さん(元電算写植機開発者)にお会いすることができたのも楽しかった。

奥村さん(奥村 晴彦 | Haruhiko Okumura)もいらっしゃったので、ついでに、実行委員としてしっかりと TeXユーザの集い 2011 も宣伝してきました(笑

簡単な XML 文書を TeX 形式へ変換してみる

Formatter Club 発足会のプレゼン中にでてきた簡単な XML 文書例を XSL-FO へ変換していたので、負けじと TeX 形式へ変換してみます。わざわざ TeX 形式へ変換する理由はとくにありません、ハイ。ここでは、xsltproc(XSLT プロセッサのひとつ)を使って、XML 文書を TeX 形式へ変換します。なお、ここでの XML 変換および TeX 組版環境は、Vine Linux 6 RC1(Vine Linux)です。

さっそく、Formatter Club 発足会のプレゼン中にでてきた簡単な XML 文書例を書きます。以下の内容を foclub-example.xml として保存しておきます。実は、村上さんがお出しになった XML 文書例と若干違います(笑 <タイトル> タグと <本文> タグを入れました。

<?xml version="1.0" encoding="UTF-8"?>
<!-- FormatterClub 発足会 2011-07-27 に出てきた XML 文書例 -->
<文書>
  <タイトル>
    <表題>簡単XML入門</表題>
    <著者>てふラボ</著者>
  </タイトル>
  <本文>
    <見出し>XMLを書いてみる</見出し>
    <段落>XMLはこんなふうに書きます。</段落>
    <段落>XMLはこんなふうにも書けます。</段落>
  </本文>
</文書>

foclub-example.xmlTeX 形式へ変換するために、XSL をゴリゴリと書きます。以下の内容を foclub2tex.xsl として保存します。極々簡単な XSL です。

<?xml version="1.0" encoding="UTF-8" ?>
<!--  FormatterClub 発足会 2011-07-27 に出てきた XML 文書例 -->
<!--  foclub-example.xml を TeX 形式に変換 -->

<xsl:stylesheet 
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
   version="1.0">

  <xsl:output method="text" indent="no" encoding="UTF-8" />
  <xsl:strip-space elements='*'/>

  <xsl:template match="文書">
\documentclass{jsarticle}
<xsl:apply-templates />
  </xsl:template>

  <xsl:template match="タイトル">
\title{<xsl:value-of select="表題" />}
\author{<xsl:value-of select="著者" />}
\date{<xsl:value-of select="日付" />}
  </xsl:template>

  <xsl:template match="本文">
\begin{document}
\maketitle
<xsl:apply-templates />
\end{document}
  </xsl:template>

  <xsl:template match="見出し">
\section{<xsl:apply-templates />}
  </xsl:template>

  <xsl:template match="段落">
    <xsl:text disable-output-escaping = "yes">&#10;</xsl:text>
    <xsl:apply-templates />
    <xsl:text disable-output-escaping = "yes">&#10;</xsl:text>
  </xsl:template>

</xsl:stylesheet>

以下のコマンドを実行して、XMLTeX へ変換します。

$ xsltproc -o foclub-example.tex foclub2tex.xsl foclub-example.xml

生成された foclub-example.tex は以下のようになります。

\documentclass{jsarticle}

\title{簡単XML入門}
\author{てふラボ}
\date{}
  
\begin{document}
\maketitle

\section{XMLを書いてみる}
  
XMLはこんなふうに書きます。

XMLはこんなふうにも書けます。

\end{document}
  

TeX → PDF へ変換します。ここでは、日本語組版エンジンとして pTeX を使います。

$ platex foclub-example
$ dvipdfmx -r 1200 foclub-example

Adobe Reader で foclub-example.pdf を閲覧してみます。


XSL-FO と TeX との違いを考察、そして、次世代 TeX 組版への期待

foclub2tex.xsl をみると、XSL-FO 仕様へ変換する XSL とくらべて、ずいぶんとすっきりとしているようにみえます。それもそのはず、XSL-FO のプロパティに対応する TeX のそれが一切記述されていないのです。

日本語 TeX 組版で利用できるおもな汎用スタイルファイルは、ASCII さんの jarticle, jbook と奥村晴彦さんの jsarticle, jsbook です。これらのスタイルファイルは、とりあえず日本語 TeX 組版ができるだけであると割り切るべきでしょう。実際に、デザインの変更や独自拡張など組版結果を変更しようとすると、以下の 3 通りの方法が考えられます。

  • 汎用スタイルを指定した上で、いくつかのマクロを上書きする
  • デザインされた別のスタイルファイルを使う
  • XSL による XML から TeX への変換に特化した、テンプレートとして使えるスタイルファイルを作る

AH Formatter による XSL-FO (+ AH 拡張) 組版 または CSS 組版TeX 組版の共通点は、どちらもスタイルファイルを用意しないといけません。それぞれ XML + XSL、plain TeX に関する知識、プログラミングが必要です。

AH Formatter による組版TeX 組版との大きく異なる点がいくつかあります。

ひとつめは、ユーザによる組版自由度の制限です。現時点で主流である日本語 TeX 組版エンジンである pTeX 自体には、もはや手がはいらない状況であると考えてよいでしょう。その上で、TeX はユーザによる TeX プログラミングにより、自由度が高い組版が可能です。しかしながら、その自由度が高すぎることにより、TeX プログラミングの知識を持っていないユーザにとって、分かりにくさ・とっつきにくさがあり、それゆえの TeX の難しさがあるように思います。同時に、TeX に関する Bad known how が多いのも事実です。

ふたつめは、ドキュメントの論理的な構造です。TeX ドキュメントは、通常、XML ドキュメントのような構造化ドキュメントと言えない*1。もちろん、TeX コーディングに慣れた TeX ユーザであれば、TeX コーディングは自明で、そのドキュメントは、十分に構造化されていると思える。

みっつめは、ドキュメントの構造解析です。「TeX/LaTeX の syntax は何なのか?そして、どのようにそれを構造解析するのか?」に対して、「TeX の文法は TeX しか分からない」という事実があります。とくに、グルーピングは、通常の {hoge} [fuga] だけでなく、 /foo/ |wara| などのグルーピングを設けることができます。ひとつめ、ふたつめにも関わることですが、TeX によるコーディング、プログラミングに然るべき制限を設けなければ、なんでもありです。

以上を踏まえると、XML から TeX 組版をする場合には、

  1. XSL による XML から TeX への変換に特化した、テンプレートとして使えるスタイルファイルの作成
  2. TeX ドキュメントのチェッカーの開発
  3. TeX プログラミングおよびコーディングの制限

が必要だと考えます。

一方、次世代 TeX として、LuaTeX が注目されています。LuaTeX は pdfTeX の後継となる予定で、将来、標準に TeX 組版エンジンになります。ZR さん(id:zrbabbler)の去年に発表されたプレゼン資料 日本人の知らないTeX ~TeXユーザの集い2010・招待講演~ [電脳世界の奥底にて] から表現をおかりしますと、LuaTeX の実装機能は以下のように表現できます。

LuaTeX = pdfTeX + Omega + Lua + MetaPost + OpenType

LuaTeX が様々なレベルで TeX 処理へ割込処理できるようで、「⼊⼒テキストのフィルタ」処理ができる点があります。Omega の思想を持っているので、この入力テキストのフィルタ処理を利用して、プラグインのフィルタから XML パーサや XSLT プロセッサを呼ぶことで、XML ドキュメントの入力へ対応できるでしょう。また、LuaTeX の出力についても、TeX/LaTeX -> dvi/pdf だけでなく、TeX/LaTeX -> XML (XML-FO, XHTML など) や XML -> XML (XML-FO, XHTML など) などの出力も可能になるでしょう。

このような LuaTeX の未来が待っているなか、日本の TeX ユーザに対して 日本語組版処理の要件(日本語版) に準じて、スタイルファイルやツールを整備されることが期待されていると思います。すでに LuaTeX-ja プロジェクト日本語トップページ - OSDN が立ち上がっています。「XML ドキュメントから LuaTeX 組版エンジンを使って、日本語組版をして、XHTML や PDF にできたら…」と妄想するだけでもわくわくしませんか?(笑 したがいまして、TeX に対して、まだまだやることがたくさんあるように思います。

*1:もちろん、TeX ソースを構造化されたドキュメントのように記述することもできる。