feed

2013年11月13日, 編集履歴

JekyllのMarkdown設定(2013年11月18日追記)

 Jekyllを使ってウェブサイトとブログの再構築をした。その際に用いたMarkdown用の設定メモ。
 現時点での_config.ymlファイルのMarkdown関係の設定は以下。

markdown: redcarpet
redcarpet:
  extensions: ["autolink", "hard_wrap"]

 生の設定ファイルはgenjiapp.github.io/_config.yml at master

Markdownレンダラの変更

 JekyllのディフォルトのMarkdownレンダラはMaruku。これをRedcarpetに変更した。なぜ変更したか。きっかけは、MarukuではTwitterの埋め込みコード(以下のようなもの)

<blockquote class="twitter-tweet"><p>ヘウレーカ! JekyllでコンテンツをHTMLで書いて良いことと、レイアウト側だけではなくコンテンツ側でも include が使えることに気がついて、蒙が啓けた気がする</p>&mdash; Genji (@genji_tw) <a href="https://twitter.com/genji_tw/statuses/398471861828206592">November 7, 2013</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

がうまく変換できずエラーを吐くことに気がついたから。_config.ymlmarkdown: redcarpetと指定することで、MarkdownレンダラをMarukuからRedcarpetに変更できる。Redcarpetなら上記の埋め込みコードを正常に処理できる。

Redcarpetの拡張設定

 指定した拡張はautolinkhard_wrapの2つ。

 autolinkは http://genjiapp.com/ のような文字列を自動でリンクに変換してくれる。

 次にhard_wrap。Markdownは標準では空行を挿入しないと改段落にならない(ブラウザでの表示で行分けされない)。つまり、

あめんぼあかいな
あいうえお

ほげほげ

とMarkdownを書くと、変換後のHTMLは

<p>あめんぼあかいなあいうえお</p>
<p>ほげほげ</p>

のようになる。Markdown上での単なる改行は改段落とはならずひとつの<p>タグに纏められ(「あめんぼあかいなあいうえお」が一行で表示される)、空行を挟んで新しい<p>タグが始まる。これは他の軽量マークアップ言語でもよくある仕様である。個人的な趣味でこの仕様があまり好きではない。
 hard_wrapを有効にすると上記のMarkdownは

<p>あめんぼあかいな<br/>あいうえお</p>
<p>ほげほげ</p>

のように変換される。Markdown上での改行が変換後に改段落されないのは同様であるが、改行部分に<br/>タグが挿入されるようになる(ブラウザでの表示において行分けされる)。
 HTMLの<p>タグひとつが日本語の意味段落に相当し、形式段落を<br/>で作るというイメージである。

追記(2013年11月18日)

 当初、Redcarpetの拡張設定はもうひとつ、no_intra_emphasisを指定していた。そして記事中では以下のようなことを書いた。

 Markdownは標準では複数のアンダーバー_間の文字列をHTML変換時に強調タグ<em>でくくる。これの何が問題かというと、プログラムの変数名等でありがちなhoge_foo_barのような文字列が意図せず強調されてしまう。no_intra_emphasisはその動作を抑制する。

 Markdownの強調構文にはアンダーバーを使う方法ともうひとつ、アスタリスク*を使う方法がある。ここで私が誤解していたのが、no_intra_emphasisはアンダーバーを使う強調構文のみが対象であると思い込んでいたことである。しかしno_intra_emphasisはアスタリスクを使う構文でも同様に作用する。

 これの何が問題かというと、分かち書きをしない日本語文中では、余分な空白を入れないと強調構文が使えなくなるということである。つまり、

ほげほげ*強調*ふーばー

と書いても、

<p>ほげほげ*強調*ふーばー</p>

と出力される。強調構文にするには、余分な空白を挿入して

ほげほげ *強調* ふーばー

としなければならなくなる。そうすると出力にも当然余分な空白が入り込む。それはイヤなのでno_intra_emphasisは外すことにした。
 プログラムの変数名等でアンダーバーが意図しない強調になってしまうという問題は、インラインコード/コードブロック構文中なら関係ないと気づいた。コード片を書くときは元々インラインコード/コードブロック構文を使っていたので、そもそもno_intra_emphasisは必要ないという結論に至った。

2013年11月13日, 編集履歴

