Fork me on GitHub

2011/10/17


このエントリーをはてなブックマークに追加
以前、「jekyllで始める簡単ブログ」という記事を書いたのですが
Big Sky :: Jekyllで始める簡単ブログ

GithubのユーザページでJekyllが使われる様になりました。 GitHub Pages Upgraded to Jekyll 0.5.0 - GitHub I just released Jek...

http://mattn.kaoriya.net/software/lang/ruby/20090409185248.htm
octopressというのを使うともっと簡単に出来る事が分かった。
Octopress

Octopress is a framework designed by Brandon Mathis for Jekyll , the blog aware static site generato...

http://octopress.org
imathis/octopress - GitHub

What is Octopress? Octopress is Jekyll blogging at its finest. Octopress sports a clean responsive t...

https://github.com/imathis/octopress
以下簡単な手順を示す。
このgithubリポジトリは基本的に、1ブログに対して1つcloneする。cloneしたら
# rake install
する。octopressをシステムにインストールのではなく、このブログ用リポジトリにsassテーマをキャッシュさせる為の設定を行うだけなので安心してやって貰ってok。
次にgithubにブログを作るのであれば
# rake setup_github_pages
を実行し、読み取り書き込み権限のあるgit URLを貼り付けて完了。
Windowsの場合はちょっとここで修正が必要で、config.rbとかRakefileに変なパスが書かれているので直す。実際にはpublic/c:/path/to/public...みたいなフルパスが重なっているはずなのでpublic...に直せばok。
これについては時間があったらパッチ書いてpull requestを送るつもり。

さて、これでブログを書く準備が出来ました。簡単すぎますね!

試しにsource/_posts/2011-10-17-github-jekyll.mkdというmarkdownのファイルを作ります。中身は以前ご紹介した内容と変わりませんが、ocotopressは幾らか拡張プラグインが入っているので色んな書き方が出来ます。
例えばgist tagプラグインを使って
---
layout: post
title: "githubとjekyllとoctopressで作るブログ"
date: 2011-07-03 5:59
comments: true
categories:
---
便利すぎる...

{% gist 1292428 %}
こう書いて
# rake gen_deploy
すると
githubとjekyllとoctopressで作るブログ - ギッハブる日記

Recent Posts githubとjekyllとoctopressで作るブログ Github Repos Status updating... @mattn on Github Latest T...

http://mattn.github.com/blog/blog/2011/07/03/github-jekyll/
こんな記事が出来上がります。dateはファイル名じゃなくてdateの方が(設定されていれば)優先されるみたいですね。以後は記事を書いてrake den_deployするだけの簡単なお仕事です。
他にも、imageタグや、haml形式入力、html5 videoタグなど、色んなプラグインがあります。また、sassフォルダ内にあるsassファイルを弄れば簡単しかも柔軟なCSSを吐き出せます。
なお、_config.xmlを弄ってタイトルやサブタイトル、githubアカウント、twitterアカウントなんかを設定すると上述の様なサイトが簡単に出来上がります。
# ----------------------- #
#      Main Configs       #
# ----------------------- #

url: http://mattn.github.com/blog
title: "ギッハブる日記"
subtitle: ギッハブで作る開発日誌
author: mattn

気をつけておいて欲しいのは、github/jekyllはCGIで動いている訳じゃなくて、octopressが静的コンテンツを生成しているので、記事をアップする環境に依存する事。まぁここはbundleを使っているのでOSさえ変わらなければ大丈夫かと思います。Windowsからでも既述の様な修正を入れれば使えています。無料のgithubで簡単にしかもモダンなブログサイトを作りたい方は、一考してみてはどうでしょうか。
Posted at 21:01 in ソフトウェア::lang::ruby
Tagged as: github, jekyll, octopress
Bookmarks: add to hatena add to hatena | add to delicious.com | add to livedoor.clip add to livedoor.clip

2011/07/28


このエントリーをはてなブックマークに追加
最近earthquakeという、rubyで書かれていて端末上で動作するtwitterクライアントをWindowsで動かそうと色々弄ってます。作者のjugyoさんにコミットビットも貰ってwork-on-windowsブランチで作業してます。earthquake側の修正はだいたいイケてるはずなんですが、問題はreadlineという行編集ライブラリで問題が発生。
ちゃんと書くと、C言語で書かれたreadlineをwrapしているreadlineモジュールじゃなくて、rubyinstallerに標準添付されたPure RubyScriptなモジュール。中身はUNIXのコードとWindowsのコードが入り乱れていて、rbreadline.rbなんか8686行もある大作。

まぁPure RubyScriptでCの真似事をしようってんだからこうなるよね...って感じ。
ただバイト長とキャラクタ数と、文字幅の扱いが間違ってて、Windows-31JなDBCSなんかではちゃんと動かない。パッチ書いて「問題があるんだよ。気付いて!」ってつもりでpull request送ったらいきなりIssue trackerでcloseされてカチンと来たので「その態度はいかがなもんかと思う」的なコメントをした。そしたら「まずテストを書け」との事だったので書いた。

