2009年5月30日土曜日

mac: Mail.app は VACUUM と REINDEX で速くなるらしい

Mail.app 2年ほど使ってたけど、どうにも遅くなってしまって、Thunderbird に乗り換えたのがつい先日。 キーバインドにどうしても慣れないけど、まあサクサク動くからいいやと思って使ってたけど、 そういやデータベースは sqlite 使ってるはずだから VACUUM とかで速くなるんじゃ? と思ったらやっぱり速くなるようだ。 http://blog.clouder.jp/archives/001110.html http://journal.mycom.co.jp/column/osx/236/index.html 会社へ行ったら早速やってみよう。 -- 追記 うむ。速くなった。

whitespace: ユーザからの入力をスタックに積む

$wspace cat.ws hogehoge # ユーザの入力 hogehoge # echo
こうゆうことがしたかったけど、Tutorial を読んでもよく分からんかった。 ようやく分かった。 heap に一旦置いて、heap から stack に積んであげる必要があるのね。
0をstackにpush (読み込みデータを置くheapのアドレス) Read a character or a number 0をstackにpush (読み込みデータを置いたheapのアドレス) heap から retrieve
これで入力されたデータが stack の一番上に積まれた状態になる。 直接 stack に積まれるもんだと思い込んでたから、理解するのに時間がかかった。

2009年5月16日土曜日

blogger API: blog を ChangeLogメモ のように使う

http://0xcc.net/unimag/1/ で ChangeLogメモを知ってからずっとChangeLogメモを愛用してきたのですが、
  • メモを入力できる場所が一つに限られる
  • 画像データを入力できない
  • 公開できない. そしてあわよくばアフィリエイトとかしてみたい
あたりが物足りなくなってきたので、今更ながらblogを使ってみることにしました。 コマンドラインからさくっと入力できるのがChangeLogメモの利点なので、これをgdata API で作ってみます。 先にオチを言っておくと検索がAPIで公開されてないんですね。残念。
class Blogger:

    def __init__(self, email, password):
        # Authenticate using ClientLogin.
        self.service = service.GDataService(email, password)
        self.service.source = 'blogger.py-1.0'
        self.service.service = 'blogger'
        self.service.account_type = 'GOOGLE'
        self.service.server = 'www.blogger.com'
        self.service.ProgrammaticLogin()

        # Get the blog ID for the first blog.
        feed = self.service.Get('/feeds/default/blogs')
        self_link = feed.entry[0].GetSelfLink()
        if self_link:
            self.blog_id = self_link.href.split('/')[-1]

    def createPost(self, title, content, author_name, label, is_draft=False):
        # Create the entry to insert.
        entry = gdata.GDataEntry()
        entry.author.append(atom.Author(atom.Name(text=author_name)))
        entry.title = atom.Title(title_type='html', text=title)
        entry.content = atom.Content(content_type='html', text=content)
        if label:
            entry.category.append(atom.Category(term=label,
                scheme="http://www.blogger.com/atom/ns#"))
        if is_draft:
            control = atom.Control()
            control.draft = atom.Draft(text='yes')
            entry.control = control

        # Ask the service to insert the new entry.
        return self.service.Post(entry,
            '/feeds/' + self.blog_id + '/posts/default')
ほとんど blogger api に付属のサンプルコードそのままなんですが、これを次のように使います。
from gdata import service
import gdata
import atom
import os
import re
import sys
from ConfigParser import SafeConfigParser
from optparse import OptionParser
from tempfile import NamedTemporaryFile

PasswdFile = os.path.join(os.environ.get('HOME'), '.password')

def sub_url(text):
    pattern = r'''
    \b
    (
     (https?|ftp):[\w/#~:.?+=&%@!\-]+?
    )
    (?=
     [.:?\-]*
     (?:[^\w/#~:.?+=&%@!\-] | $)
    )'''

    regex = re.compile(pattern, re.IGNORECASE|re.VERBOSE)
    result = regex.sub(r'\1', text)

    return result

def createBlogData():
    # edit temp blog data file 
    temp_file = NamedTemporaryFile(suffix='.txt', prefix='blogger_py')
    editor = os.environ.get('EDITOR')
    if editor == '':
        editor = 'vi' # XXX: default
    stat = os.spawnlp(os.P_WAIT, editor, editor, temp_file.name)
    if stat != 0:
        raise EditError, 'edit tempfile failed: %s %s' % (editor, temp_file.name)

    # read blog data from temp file, publish a public post.
    title = temp_file.readline().rstrip('\r\n')
    label = temp_file.readline().strip()
    if label == '':
        _title = title.split(':') # title == 'LABEL: string'
        if len(_title) >= 2:
            label = _title[0]
    content = temp_file.read()
    author_name = "zakkie3"

    content = sub_url(content)
    title = title.decode('euc-jp')
    content = content.decode('euc-jp')

    temp_file.close()  # temp_file will delete automatically

    return title, content, author_name, label