Jekyllを使ってウェブサイトを再構築

 Jekyllという静的ウェブサイト&ブログ生成システムとGitHub Pagesを用いて、ウェブサイトを再構築しました。
 以前からウェブページのホスティングにはGitHubが提供するGitHub Pagesというホスティングサーヴィスを利用してローカルで作成したHTML等をアップロードしていましたが、今回はそれに加えてJekyllという静的ウェブサイト&ブログ生成システムを用いました。

 GitHub Pagesでは、完全なウェブページをそのままアップロードする他にも、Jekyllというシステムを用いる方法が提供されています。
 JekyllはテンプレートとなるHTMLのガワを用意しておき、Markdown等を用いたコンテンツ文書を(HTML断片に変換して)流し込むことで静的なウェブページを生成します。ブログ等のように同じデザインのページを多く生成する必要がある場合に役立ちます。
 GitHub PagesのホスティングサーヴィスはJekyllを内蔵しており、構成ファイルをリポジトリィにプッシュすることで、自動的に静的なウェブサイトを生成してくれます。

 Jekyllを使ってウェブサイトの再構築をしようと思ったきっかけは、ブログを以前から使用していたGoogleのBloggerから移行し、新しく別のブログを始めたかったからです。Bloggerから離れたい理由はGoogleへの不信感ですが、それ以外にもブラウザ上のウェブインターフェイスで文章を書くのがやりづらいという理由もあります。しょーもないことをたくさん書いてある過去のブログ記事を抹消したいという思いもあります(なので旧ブログはそのうち閉鎖します)。
 他のよくあるブログサーヴィスに移行したところで、ウェブインターフェイスからは離れられません。であれば、元々利用していたGitHub Pagesが内蔵するJekyllを用いてブログを書こう、ブログをJekyllで書くならばウェブサイトの方もJekyllで管理しよう、というのが今回の再構築の理由です。

余談

 Jekyllの使い方を紹介しているページ等では、コンテンツ文書をMarkdown等の軽量マークアップ言語で書き、それをテンプレートに流し込んでいます。テンプレートではHTMLのガワを記述し、複数のテンプレート間で共通する構成要素があればそれを部品化してincludeしています。それがJekyllの基本的な使い方なので、当然そのように書きます。
 ブログ記事以外のページを書くときに、そこではたと困りました。テンプレートに流し込むシンプルな構成のブログ記事であればMarkdownで書けますが、ペラいちのページを単純なMarkdownの流し込みで表現するのは難しいです。Markdownはシンプルな構成の文書を書く際には有用ですが、HTMLの表現力を100%使うことはできません。
 異なるデザインの複数ページを作る場合(このウェブサイトの場合は各アプリケーションの紹介ページのような)はテンプレートを使い回しにくいので、各ページごとに専用のテンプレートを作成しなければならないのだろうか? それとも完全にふつうのHTMLを書くしかないのだろうか?

 悩むことしばし。

ヘウレーカ! JekyllでコンテンツをHTMLで書いて良いことと、レイアウト側だけではなくコンテンツ側でも include が使えることに気がついて、蒙が啓けた気がする

— Genji (@genji_tw) November 7, 2013

 コンテンツ文書を書くのにMarkdownではなく、HTMLが使えることに気づきました。さらに、includeコマンドをテンプレート文書だけではなく、コンテンツ文書にも書くことができることに気付き、問題は解決しました。
 通常はテンプレート内で使うことが多いであろうincludeコマンドをHTMLで書くコンテンツ文書内でも多用して、アプリケーション紹介ページ等を作成しました。このウェブサイトはGitHub Pagesでホスティングしているので、リポジトリィを見れば、どういう設定でどういう構成になっているのかが解ります。

2013年10月02日, 編集履歴