しかしながら、上記の間違いを直すとしてreadlineの正しい動きをテストするって難しい。関数単体なら出来るけどUIのテストはどの言語でも苦しむ。おまけにreadlineはreadline()メソッドを呼び出してる最中は、テスターが止まってしまう。終えるにはユーザの入力が必要。
じゃぁユーザの入力を横取りしてやんよ!って事で、rl_get_char()をぶんどる事にした。
module RbReadline
  #...

  alias :old_rl_get_char :rl_get_char
  def rl_get_char(*a)
    c = old_rl_get_char(*a)
    c.force_encoding("ASCII-8BIT"if c
    @last_xy = xy
    return (c || EOF)
  end

  def rl_get_char=(val)
    for c in val.reverse
      _rl_unget_char(c)
    end
  end

  module_function :old_rl_get_char:rl_get_char:"rl_get_char="
end
こんな感じにRbReadline.rl_get_char()をMix-inで上書きしてやる。こうすれば、外からキー入力を差し替えられる。
RbReadline.rl_get_char = [""""""""""]
buf = Readline.readline("")
これさえ出来れば、文字入力させて最後のカーソル位置が正しい位置にいる事を確認出来る。カーソルの位置はGetConsoleScreenBufferInfo()で得られるのでWin32API使ってゴリゴリ取った。また、最終的な入力結果が文字化けしていない事を確認する為にReadConsoleOutputCharacter()も使った。
全体のコードは以下の様になった。
# encoding: CP932
require 'test/unit'
require 'rb-readline'
require 'Win32API'

module RbReadline
  @GetStdHandle = Win32API.new("kernel32","GetStdHandle",['L'],'L')
  @hConsoleHandle = @GetStdHandle.Call(STD_OUTPUT_HANDLE)
  @GetConsoleScreenBufferInfo = Win32API.new("kernel32","GetConsoleScreenBufferInfo",['L','P'],'L')
  @ReadConsoleOutputCharacter = Win32API.new("kernel32","ReadConsoleOutputCharacter",['L','P','L','L','P'],'I')

  alias :old_rl_get_char :rl_get_char
  def rl_get_char(*a)
    c = old_rl_get_char(*a)
    c.force_encoding("ASCII-8BIT"if c
    @last_xy = xy
    return (c || EOF)
  end

  def rl_get_char=(val)
    for c in val.reverse
      _rl_unget_char(c)
    end
  end

  def last_xy
    @last_xy
  end

  def last_xy=(val)
    @last_xy = val
  end

  def xy
    csbi = 0.chr * 24
    @GetConsoleScreenBufferInfo.Call(@hConsoleHandle,csbi)
    [csbi[4,2].unpack('s*').first, csbi[6,4].unpack('s*').first]
  end

  def get_line(l)
    line = 0.chr * 80
    length = 80
    coord = l << 16
    num_read = ' ' * 4
    @ReadConsoleOutputCharacter.Call(@hConsoleHandle,line,length,coord,num_read)
    line.force_encoding("Windows-31J")
  end

  module_function :old_rl_get_char:rl_get_char:"rl_get_char="
end

class TestReadline < Test::Unit::TestCase

  def setup
    Readline::HISTORY << "世界".force_encoding("ISO-8859-1")
    Readline::HISTORY << "abc".force_encoding("ISO-8859-1")
    Readline::HISTORY << "bcdef".force_encoding("ISO-8859-1")
    RbReadline.rl_get_char = []
    RbReadline.last_xy = RbReadline.xy
    puts
  end

  def test_cursor_position_normal
    a = RbReadline.xy
    buf = Readline.readline("")
    b = RbReadline.last_xy
    assert_equal 2, b[0] - a[0]
    assert_equal 0, b[1] - a[1]
  end

  def test_cursor_position_mix
    a = RbReadline.xy
    buf = Readline.readline("$$$")
    b = RbReadline.last_xy
    assert_equal 5, b[0] - a[0]
    assert_equal 0, b[1] - a[1]
  end

  def test_cursor_position_insert_single_width
    a = RbReadline.xy
    RbReadline.rl_get_char = ["a""b""c""d""e"]
    buf = Readline.readline("")
    b = RbReadline.last_xy
    assert_equal 7, b[0] - a[0]
    assert_equal 0, b[1] - a[1]
  end

  def test_cursor_position_insert_double_width
    a = RbReadline.xy
    RbReadline.rl_get_char = [""""""""""]
    buf = Readline.readline("")
    b = RbReadline.last_xy
    assert_equal 12, b[0] - a[0]
    assert_equal 0, b[1] - a[1]
  end

  def test_cursor_position_previous_history
    a = RbReadline.xy
    RbReadline.rl_get_char = ["a""\340H""\340H"]
    buf = Readline.readline("")
    b = RbReadline.last_xy
    assert_equal 5, b[0] - a[0]
    assert_equal 0, b[1] - a[1]
  end

  def test_cursor_position_next_history
    a = RbReadline.xy
    RbReadline.rl_get_char = ["a""\340H""\340H""\340P"]
    buf = Readline.readline("")
    b = RbReadline.last_xy
    assert_equal 7, b[0] - a[0]
    assert_equal 0, b[1] - a[1]
  end

  def test_cursor_position_history_include_multibyte
    a = RbReadline.xy
    RbReadline.rl_get_char = ["a""\340H""\340H""\340H"]
    buf = Readline.readline("")
    b = RbReadline.last_xy
    assert_equal 6, b[0] - a[0]
    assert_equal 0, b[1] - a[1]
  end

  def test_cursor_position_insert_into
    a = RbReadline.xy
    RbReadline.rl_get_char = ["""""""\340K""\340K""a"]
    buf = Readline.readline("")
    b = RbReadline.last_xy
    assert_equal 5, b[0] - a[0]
    assert_equal 0, b[1] - a[1]
    assert_equal "$あaいう"RbReadline.get_line(b[1])
  end
end
僕がpull requestしたpatchもtest_cursor_position_insert_intoはNG出るのでこれを直していこうと思う。
Posted at 02:42 in ソフトウェア::lang::ruby
Tagged as: rb-readline, readline, ruby
Bookmarks: add to hatena add to hatena | add to delicious.com | add to livedoor.clip add to livedoor.clip

2009/06/18


このエントリーをはてなブックマークに追加
require "rubygems"
require "dl/import"
module Lib_MSVCRT extend DL::Importable
  LC_CTYPE = 2
  dlload "msvcrt.dll"
  extern "char* setlocale(int, char*)"
end
Lib_MSVCRT::setlocale(Lib_MSVCRT::LC_CTYPE, "")
Posted at 15:08 in ソフトウェア::lang::ruby
Tagged as: ruby
Bookmarks: add to hatena add to hatena | add to delicious.com | add to livedoor.clip add to livedoor.clip

2009/06/17


このエントリーをはてなブックマークに追加
使っているreadline.dllはここから持って来ているんだけど、まずこれがマルチバイトありでビルドされていない。なのでマルチバイト文字を入力した後、バックスペース押すと1バイト単位でしか戻らない。
今日はそれを解決してみる。readline-4.3-2-src.zipを持ってきて
# unzip readline-4.3-2-src.zip
# cd readline-4.3-2¥win32¥shlib
# copy config.h config.h.orig
# vim config.h
diff -u config.h.orig config.h
--- config.h.orig   2003-04-14 16:04:46.000000000 +0900
+++ config.h    2009-06-17 17:04:07.234375000 +0900
@@ -128,11 +128,9 @@
 /* Define if you have the <varargs.h> header file.  */
 //#define HAVE_VARARGS_H 1
 
-/*
 #define HAVE_WCTYPE_H 1
 #define HAVE_WCHAR_H 1
 #define HAVE_MBSRTOWCS 1
-*/
 /* config.h.bot */
 /* modify settings or make new ones based on what autoconf tells us. */
 
# copy config.h ..
# mingw32-make -f GNUmakefile
とするとreadline.dllが出来上がるのでそれをパスの通った場所に置く。古いreadline.dllをバックアップしておいて入れ替えるのもOK。
次に、id:Constellationさんの記事にある以下のソースをlocale.cとして保存する。
#include <locale.h>
#include "ruby.h"

static VALUE mLocale;

static VALUE
locale_setlocale(obj)
{
  setlocale(LC_CTYPE, "");
#ifdef LC_MESSAGES
  setlocale(LC_MESSAGES, "");
#endif
  return Qnil;
}

void
Init_locale()
{
  mLocale = rb_define_module("Locale");
  rb_define_module_function(mLocale, "setlocale", locale_setlocale, 0);
}
そしてコンパイル
# gcc -Ic:/ruby/lib/ruby/1.8/i386-mswin32 -shared -o locale.so locale.c libreadline.a c:/ruby/lib/msvcrt-ruby18.lib
ワーニングが出るけど気にしない
出来上がったlocale.soを
C:¥ruby¥lib¥ruby¥1.8¥locale.so
として配置し、ホームディレクトリ(HOME環境変数を設定していないならばUSERPROFILE変数の位置)に".irbrc"というファイルを作って以下の様に書く。
begin
  require"locale"
  Locale.setlocale
rescue
end
require 'rubygems'
require 'utility_belt'
require 'win32console'
"utility_belt"はこの記事を、win32consoleはエスケープシーケンスを色付けして表示して貰うために...
後はirbを起動すれば、マルチバイト文字でバックスペースしても正しく1文字消えてくれます。

Constellation++

これでようやく、termtterでも正しく日本語が打てる。
なお、Constellationさんの記事にも書かれていますがtime.rb周りで弊害が出る可能性があるので、気を付けて。termtterの場合なら"~/termtter/config"にLocale.setlocaleを書いた方が良いかもしれない。
Posted at 17:20 in ソフトウェア::lang::ruby
Tagged as: ruby, windows
Bookmarks: add to hatena add to hatena | add to delicious.com | add to livedoor.clip add to livedoor.clip