def main():
    email = ''
    password = ''
    author = ''

    # parse passord file
    cParser = SafeConfigParser()
    is_exists = cParser.read(PasswdFile)
    if is_exists and cParser.has_section('blogger.py'):
        if cParser.has_option('blogger.py', 'email'):
            email = cParser.get('blogger.py', 'email')
        if cParser.has_option('blogger.py', 'password'):
            password = cParser.get('blogger.py', 'password')
        if cParser.has_option('blogger.py', 'author'):
            author = cParser.get('blogger.py', 'author')

    # parse command-line options
    oParser = OptionParser()
    oParser.add_option("-e", "--email", dest="email", help="E-mail address");
    oParser.add_option("-p", "--password", dest="password",
        help="E-mail address");
    oParser.add_option("-u", "--author", dest="author",
        help="Blog author");
    oParser.set_description('follow options can be set by ~/.password.')

    option, args = oParser.parse_args()
    if option.email: email = option.email
    if option.password: password = option.password
    if option.author: author = option.author

    if email == '' or password == '' or author == '':
        oParser.print_help()
        sys.exit(2)

    blogger = Blogger(email, password)
    title, content, label = createBlogData()
    blogger.createPost(title, content, author, label)
~/.password に blogger のアカウント情報を以下のように書いておきます。
[blogger.py] email: EMAIL@example.com password: PASSWORD author: zakkie3
やっていることは
  • EDITORを起動し、temporary file を編集
  • temporary fileの1行目をtitle
  • 2行目をlabel, なければtitleの':'の前をlabel
  • 3行目移行を本文
  • 本文のうち、URLっぽい文字列はリンクにする
  • EUC-JP固定
もっとかっこいいやり方があるんだろうけど、自分用なのでこれで十分。

2009年5月12日火曜日

blogger: blogger api からラベルも設定

blogger api でラベルを設定する際にハマったのでメモメモ。
label = "hoge"
entry = gdata.GDataEntry()
entry.author.append(atom.Author(atom.Name(text=author_name)))
entry.title = atom.Title(title_type='html', text=title)
entry.content = atom.Content(content_type='html', text=content)
if label:
    entry.category.append(atom.Category(term=label,
        scheme="http://www.blogger.com/atom/ns#"))

2009年5月10日日曜日

mac: mac book で右クリック

Mac OS X では Ctrl-クリックで右クリック相当になるけど、 X11 では Ctrl-クリックが左クリックと判定されてしまう。 これ、MacBook で tgif 使ってハマりました。 トラックパッドの設定で2本指タップを右クリックにできて、これで回避できます。 いやーハマった。

2009年5月6日水曜日

cocoa: book review

最近これ読んでます。 和訳はないのですが、平易な英語で苦になりません。 asin:0321503619
Cocoa Programming for Mac OS X
単なる How-to の寄せ集めではなく、例えば Core Data がどのような要素から実現されているのか、といった背景の説明もあるので応用の幅も広がりそうです。 序文に曰く、"this book is just the resource you need. (snip) it does cover probably 80% of what you need to know." とのことで、実際なんかしらのアプリを作れそうな気になります。 Cocoa の入門書的な位置付けのようですが、"This book is written for programmers whi alredy know some C programming and something about objects" の言葉の通り、C とオブジェクト指向言語を知らないとチンブンカンブンだと思います。 -- 追記 errata 情報: http://www.bignerdranch.com/products.shtml

cocoa: NSBox で枠を表示しない

Attributes inspector で Display - transparent を ON にする。 巷の NSBox を使ってそうな、画面変更のあるアプリケーションでは枠とか当然のようになくて、どうやって実現しているんだろうって不思議だった。

2009年5月4日月曜日

diary: The GARDEN Oriental KYOTO

僕たちが結婚式を挙げた場所。 スタッフのみなさんの人柄もよく、建物や庭園の雰囲気も素敵です。 レストランもやっていて、ウエディング以外でも利用可能。 僕たちもまた行こう。 http://www.thegardenorientalkyoto.com/