Google Adwardsのプロモーションコードに関するトラブル(2013年10月21日追記)

 「Google Adwordsが一ヶ月分無料」というようなプロモーションコードがGoogleから郵送されてくることがある。無視しても忘れた頃にまた何度も郵送してきたりする。同じようなダイレクトメールを受け取ったことがあるひともいるだろう。

 AdwordsはGoogleの検索結果等に広告を掲載してくれるサーヴィスである。広告を出稿するには当然料金が掛かるわけだが、それを「一ヶ月分無料でお試しください」と謳っているのが前述のプロモーションコードである。

 無料なら、ということでプロモーションコードを入力し、一ヶ月間広告の出稿を行なっていた。
 ところが、ふとクレジットカードの明細を見るとGoogle Adwordsの料金の請求が掛かっている。プロモーションコードの入力は正常に行えており、期間も料金も上限を超えていない。どういうことかとサポートに連絡したところ、以下のような返答をもらった。

 プロモーションコードで「利用金額」分が付与されるので、当然Adwordsを「利用」しなければならない。ところが付与された金額分で「利用」した分を相殺できないというのである。
 ダイレクトメールの文言には「一ヶ月分無料でお試しください」などとあるが、料金は必ず掛かり、その後も利用を継続しなければプロモーションコードの恩恵を受けられないのであれば、それは「無料でお試し」とは言えないのではないか?
 サポートでは請求の取り消しは難しいということである。サポート曰く、同様の連絡がこれまでにもあったということで、過去に比べればダイレクトメールの文面も改善されているということであるが、私はこのように実際に請求されて困っているわけである。

 諦めるしかないのだろうか。

追記(2013年10月21日)

 その後、Google Adwordsの「料金」ページを見ていると「処理中の払い戻し」なる項目があり、払わされた金額分と同額が表示されているのに気がついた。
 これは何だろう、結局返金してくれるのかだろうか。サポートに問い合わせをしたところ、この表示は間違いである、不具合である、払い戻しはない、という返答。
 なるほどなるほど。仮に今回のトラブルの原因がこちらの勝手な誤解、間違いにあったとして、こちらの間違いには容赦なく料金請求をする。しかしGoogleが「払い戻し」の表示をしておいて、払い戻しはない、不具合であるとして自分の間違いからは逃げるわけか。
 ご立派。

2013年08月20日, 編集履歴

佐野昌一(海野十三)の「虫喰い算大会」電子書籍版を公開

 佐野昌一(海野十三)の「虫喰い算大会」を横組みにし、問題部分をSVG画像化した電子書籍をGitHubで公開しました。

 「虫喰い算大会」は、探偵小説家の海野十三が本名の佐野昌一名義で出版した虫喰い算が多数掲載された本で、青空文庫で公開されています。

 AmazonのKindleストア等、青空文庫の作品をラインナップしている電子書籍プラットフォームからでもこの本を入手することは可能ですが、ひとつ問題があります。

 たとえばKindleストアの「虫喰い算大会」は、他の一般的な小説等と同じように縦組みで組版されています。これの何が問題かというと、青空文庫の「虫喰い算大会」の問題部分はプレインテキストでベタ組みされており、そのまま縦組みにすると問題の筆算が90度回転したかたちになってしまいます。さらに筆算の途中でページを跨いでしまうという問題もあり、読みにくいものになっています。
 Kindleストアに並んでいる青空文庫の本は自動変換されたものでしょうし、虫喰い算を扱った本書が一般の小説とは異なる特殊なものであるということで、これは仕方のない事です。

 そこで、「虫喰い算大会」を横組みにし、問題部分をSVG画像化して読みやすくした電子書籍を作成しました。
 問題部分を画像化することで美しく、かつページ跨ぎをさせないように読みやすくしました。底本である元々の「虫喰い算大会」は縦組みっぽいのですが、序文の解き方解説等で数字を多く扱うので、横組みの方が読みやすいだろうということで、横組みにしました。

Mac用EPUBリーダMurasakiでEPUB版を表示

Kindle PreviewerでMOBI版を表示

iPhoneのKindleでAZK版を表示

iPhoneのiBooksでEPUB版を表示

2013年01月04日, 編集履歴

OS Xステータスバーアプリケーションの作り方

