No Programming, No Life

プログラミング関連の話題や雑記

GitHub Pagesを作成してみた

前からやりたいなと思っていたGitHub Pagesを作成しました。

http://fumokmm.github.io/


こちらの記事を参考にさせていただきながら作成しました。
(余談ですが、この記事のころはドメインが "http://username.github.com/" だったようですが、2014-05-03現在では "http://username.github.io/" になったようですね)

まだなにもありませんが、どうやって使っていこうか考え中です。
SphinxとかJekellとかを使ってみるいい機会かなとも思っています。

中括弧省略問題

例えばif文で、

「処理する行が1行のみであった際は、中括弧を省略できる」

if (条件) 処理;

と、みなさんは最初習ったのではないだろうか。
しかしどうだろう、次のようにも考えられないだろうか。

「条件式のあとは式が一つのみ指定できます。
もし複数指定したい場合は、中括弧で複数の処理を囲むことで指定可能です」

if (条件) {
  処理1;
  処理2;
}

こちらの方が、中括弧は複数の処理をまとめるためのものという本質を捉えているように思える。

しかし、よく目にするコーディングルールには「常に中括弧を付けよ!」みたいなものがあるほどだ。
曲解、理解の逆転もいいところだが、これも、「範囲をミスしにくくする」という現実的な解であるととらえれば頷ける。*1

現実にはいつも設計者の意図を超えた使われ方をするものだ。

もし、しっくりこない説明に出くわしたとして理解できないような概念があったとして、それがスタンダードな考え方だったとしても、どうか落ち込まないで欲しい。
それは今回の中括弧省略問題のようなスタンダードな曲解かもしれない。だから、さまざまな視点から観察し、本質を捉えられるようになるベキだと、わたしは思う。

*1:後者の説明を推奨するならば、学習者はデフォルトで中括弧を使わなくなるだろう。もしかするとこのコーディングルールの設計者はそれを回避するためにあえてそうしているのかもしれない。

システム維持・保守は歯科医の業務に似ているという話

最近、歯の治療のため、歯科医に通っていた、ふもです。
治療中にふと思ったので書き留めておこうと思います。

お客さん=ユーザーさん

歯=運用中のシステム

歯茎の腫れ=エラーや警告

悪い歯並び=スパゲッティコード

歯の矯正=リファクタリング

虫歯=バグ

親知らず=仕様バグ

被せ物が取れた=修正ミス・デグレード

  • 当時治療した歯医と違う歯医にかかるとか、システム開発でいうところの、別会社への修正依頼と一緒

差し歯・入れ歯=一部の機能を作り直し(一からコードを書く)

総入れ歯=新システム構築

虫歯治療=バグ改修

治療後の一週間=初動確認

麻酔=システム停止時間

歯のクリーニング=リファクタリング

歯磨き=ログ監視・データパッチ

治療の際、お客さんの歯を傷つけない=改修の際、運用中のシステムを壊さない

簡単には入れ歯にできない、段階を踏んだ治療を行う=バグ改修で済むならそれを行い、手も足も出ない状況になったら総書き換え

歯以外の部分を傷つけない(唇とか舌とか)=他の外部システムとのインタフェースを壊さない

はーい、口を大きく開いて下さ〜い=要件定義・ヒアリング・影響範囲の見極め

レントゲン写真撮影=システムの解析・影響範囲の見極め

はーい、うがいして下さ〜い=ユーザーテスト

いかがでしょうか?
あなたがシステム維持・保守担当者さんなら、歯医者さんになった気持ちでシステムに向き合ってみると面白いかもしれません。
あなたがシステム開発者なら、なるべく治療せずとも、長く使っていけるシステムを仕上げるよう心がけて下さると助かります。

レッツ80・20!

MacのGoogle日本語入力でバックスラッシュ(\)を入力する方法

「環境設定 -> 一般 -> ¥キーで入力する文字」
で指定可能でした。

真ん中あたりの「¥キーで入力する文字」をクリックして

「バックスラッシュ(\)」に変更

これで、\がさくさく入力できるようになります。

GroovyでMarkdownパーサーを作ろう #4「Headers(見出し)の実装」その2

このシリーズの一覧


Groovy! (挨拶)

どうも、ふも(@)です。

はじめに

さてそれでは、前回の続きで、Headers(見出し)の具体的な実装に入って行きたいと思います。

一行ずつ処理する

前回までは、ファイルから読み取った内容を一気にHTMLのBODYタグに埋め込んでいましたが、
今回実装しようとしているAtx形式のヘッダーは行単位で処理してゆくのが適していそうです。
そこでまず、ファイルから一行一行取り出して処理するように変更したとして、
その一行一行に対する処理を考えてみましょう。
ということでまず、fumomarkdowngの冒頭部分を以下のように変更します。

// 第一引数の内容を読み込む
def lines = new File(args[0]).readLines()

// Markdown形式をHTMLに変換
def md = new Markdown()
def contents = lines.collect {
  md.headerAtx(it)
}.join('\n')

