78 howm-mode.vim (2-42) howm-actionlock-isbn.vim の公開
howm-mode.vim 狙えパッチ適用版で、はてなダイアリーの isbn/asin 記法に対応するための設定スクリプト「howm-actionlock-isbn.vim」を公開しました。
ダウンロード: http://khkh.o0o0.jp/vim/howm-actionlock-isbn.vim
概要
howm-mode.vim 狙えパッチ適用版で、はてなダイアリーの isbn/asin 記法が使用できます。厳密には asin には対応していないので、isbn 記法 ( detail ) のみが使用できます。 isbn10 や isbn13 から、書籍の情報を取得できます。
= [2008-04-07 14:35] isbn:4861970016:detail
という風に isbn 記法を入力し、カーソルを上に置いてエンターキーを叩くと
= [2008-04-07 14:35] isbn:9784861970014:detail 坊ちゃん 作者: 夏目漱石 出版社/メーカー: フロンティアニセン 発売日: 2004/09/01 メディア: ? http://d.hatena.ne.jp/asin/4861970016
こんな感じで情報を取得できます。isbn 記法内のコードが isbn10 の場合は、自動で isbn13 に置き換えます。以前の sync-isbn.vim と同様のものと考えていただいて結構です。
必要環境
導入方法
ダウンロードした howm-actionlock-isbn.vim を、以下のように vimrc で source コマンドを使って読み込んでください。
" パスは適宜修正してください so ~/.vim/howm/howm-actionlock-isbn.vim
注意事項
isbn10 から isbn13 への変換はきっちりとしていますが、情報取得や isbn13 から asin への変換は「はてな頼み」です。
スクリプト解説とか
isbn の処理において、きちんとした手順を踏んでいることが大きな特徴です。
以前公開した sync-isbn.vim では、ひどい処理をしていました。大きな問題が二つあります。
一つ目の問題は isbn10 と asin を区別していないことです。 isbn13 を isbn10 に変換するつもりで、はてなダイアリーを使用していました。これは実際は asin に変換されています。今回のものは、isbn10 についてはすべて isbn13 に変換し、isbn13 から asin に変換する(情報を取得する)ために、はてなダイアリーを使用しています。今回は、きっちりと isbn10 と asin を区別しています。
二つ目の問題は isbn の妥当性をきちんと検証していないことです。 isbn10 / isbn13 にはチェックディジットがあります。これらの計算をしていませんでした。ですから、形式さえ同じであれば、isbn として通ってしまっていました。今回のものは、isbn10 / isbn13 ともに、形式だけでなくチェックディジットの計算を行っています。
今回のものでは、上記の二点以外に改善された点があります。それが「isbn10 から isbn13 への変換」です。先にすこし書いたとおり、今回のものは isbn10 を isbn13 に変換してしまいます。その過程でも、妥当性の確認を行い、より正確に変換しています。
繰り返しますが、isbn の処理がきちんとした手順を踏んでいます。ですから、isbn に関するコードに関しては、今回のものだけに限らず「流用できる」と考えています。
だらだらと書きすぎてしまいました。では、以下に実際のコードから、該当部分を抜粋しておきます。
function! s:get_isbn10_cdigit(isbn) if a:isbn !~# '\d\{9}' | return 0 | endif let sum = 0 for i in range(9) let n = substitute(a:isbn, '^\d\{' . i . '}\(\d\)\d*$', '\1', '') let sum = sum + n * (10 - i) endfor let cdigit = (11 - (sum % 11)) if cdigit == 10 let cdigit = 'X' elseif cdigit == 11 let cdigit = '0' else let cdigit = string(cdigit) endif return cdigit endfunction function! s:get_isbn13_cdigit(isbn) if a:isbn !~# '\d\{12}' | return 0 | endif let sum = 0 for i in range(12) let n = substitute(a:isbn, '^\d\{' . i . '}\(\d\)\d*$', '\1', '') let sum = sum + n * (i % 2 == 0 ? 1 : 3) endfor let cdigit = (10 - (sum % 10)) let cdigit = string(cdigit == 10 ? 0 : cdigit) return cdigit endfunction function! s:is_isbn10(s) if a:s !~# '^\d\{9}[0-9xX]$' | return 0 | endif let isbn10 = substitute(a:s, '^\(\d\{9}\)\([0-9xX]\)$', '\1', '') let cdigit = substitute(a:s, '^\(\d\{9}\)\([0-9xX]\)$', '\2', '') return (cdigit =~? s:get_isbn10_cdigit(isbn10)) endfunction function! s:is_isbn13(s) if a:s !~# '^\d\{13}$' | return 0 | endif let isbn13 = substitute(a:s, '^\(\d\{12}\)\(\d\)$', '\1', '') let cdigit = substitute(a:s, '^\(\d\{12}\)\(\d\)$', '\2', '') return (cdigit =~? s:get_isbn13_cdigit(isbn13)) endfunction function! s:isbn10to13(isbn10) if !s:is_isbn10(a:isbn10) | return '' | endif let isbn10 = substitute(a:isbn10, '^\(\d\{9}\)\([0-9xX]\)$', '\1', '') let isbn13 = '978' . isbn10 let cdigit = s:get_isbn13_cdigit(isbn13) let isbn13 = isbn13 . cdigit if !s:is_isbn13(isbn13) | return '' | endif return isbn13 endfunction
わーい、チェックディジット計算まちがえてた