ステータスバーアプリケーションについて

 ステータスバーとは、OS Xの画面上部に表示されるメニューバーの、右側に位置する部分である。メニューバーの右端には通知やSpotlightのアイコン、時計表示、システムによって制御される機能(音量やBluetooth等)のアイコン(メニューエクストラ)が並び、その次に様々なアプリケーションのアイコンが並んでいる。

 上記画像で言えば、Google NotifierやDropbox、Adium、ClamXavのアイコンがある赤く塗った領域がステータスバーである。アプリケーション自身が非アクティヴであるときやウィンドウ等を表示していないときも、状態を示したり何らかの機能を呼び出したりする場合にステータスバーにアイコン等の項目(ステータス項目)を配置することができる。

 ここで言う「ステータスバーアプリケーション」とはいわゆる「常駐アプリケーション」と呼ばれるものの一種である。アプリケーションを起動してもウィンドウやDockのアイコンが表示されず、代わりにステータスバーにテキストやアイコンを表示し、そこから呼び出されるメニューやウィンドウを用いる。基本的にはバックグラウンドで常に起動しておき、タイマや何らかのイヴェントをフックして動作するアプリケーションを想定する。
 ステータスバーアプリケーションの特徴は、

 ここでは上記のような特徴を持つアプリケーションを作成する。今回作成したプロジェクトはGenjiApp/StatusBarApp - GitHubで公開するので参照のこと。なおXcodeのヴァージョンは4.5.2を用いた。

Xcodeプロジェクトの作成

 Xcodeを起動し、New Project…からOS X ApplicationのCocoa Applicationを選択する。ここではProject NameをStatusBarAppとし、Create Document-Based Applicationはオフに、Use Automatic Reference Countingをオンにしてプロジェクトを作成した。

常駐アプリケーションとして設定する

 常駐アプリケーションとして設定するには以下の手順を行う。

  1. Xcodeウィンドウ左のProject Navigatorからプロジェクトを選択し、Project Editorを表示させる
  2. Project EditorのTARGETSからアプリケーションのターゲットを選択する
  3. Project EditorのInfoペインを表示させる
  4. Custom OS X Application Target PropertiesからApplication is agent (UIElement) Keyを追加し、TypeをBoolean、ValueをYESに設定する。

 この設定により、アプリケーションは常駐アプリケーションとして起動され、Dockにアイコンが表示されなくなる。同時に、ふつうのアプリケーションであればアクティヴ時にメニューバーに各種メニュー項目が表示されるが、それも表示されなくなり、Command + Option + Escapeで呼び出される「アプリケーションの強制終了」ダイアログにもアプリケーションが表示されなくなる。したがって、後述するメニュー等でアプリケーションを終了する手段を提供しておかないと、アクティビティモニタを使用しないとアプリケーションを終了するできなくなってしまう。

メニューの追加

 MainMenu.xibにステータスバー項目をクリックしたときに表示されるメニューを追加する。

ウィンドウオブジェクトの削除

 MainMenu.xibを開く。XIBファイルにはウィンドウオブジェクトがトップレヴェルに存在しており、アプリケーション起動時にそのウィンドウが自動的に開かれてしまう。今回はウィンドウは必要ないのでこのオブジェクトは削除しておく。ウィンドウオブジェクトを削除したらAppDelegate.hを開き、

@property (assign) IBOutlet NSWindow *window;

の行を削除する。

 後々、環境設定ウィンドウ等を作成するのであれば、このウィンドウオブジェクトをとっておいて流用してもよい。その場合は起動時にウィンドウが開かないように、

  1. ウィンドウオブジェクトを選択する
  2. UtilitiesエリアのAttributes Inspectorペインを選択する
  3. BehaviorのVisible At Launchチェックボックスをオフにする

としておく。

メニューの追加とアクション接続

 UtilitiesエリアのObject libraryペインからMenuを選択し、トップレヴェルに追加する。

 追加したメニューは三つのメニュー項目(Item1、Item2、Item3)を持っているので、そのうちのふたつを削除する。残ったひとつのタイトルをQuit StatusBarAppに変更する。Quit StatusBarAppメニュー項目からInterface Builder DockのApplicationまでControlキィを押しながらドラッグを行い、terminate:アクションと接続する。これでQuit StatusBarAppメニュー項目を選択したときにアプリケーションを終了できるようになる。

メニューのアウトレット接続

 追加したメニューをコードから参照できるようアウトレット接続を行う。

 前準備としてAppDelegateにクラスエクステンションを追加する。AppDelegate.mファイルを開き、@implementation AppDelegate行の前に以下の記述を追加する。

@interface AppDelegate ()

@end

 次に、XIBファイルを開いた状態でAssistant editorを表示し、そこにAppDelegate.mを開く。Interface Builder Dockから追加したメニューオブジェクトを選択し(XIBにはじめからあるMain Menuと間違えないように注意)、Controlキィを押しながらAppDelegate.mのクラスエクステンション内までドラッグする。そうするとダイアログがポップアップ表示されるので、