マークダウン形式のファイルを読み込んで一行ずつのリストにして(#readLines)、変数linesに格納します。
次に、Markdownクラスを作成*1して、読み込んだ各行について、Markdown#headerAtxを呼び出し変換処理を行う。
変換した結果は、改行文字で#joinして、contentsの出来上がりという流れ。
これで、外枠の読み込み部分はできましたので、次は変換処理のメインに行きましょう。

Markdownクラスの作成

今後、色々な変換処理を実装することになりそうなので、Markdownというクラスを作成することにしました。
今回はとりあえずAtx形式変換するメソッド #headerAtx を実装することにしましょう。

Groovyではクラス定義の仕方はJavaと同じです。

class Markdown {
   // ...
}

メソッド定義もJavaと同じです。さらにGroovyでは引数を省略してdefキーワードも使えるのですが、今回は明示的にStringにしておきましょうか。
引数はString mdで、ファイルから読み取った1行の文字列が来る想定です。

class Markdown {
  /** 見出し:Atx形式 */
  String headerAtx(String md) {
    // ...
  }
}

行の先頭をまず確認します。具体的には "#" で始まっているかどうか?を確認する必要がありますね。

次に、#headerAtxの中身です。まずは、'#'の数を数えておきましょう。

def sharpSize = md.find(/^#+/).size()

#の数は1〜6の範囲です。それ以上でも以下でもないです。
"#" が所定の数で始まっているなら、次のステップへ移行します。

'#'の数が1〜6なら所定の処理を行う部分は、Groovyならin演算子を使って以下のように書けますね。

if (sharpSize in 1..6) {
  // ...
} else {
  return md 
}

"#" が所定の数で始まっていなかったり(例えば7個とかね) そもそも "#" で始まっていなかったりした場合はそのままその行は終了。

'#'の数が範囲外なら、何もせずにそのままreturn mdします。

さて、範囲内だった場合、いよいよ変換処理なわけですが、'#'の数がそのままHタグの数値部分になるのですが、
'#'の数はすでにわかっているので、

その行の先頭と末尾の連続する "#" を取り除きます。

def contents = md.replaceAll(/^#+\s*|\s*#+$/, '').trim()

もしくは、同じことが以下のようにも書けます。

def contents = md.replaceAll(/(?x) # enable whitespace and comments
  ^\#+   # 先頭からはじまるシャープ
  |      #   または
  \#+$   # 最後のシャープ
/, '').trim()

(?x)はGroovyの正規表現拡張で、Groovyの正規表現リテラルのようなもの*2の中で、改行を入れたり # でコメントを入れたりして見やすく正規表現が書けるようにするものです。
(ただ、今回は '#' 自体をどうにかしたい関係で、 ¥# のようにエスケープが必要になってしまい、あまり見やすいとは言えないのですが。)
上記のどちらでもやりたいことは一緒で、先頭と末尾の連続する '#' を削除したあと、trimしています。

最後に "#" を取り除いた結果をトリムして、Hタグでくるんであげれば変換完了です。

ということで、変換結果はcontentsに入っているはずなので、以下のようにして変換完了です。

def tags = [  "<h${sharpSize}>",
             "</h${sharpSize}>" ]
return "${tags.first()}${contents}${tags.last()}"

おわりに

少し急ぎすぎた感じもありますが、これで期待どおりの結果が得られます。

今回使用したソースはこちら

前の記事:GroovyでMarkdownパーサーを作ろう #3「Headers(見出し)の実装」 - No Programming, No Life

*1:この後すぐ示します。

*2:/ ではじまり / で終わる文字列。

GroovyでMarkdownパーサーを作ろう #3「Headers(見出し)の実装」その1

このシリーズの一覧


Groovy! (挨拶)

どうも、ふも(@)です。

はじめに

さて、今回から具体的な変換処理の実装に入っていくわけですが、いざ実際にコードを書いていこうとすると色々と下準備が必要になってきそうです。ゆっくりやっていきたいと思います。
さしあたって、今回から数回に分けて、Header(見出し)の実装に取り掛かりましょう。

見出し(見出し)記法の確認

Headers - 見出し
MarkdownはSetextとatxという、二つの形式をサポートしています。

blog::2310 » Markdown文法の全訳

ということで、見出しの実装でも二種類あるようですね、今回はひとまず簡単な方のatxという方を実装して行きたいと思います。

Atx形式

Atx形式は見出しの行頭に1つから6つまでの#(ハッシュ記号)を用いる方法です。#(ハッシュ記号)の数が見出しレベルと一致します。例えば

# This is an H1
## This is an H2
###### This is an H6

Markdown独自の機能として、atx形式を「閉じる」ことができます。 この表現が好みであれば使うことができますが、単純に見栄えの問題です。 行末の#(ハッシュ記号)の数は行頭と一致する必要もありません。

# This is an H1 #
## This is an H2 ##
### This is an H3 ######
blog::2310 » Markdown文法の全訳

要約すると

  • 行頭を "#" 1つ〜6つで始めると、それは見出しとなる
  • 例えば、"# abc" なら、 <h1>abc</h1> のようになる
  • 見映えのため、行末には好きなだけ "#" を並べられる(そしてそれらは変換結果としては無視される)

という感じでしょうか。

ロジックを考えてみる

  1. 一行ずつ処理する
    1. 前回までは、ファイルから読み取った内容を一気にHTMLのBODYタグに埋め込んでいましたが、今回実装しようとしているAtx形式のヘッダーは行単位で処理してゆくのが適していそうです。そこでまず、ファイルから一行一行取り出して処理するように変更したとして、その一行一行に対する処理を考えてみましょう。
  2. 一行に対する処理
    1. 行の先頭をまず確認します。具体的には "#" で始まっているかどうか?を確認する必要がありますね。そして#の数は1〜6の範囲です。それ以上でも以下でもないです。
    2. "#" が所定の数で始まっているなら、次のステップへ移行します。まず#の数を数えておきます(1〜6のいずれかになるはずですね)。あとでHタグ数値部分として使うためです。次はその行の先頭と末尾の連続する "#" を取り除きます。最後に "#" を取り除いた結果をトリムして、Hタグでくるんであげれば変換完了です。
    3. "#" が所定の数で始まっていなかったり(例えば7個とかね) そもそも "#" で始まっていなかったりした場合はそのままその行は終了。*1

という流れで良さそうですね。

おわりに

ちょっと長くなりそうなので、実際のソースは次回に引き継ぎます。
それではまた。

次の記事:GroovyでMarkdownパーサーを作ろう #3「Headers(見出し)の実装」その2 - No Programming, No Life
前の記事:GroovyでMarkdownパーサーを作ろう #2「HTML出力部分の作成」 - No Programming, No Life

*1:7個以上の場合は、6個までは見出し<H6>として処理してあげた方がいいのかな?

GroovyでMarkdownパーサーを作ろう #2「HTML出力部分の作成」

このシリーズの一覧


Groovy! (挨拶)

どうも、ふも(@)です。

はじめに

さて、それでは早速コードを書いて行きたいと思います。といってもまだ、Markdownの変換ロジックには入りません。
今回は設定ファイルを読み込んで、その内容をプレーンなHTMLにそのまま埋め込んで出力させるというところまで作って行きたいと思います。

作成するスクリプト

スクリプト名は前回決めた通り、fumomarkdowngにしようと思うので、

fumomarkdowng.groovy

になります。
そして、マークダウン形式で内容が書かれたファイルは、

hoge.md

にしてみましょう。

外部ファイルの内容読み込み

何はともあれ、hoge.mdの内容をまず読み取るところから。
Groovyでは、外部ファイルの読み込みはFile#text*1を利用して行えます。

new File('path to file').text

コマンドライン引数はargsという暗黙変数にString[]型として格納されます。第一引数の文字列の取得は

args[0]

のようにします。ということで、外部ファイルの内容を文字列で取得し、contentsという名前の変数に格納しておくことにします。

// 第一引数の内容を読み込む
def contents = new File(args[0]).text

HTMLを出力

で、次はHTMLの出力部分。ひとまず標準出力への出力でいいかな、ファイルへ出力する場合はリダイレクトすればいいし。
Groovyでは標準出力への出力はprintprintlnprintfを使います。
複数行の文字列は ''' か """ で囲みます*2*3。今回は変数展開を使いたいので、""" の方を使いましょう。

// 読み込んだ内容をHTMLのテンプレートに流し込む
println """<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>fumomarkdowng</title>
</head>
<body>
${contents}
</body>
</html>"""

まぁ、こんな感じでしょうか。タグの中身は${contents}なので、ひとまず読み込んだファイルの中身をそのまま入れ込む感じです。

実行してみる

$ groovy fumomarkdowng.groovy hoge.md
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>fumomarkdowng</title>
</head>
<body>
# level1
## level2
### level3
</body>
</html>
$

うまく行きました、予想通りです。
あ、ちなみに、hoge.mdの内容はお察しの通り

# level1
## level2
### level3

です。まだ本題であるMarkdownの変換処理を何も書いていないのでそのまま出力されているわけです。

おわりに

さて、次回からは変換ロジックを書いて行きたいと思います。まずは簡単な見出しあたりからかなぁ。ではまた!

今回使用したソースはこちら

次の記事:GroovyでMarkdownパーサーを作ろう #3「Headers(見出し)の実装」 - No Programming, No Life
前の記事:GroovyでMarkdownパーサーを作ろう #1「名前決め」 - No Programming, No Life

*1:#getTextの省略系

*2:他の言語だとヒアドキュメントとか呼ばれてるやつです。今回みたいにテンプレートとして使う場合に改行込みに出来るので便利です。

*3:Groovyでは複数行の文字列を扱う記法がまだあります。ドルスラッシュ文字列とか。詳しくは参考記事のv1.8の新機能あたりをご覧下さい