とし、Connectボタンをクリックする。

 アウトレット接続をヘッダファイルで行う場合は実装ファイルにクラスエクステンションを追加する必要はないが、ここではメニューを参照する変数は外部に公開する必要はないので、実装ファイルへ退避させた。

ステータス項目を表示する

 AppDelegate.mを開く。まずステータス項目を保持するインスタンス変数を宣言する。

@implementation AppDelegate
{
  NSStatusItem *_statusItem;
}

 次に以下のようなメソッドsetupStatusItemを定義する。

- (void)setupStatusItem
{
  NSStatusBar *systemStatusBar = [NSStatusBar systemStatusBar];
  _statusItem = [systemStatusBar statusItemWithLength:NSVariableStatusItemLength];
  [_statusItem setHighlightMode:YES];
  [_statusItem setTitle:@"StatusBarApp"];
  [_statusItem setImage:[NSImage imageNamed:@"StatusBarIconTemplate"]];
  [_statusItem setMenu:self.statusMenu];
}

 ここで行っていることを行ごとに説明すると、

  1. NSStatusBarsystemStatusBarクラスメソッドでステータスバーを取得する。

  2. NSStatusBarstatusItemWithLength:インスタンスメソッドでステータス項目を新しく生成し、_statusItemインスタンス変数に保持する。このメソッドの引数にCGFloatの数値を渡すと固定幅のステータス項目が生成されるが、たいていは項目の内容によって幅が可変になるNSVariableStatusItemLength定数を用いればよい。
    なお、このメソッドの返り値はretainされていないオブジェクトであり、オブジェクトが解放されると同時にステータスバーから項目も消えてしまう。したがって、ARC環境では強参照なインスタンス変数やプロパティで、非ARC環境ではretainしてからインスタンス変数に入れるかretainを指定したプロパティで保持しておく必要がある。

  3. setHighlightMode:YESを渡すことで、ステータス項目が選択されたときに、選択された状態が視覚化される(背景が青くなる)。通常はYESを渡しておく。

  4. setTitle:でステータス項目にタイトル文字列を指定する。タイトルが必要なければ不要だが、後述のアイコン等の内容物がないとステータス項目が見えない。

  5. setImage:でステータス項目にアイコン画像を指定する。画像ファイルはあらかじめプロジェクトに追加しておく。アイコンが必要なければ不要だが、前述のタイトル等の内容物がないとステータス項目が見えない。
    なお、上記のコードで画像のファイル名がTemplateで終わった形式になっているのは、その形式の画像ファイルからNSImageを生成すると自動的にテンプレート画像として扱ってくれるからである。テンプレートとして指定された画像をボタンやセグメンテッドコントールに指定すると、それらを選択したとき等にシステムが自動でイイ感じに画像を扱ってくれる(色の反転や非アクティヴ時のグレーアウト等。ただしテンプレート画像は黒と透明のみ)。今回のステータス項目のアイコン画像もテンプレート画像を指定しておくことで選択時にアイコンの色を反転してくれる。
    ファイル名がTemplateで終わっていない画像でも、NSImagesetTemplate:メソッドを使うことでテンプレート画像として扱うことができる。

  6. setMenu:で前項でアウトレット接続したメニューを指定する。これでステータス項目を選択したときにメニューが表示されるようになる。

 最後にapplicationDidFinishLaunching:内でいま実装したsetupStatusItemメソッドを呼び出す。

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
  [self setupStatusItem];
}

 applicationDidFinishLaunching:はアプリケーションの起動が終了した時点で呼ばれるので、そのタイミングでステータスバーにステータス項目が表示されるようになる。

ビルドして実行

 プロジェクトをビルド、アプリケーションを実行すると、ステータスバーにアイコンとタイトルテキストが配置され、それを選択するとメニューが表示されることを確認する。ウィンドウやDockアイコンは表示されないこと、ステータス項目が選択されたときにタイトルやアイコンの色が反転されること、Quit StatusBarAppメニュー項目を選択するとアプリケーションが終了することも確認する。

 以上により、ステータスバーアプリケーションの基本的な実装が完了した。実際に何かの仕事をさせる場合は、タイマ等を使って定期的に処理をしたり、何らかのイヴェントをフックしたりする必要がある。