Google Code Prettify

2019年12月22日

久しぶりの投稿

かなり期間が空いてしまったが、ブログを再開してみようと思う。

2013年3月が直前の投稿だったが、頻繁に更新していた時期が 2011年11月までなので、8年間ぶりとなる。

8年間なにをしていたのかと言えば、2回転職して未だにIT技術者の職を得ている。

その期間、ざっくりと扱ったプラットフォームと言語は以下

2011/11〜
  • Server Side Engineer
    • PHP(CakePHP, Laravel), Perl(mod_perl,Catalyst)
  • Infra engineer
    • AWS / On-premises
  • iOS / Android Engineer
    • Objective-C / Swift / Java
2016/8〜
  • Android Engineer
    • Java / Kotlin
  • Server Side Engineer
    • PHP(Phalcon, FuelPHP), Java/Kotlin(Spring Boot)
あと docker とか ansible 等々、必要に応じて使ってきた。

色々ノウハウを溜め込んだが仕事以外で出力していない。

良くあるアウトプット不全症なのだが、リハビリ変わりに書き出していこうと思う。

まずは、このブログの表示も 8年前の感じでなので、、、直していこう。

2013年3月16日

Cocoa Emacs 24.3 構築 (2013/03版)

暫く使っている Cocoa Emacs を更新していなかったので、24.3 に上げてみた。
当てるパッチは inline patch とポップアップフリーズ対応パッチくらい。
24.3 には既にフルスクリーン実装が入っているので、よく使われているフルスクリーンパッチは外した。
普通に安定してる。。。良い事。
但し、フルスクリーン時に、ツールバー表示をトグルすると上下に変な隙間が出て、変だ。
どうしたもんだかなぁ

2011年11月6日

Ant を使って Android アプリを構築する

Eclipse を使って Android アプリのプロジェクトを作成すると build.xml が作られずに、 コマンドラインからの構築ができない。 ただ、ちょっと前の ADT の話なので定かでない。。。
Eclipse を使うと署名済みの apk パッケージまで作れるが、 GUIを使って一連の操作を毎回するのは面倒なので、 ant を使ったリリース方法を調べてみた。

2011年6月5日

Cocoa Emacs 23 構築 (2011/06版)

定期的にCocoa Emacs 23 を構築して使っていた。今日も定期作業とおもって、構築したらビルドが失敗してしまった。。。
どうしたもんだかなぁ

2011年5月26日

MacOSX で Zen Touch 2 (Android2.2)を開発端末にしてみる

自分の携帯を Androidの開発端末として使うのは、日常生活でメールや連絡が来たりするときに結構困る場合がある。なので、3〜4インチ程度の安いAndroid 端末が無いかなと物色したら、Zen Touch 2 がよさげ。

、、、

静電式のものに慣れているので、感圧式タッチパネルが違和感ありまくり操作がし辛いこと。

実物を見ないで、購入したので自業自得だが、、、ついでに、Android Market 非対応のも、、、 余り Android 端末としてはお薦めできないなぁ。。。まぁ音楽プレーヤーですね。

今まで扱った Android 端末は、何もせずに MacOSX の Android 開発用の SDK で認識されたので、気に留めるなかったが、こいつは認識しない。。。

はて、どうしたもんだかなぁ

2011年5月7日

iOS の View Controller の lifecycle の図

iOS の VIewController のライフサイクル図を書き起こしてみた。

開発ドキュメントから読み取ったのだが、理解不足なためか不正確な部分も無きにしもあらず。精進せねば。

UIViewController のサイクル

まぁ、いらないと思うがPDF版 @ Google Docsもアップ。

2011年4月23日

Android の Activity のlifecycleの図

Android の基本の Activity のライフサイクルの図が開発サイトに乗ってる。

これでも前後の文章で補完すれば分かるんだが、2〜3ヶ月後の自分はまた忘れてる可能性大なので、 ちょこっと弄ってみた。

Android Activity 遷移図

まぁ、いらないと思うがPDF版 @ google docs もアップ。

2011年3月4日

Google提供の python ライブラリで Google Reader API を使ってみた

Google のサービスと連携するには Google Data API を使う。Googleが公式にサポートしているので、とても安心して使える。RSS リーダーとしてよく使われている Google Reader 用のAPI も。。。は、まだ公式には無い。

まぁ、色々な人が解析しており、GoogleReaderAPIのページが、詳細にまとまっている。

なので、Google 提供の python ライブラリで、Google Reader API を叩いてみた

ただ、サンプルを書いたあとで、pyrfeed内にGoogleReader 用のライブラリが含まれていたのに気付いたので、そっちを使うのがいいのかも。

インストール

MacPorts を使っているので、さくっとインストール。

% sudo port install py27-gdata

そうでないならば、gdata-python-clientから最新版をインストールする。

Google Reader 用の下準備と認証

gdata-python-client には、Reader サービスの固有の API は無いので、ベースのモノを適当に設定する必要がある。

import gdata.service

config = { 'Email': 'foobar@gmail.com', 'Passwd': 'password' }

# Google Reader サービス設定
service = gdata.service.GDataService(account_type='GOOGLE',
                                     service='reader',
                                     server='www.google.com',
                                     source='MyReaderHoge')

# Google アカウント設定とログイン
service.ClientLogin(config['Email'],config['Passwd'])

# 認証トークン(SIDの値)
print service.GetClientLoginToken()

# 書き込み用のトークンの取得
token = service.Get('/reader/api/0/token',converter=lambda x:x)
print "token:", token

'api/0'以下のレスポンスが AtomPub 形式では無く、小細工が必要である。gdata-python-clientには、ちょうど隙間が開いてるようである。。。

未読件数を取得

'api/0/unread-count'を JSON 形式で取得する

query = gdata.service.Query(feed='/reader/api/0/unread-count',
                            params={'all':'true', 'output':'json'})
feed = json.loads(service.Get(query.ToUri(), converter=lambda x:x))
unreadcounts = feed['unreadcounts']

# 全体の未読数を一番前に移動しとく
for i, item in enumerate(unreadcounts):
    if re.match(r'^user/\d+/state/com.google/reading-list$',item['id']):
        unreadcounts.pop(i)
        unreadcounts.insert(0,item)
        break

# 全体の未読数
print int(unreadcounts[0]['count'] if len(unreadcounts) > 0 else 0)
#=> 1

# 未読があるラベルとその未読数
for item in unreadcounts:
    if not re.match(r'^user/\d+/label',item['id']): continue
    print "count:%(count)s id: %(id)s" % item

#=> count:1 id: user/16814486509924941024/label/android

すべてのラベルを取得

query = gdata.service.Query(feed='/reader/api/0/tag/list',
                            params={'all':'true', 'output':'json'})
feed = json.loads(service.Get(query.ToUri(), converter=lambda x:x))
tags = feed['tags']

for item in tags:
    tag = re.sub(r'^user/\d+/',r'',item['id'])
    print "tag: %s" % tag
#=> tag: state/com.google/starred
#=> tag: state/com.google/broadcast
#=> tag: label/android
#=> tag: label/misc
#=> tag: label/neta
#=> tag: state/com.blogger/blogger-following

ラベルを指定して取得

android 関連の記事を 5 件見てみるかいな。。。

query = gdata.service.Query(feed='/reader/atom/user/-/label/android',
                            params={'n': str(5)})
feed = service.Get(query.ToUri())
for entry in feed.entry:
    print "===="
    dom = xml.dom.minidom.parseString(entry.ToString())
    print dom.toprettyxml(indent="  ")
    print "===="
    print "href: %s" % entry.GetHtmlLink().href
    print "title: %s" % entry.title.text
    # print "%s" % entry.summary.text

未読を既読に変更

先の記事は、読んだから既読にする。

# token, feed は、上に記載の書き込み用トークンと直前で取得した記事リスト
for entry in feed.entry:
    i = entry.id.text
    s = entry.source.extension_attributes['{http://www.google.com/schemas/reader/atom/}stream-id']
    ret = service.Post(urllib.urlencode({'i':i,
                                         'a':'user/-/state/com.google/read',
                                         's':s,
                                         'T':token,
                                         }),
                       '/reader/api/0/edit-tag',
                       converter=lambda x:x,
                       extra_headers={'Content-Type': 'application/x-www-form-urlencoded'})
    print i,ret

何でも無いが、この部分には半日悩んでしまった。

何気ない POST パラメータを送信する POST 処理なのだが、gdata.service.Postaplication/atom+xml形式のデータ送信を想定するため、明示的に Content-Typeを指定する必要がある!気づくまで、「400 Bad Request」+「X-Reader-Google-Bad-Token: true」に悩まされてしまった。

新しいフィードを登録

sub = r'feed/http://headlines.yahoo.co.jp/rss/rps_dom.xml'
ret = service.Post(urllib.urlencode({'s':sub,
                                     'ac': 'subscribe',
                                     'T':token,
                                     }),
                   '/reader/api/0/subscription/edit',
                   converter=lambda x:x,
                   extra_headers={'Content-Type': 'application/x-www-form-urlencoded'})
print sub,'subscribe',ret

購読しているフィードを解除

sub = r'feed/http://headlines.yahoo.co.jp/rss/rps_dom.xml'
ret = service.Post(urllib.urlencode({'s':sub,
                                     'ac': 'unsubscribe',
                                     'T':token,
                                     }),
                   '/reader/api/0/subscription/edit',
                   converter=lambda x:x,
                   extra_headers={'Content-Type': 'application/x-www-form-urlencoded'})
print sub,'unsubscribe',ret

参考

2011年2月15日

polipo + MacOSX で使う

普通の PC にインストールした Linux サーバに Squid + Squidguard で使っていたんだが、 別サーバを必ず立ち上げていないと行けないのが面倒なので、、、 乗り遅れ感が否めないが、polipo を常用をする環境を整えてみた。

移行に関しては、GUIは必要ないが launchd との繋ぎの設定ファイルを準備するのが面倒なので MacPorts パッケージを使いつつ、自前に用意したバイナリを使った。

本家サイトで公開されている git レポジトリを元に数点修正したものを使った。

  • 64 bit 環境だと stdarg 絡みで落ちるっぽい部分?を修正
  • redirector の入出力の行仕様をpolipo側でダミーで合わせた
  • censorReferer を maybe に設定した時、サブドメインに加えて指定のサイトリストも Referer を通す機能を追加

修正した履歴はgithubに公開してある。

最後の機能は、画像用を公開してるドメインが短縮した別ドメインに置き Referer で制限しているサイトに対応するためで、設定値uncensorRefererFileに、forbiddenと同じ形式で書けば、Referer を削除せずにスルーしてくれる。

まぁ、polipo も使えない事はないかなぁ。。。あとは、forbidden/redirector で Location を返す挙動がなんとかなれば、いいのになぁ。。。もうちょっと弄ってみるかなぁ

2011年1月27日

Mail.app の備忘録から Evernote に移行する

発売日に予約した IS03 が漸く入荷したので受け取ってきた。

いじり倒せる Android 端末が入手できた。 事前に電池のもちが異様に悪いと噂があったので、Killerアプリ等でコマメにアプリを終了し倒すように気を付けているので、ある程度許せる範囲に留まっている気がする。

まぁ、ノートパソコンにあるような大容量バッテリとかが出てくるのは、歓迎するが。。。どうなんだろう。

MacOSX の Mail.app には備忘録の機能が付いており、iOSとの組み合わせで同期が可能である。 結構便利でサクサク使っていたが、新規に Android でも同じようなことがしたくなって調べてみると、 どうも Evernoteが良いらしい。

メモに特化したアプリ、各プラットフォームにアプリがあり、相互に連携できる。。。なんか世の中凄いことになってるんだなぁ。。。

Mail.app の備忘録に蓄積したメモ書きを EverNote にサクっと移行するには、、、

どうすれば良いのだろうか?

何のことはない AppleScript を使うのが定石らしい。

参考URLの先コードを 「ユーティリティ」>「AppleScriptエディタ」にコピペして、「mailbox "Notes"」に書き換えて、実行すれば、「Imported Notes」という名前のノートブックの中にほぼ全部(「このMac内」の奴)コピー出来た。

あとは、ちまちまタグ付けや整理すればまた使いやすくなるのかなぁ。。。

参考URL

2010年11月9日

Google Chrome が吐き出すログをちょっとだけ片付ける

Mac OSX 上の Google Chrome は、何故か system.log にデバックか実装上の何かしらの情報を沢山吐く。

システムの他の問題を調査するときジャマ臭い。。。なんとかならんのかなぁ。

syslogd には高度なフィルタ機能が実装されていないので、system.log に書き出される行に関しては何ともしがたい。

但し、MacOSXでは syslogd とは別に asl という仕組みが並行して導入されている。「コンソール.app」 のデータベース検索以下の情報は asl の仕組みから取得している。

asl には、結構便利なフィルタ機能が実装されている。なので、件のログを収集しないようにするには、/etc/asl.conf の最後に次の設定を付け加えれば良さそうである。

# /etc/asl.conf に追加
# ommit com.google.Chrome
? [S= Sender com.google.Chrome] ignore

追記

良く考えれば、Chromeからのログを除外した「新規データベース検索」を登録しとけば良かったのかぁ。。。

2010年11月6日

MacOSXでRAMディスク上にブラウザのキャッシュを割り当てる

MacBook Pro 15(Late 2008)は公式では最大メモリ容量は4Gまでサポートなのだが、ファームウェアを最新のアップデート(MacBook Pro EFI ファームウェア・アップデート 1.8)を適用すれば、最大 8G まで普通に認識し速度低下せずに使えるそうである。

2009年末位には結構高価だったのだが、最近値下がりして手ごろになってきたので、交換した。 次いで HDD も交換して SSD (TOSHIBA THNS256GG8BBAA)に入れ替えた。

まぁ、SSD に入れ替えたお陰でOSの起動もアプリの起動も機敏で、いい感じ。

空きメモリが増えてたので、ちょっと1Gくらいブラウザのキャッシュに割り当ててみた。

MacOSX では「hdid」コマンドを使えば簡単にRAMディスクを作成できる。

ramlabel="RamDisk"
ramdev=$(hdid -nomount ram://10240)
diskutil eraseDisk HFS+ ${ramlabel} ${ramdev}
で、コイツを rc.localに仕込んでやれば、起動時にRAMディスクを作成できる。

なぜか上手く行かない。起動後に手打ちで入力すれば、出来るのだが、、、

はて、なんでだろうかぁ?

まぁ、ググっても明快な正解がわからない。。。

当てずっぽに答えれば、『「hdiejectd」デーモンが起動して、正常に定常状態に無いときには「hdid」は機能しない』っぽいのかなぁ。。。多分 SSD で起動が拙速になったからだと思うが、、、

上記の憶測のもとに rc.local を次のようにすれば、起動直後にユーザ用にRAMディスクに載ってる作業領域が作れるようになる。

#!/bin/sh

RAMSIZE=1024 # MBtyes
MP=/tmp/ramdisk
MYNAME=username

# Start hdiXXX
launchctl start com.apple.hdiejectd

sleep 5

# Make RamDIsk
RAMNUMSECTORS=$((${RAMSIZE}*2048))
ramdev=$(hdid -verbose -kernel -nomount ram://${RAMNUMSECTORS})
newfs_hfs -v ramdisk $ramdev
[ -d ${MP} ] || mkdir ${MP}
mount -t hfs -o nobrowse $ramdev ${MP}
# Finder.appで /Volume 以下で参照したいときは nobrowse を外す

# for ${MYNAME}
mkdir ${MP}/${MYNAME}
chown -R ${MYNAME}:${MYNAME} ${MP}/${MYNAME}

あとは、ログイン項目に、次のような キャッシュを調節するシェルスクリプトを埋め込んだ Automator アプリを登録すれば良い。

まぁ、サクサクになったのかなぁ?

追記 (2010/11/06)

コードをちょっとだけ整理して、Xcode と TMPDIR もRAMDISKにのせてみた。

追記 (2010/12/23)

TMPDIR もRAMDISKに載せると、どうも ramdisk のアクセス出来ない現象が時々発生し、キャッシュを載せている Chromeなどのブラウザが固まって、まともに使えない結果になる。。。どうも TMPDIR は ramdisk に載せて運用するのは難しそうである。仕方がないので、設定を削除してみた。。。ここ1ヶ月は、安定してるっぽいので正解かな。。。

2010年10月16日

dotfiles を github に上げてみた

dotfiles を公開レポジトリに上げるのが最近の流行らしい。なので、僕も github に上げてみた。

結構古くから VCS に入れて適当に履歴を記録したんだが、 「git rebase -i 」を使うと commit を修正できるので、 CVS ~ Subversion ~ git に変更する過程の履歴を 適当に整理してみた。

うん、なんとも紆余曲折がある、、、未だにちょっと壊れ気味の設定だなぁ。。。

2010年10月1日

Squeeze に移行してみる

squeeze がフリーズされて、暫く経つので安定の良い頃合いかなと、 自宅のメインのサーバを lenny から squeeze に移行してみた。

何とも、安定してる。。。

lenny ベースだと、古く使いたい機能が無いので、 適当に野良バックポートしてた netatalkkvm/libvirt-bin とか幾つかあったのが、 標準のパッケージで済むのが良い。

ただ、1点だけ手作業が必要だった。 どうも autofs のマップファイルが LDAP を参照しているとき、 マスタでは slapd が立ち上がらないタイミング(autofs より slapd が後)なので、 うまく機能しない。。。

まだ sysvinit ベースなので、次のようにした。

update-rc.d -f slapd remove
update-rc.d slapd defaults 18 82

upstartに移行した暁には、Debian もいい感じになるのかなぁ

追記 (2011/02/12)

Debian squeeze から upstart の時代だといった奴は、、、 sysvinit と insserv の合わせ技が標準じゃないかぁ!!

なので、/etc/init.d/autofs の先頭に書かれた insserv 設定行の該当部分を下記のように書き換えると、対処ができる。

...
# Should-Start: ypbind nslcd slapd
# Should-Stop: ypbind nslcd slapd
...

2010年7月1日

Linux SCSI Target Framework を使う

Debian/Ubuntu の iSCSI Target のお話が出てくると、iSCSI Enterprise Target (IET)が必ず出てくる。

まぁ、良いんだけど kernel ソースに取り込まれていないモジュールを使うので、 時々、他の複合的な要因かもしれないが、あさっての場面で oops は吐いくれたりする。

Fedora/RHEL/CentOS とかだと、既にLinux SCSI Target Framework(tgt)に移行している。コイツは 2.6.20 頃 kernel ソースに取り込まれているので、 結構安定してるんじゃないかなと思う。

tgt の性能に関しては、2006 年頃の論文「Linuxにおけるストレージシステムフレームワークの実現(オペレーティングシステム)」を見る限り、IET と若干落ちるぐらいなので、気にしなくても良いかも。

そろそろ Debian/Ubuntu でも Linux SCSI Target Framework(tgt)に移行する時期だ。

ユーザベースのツール群 tgt パッケージは、squeeze/lucid で用意されているみたいなので、やってみた。

ハマりポイントが2点ある。

  1. init スクリプトが見当たらない。バグ(#577925BUG #574554)として登録されている。
  2. tgt-admin 内で、デバイスが既に利用してるかどうかチェックする部分が上手く動いていない。と言うか、Debian/Ubuntuでは /bin/sh が dash (ash の亜種) になっているため、perl の system関数の呼び出しのスクリプト片に移植性がある書き方が要求される。コイツを踏んでる。

なので Fedoraのinitスクリプトを参考に、upstart 用のイベント設定ファイル? /etc/init/tgtd.confを書き下し、tgt-admin の修正パッチtgt-admin.diffを作ってみた。

例として、単一ディスクをiSCSIで公開する事を考える

以下の設定ファイルを書き下し、「tgt-admin -e」とタイプすれば良い。

/etc/tgt/targets.conf

default-driver iscsi

<target iqn.2010-07.com.example:stroage.fserver.data>
	driver iscsi
	backing-store /dev/sdb
</target>

実際にiSCSIターゲット設定が上手く行ったかは、次のようにする。

# tgt-admin -s
Target 1: iqn.2010-07.com.example:stroage.fserver.data
    System information:
        Driver: iscsi
        State: ready
    I_T nexus information:
    LUN information:
        LUN: 0
            Type: controller
            SCSI ID: IET     00010000
            SCSI SN: beaf10
            Size: 0 MB
            Online: Yes
            Removable media: No
            Backing store type: rdwr
            Backing store path: None
        LUN: 1
            Type: disk
            SCSI ID: IET     00010001
            SCSI SN: beaf11
            Size: 34360 MB
            Online: Yes
            Removable media: No
            Backing store type: rdwr
            Backing store path: /dev/sdb
    Account information:
    ACL information:
        ALL

あとは、巷に溢れている tgt の設定方法が使える。 上手く設定すると、CDドライブやリムーバルディスクとかも、ネット越しで使えるようになるらしい。

追記 (2010/09/06)

気づいてみると、二番目のハマり点も修正済み(#589716)になったようである。

debian squeeze がリリースしたら、tgt をサクッと使うようになれる訳ですね。

2010年6月8日

日本語 texi から栞付きPDFを生成する

GNU のドキュメントシステムに texi 形式のファイルがある。 この形式のファイルから適当なコマンドを使って、info / dvi / pdf / html 等の 文書に変換できる。

最近では PDF 形式に変換するのに pdfetex を使う事で dvi 経由せずに直接 pdf に変換できる。 ただ、pdfetex は日本語化されていないので、日本語で書かれた texi は pTeX と dvipdfmx を組み合わせて変換する必要がある。

% TEX=ptex texi2dvi filename.tex
% dvipdfmx filename.dvi

このやり方でも pdfetex を使った変換と同様な PDF が作れるが、一つだけ違いがある。

栞/ブックマークが付かない。

実用上は問題は無いが、栞が付いた方が使い易い。。。はてどうしたもんだかぁ

texinfo.tex の日本語化

変換用のマクロ texinfo.tex の日本語化は本家 texinfoには含まれていない。 現在良くメインテナンスされているものとして、角藤版pTeXの texinfotools-w32.tar.bz2 がある。

ただ、僕も昔に texinfo.tex や makeinfo のナンチャって日本語化対応したことがある。 HDD の隅にある断片を探して調べてみたら、どうも elisp-manual-19-2.4-jp2.0.tar.gz を起点にして 作業したもので、検索をかけるとホンの僅かだが OSS の文書変換用に取り込まれている。。。

まぁ、自分の成果から起点とするのが、やり易いからコイツから作業するのがいいやぁ

dvipdfmx が PDF 生成用の special は 「Dvipdfm User’s Manual」/「DVI specials for PDF generation」 にキッチリ記載があり、栞の生成は難しくはなさそうである。

で、texinfo.tex の履歴だけgithub fukusaka/texinfo-ja に上げて、texinfo.tex の最新版と組み合わせて使えるように修正、同時に栞生成コマンド@usedvipdfmxを追加してみた。

使い方

texi のヘッダ部を次のように修正する。

\input texinfo @c -*-texinfo-*-
@c %**start of header
@setfilename filename.info
@settitle TITLE
@documentlanguage ja
@documentencoding utf-8
@iftex
@usedvipdfmx
@end iftex
@c %**end of header

で、pTeX / dvipdfmx を使って、栞付きのPDFが生成できる。

まとめ

iOS4のPDFリーダーは栞付きが上手く扱えるのだろうかぁ。。。

2010年5月26日

Cocoa Emacs のフレームをSpaces のワークスペースの上下左右に飛ばす。

個人的な使い方の問題だろうが、emacs に凝っていた頃は仮想ディスクトップ毎にフレームを置いた使い方をしていた。

この使い方の要は、elisp からフレームを任意の位置、任意のワークスペースに移動できる事であった。

既に MacOSX では仮想ディスクトップが Spaces としてサポートされている。 位置移動はできるようだが、ワークスペースの移動はどうもわからない。。。

マウスでチマチマ動かすのは、ちょっといただけない。。。

どうしたもんだろう?

Quartz のなんか

MacOSX の仮想ディスクトップは Leopard で初めてお目見えしたが、 結構前から Window Server (Quartz Compositor/Core Graphics Services/Quartz Window Services...一体いくつの名称があるんだか。。。)には実装されていたそうである。 Tiger の時代から仮想ディスクトップがサードパーティのものがあったのはそういう訳らしい。

で、コイツのAPIのほとんどが今でも非公開になっている。。。断片的には、スクリーンキャプチャ用途レベルのものが公開されている。。。なんとも厄介。

先人が調べ尽くした結果として、最後のリンクの先の内容が、 特定のウィンドウを任意のワークスペースに移動する方法らしい。

模式コードは次のようになる。(CGSPrivate.hは一番目のリンク先にあるもの)

#import <CGSPrivate.h>
...
NSWindow *win = ...;
CGSConnection cid = _CGSDefaultConnection();
CGSWindow wid = [win windowNumber]; // ?
CGSMoveWorkspaceWindowList(cid, &wid, 1, workspace);

CGSを解析した作られた CGSPrivate.h でのCGSWindow と Appleから出ているドキュメントに出てくる CGWindowID とは window server 内で割り振られた番号で同じ実体と思われるが、 NSWindow の windowNumber のドキュメントには、それとは違うと書かれている。 混ぜても動いたから多分良いかと思われるが、、、ここいらはぼかしたい内容なのかなぁ。。。分からんなぁ林檎は。

まぁ、ここまで分かれば、出来たも同然〜。

で、適当にコマンドを作ってみた。

cgsutil.m

Emacs.appの改造

(frame-parameters)には window-id があるから、Cocoa Emacs では多分コイツがフレームウィンドウの CGWindowID のはずで、コイツと飛ばしたい workspace 番号を適当に作ったコマンドに渡して、お仕舞いかなぁ。

わぁーい。らくちん。

はぅ。。。

Cocoa Emacs では window-id の値は、1から単調増になるように割り振った全く意味の無い番号でした。

仕様が無いので、次の追加機能を付けるパッチ(emacs-23-cgs-workspace.diff) を作ってみた。

  • フレームパラメータns-window-idに、CGWindowIDと思われる値
  • フレームパラメータns-workspace-idに、フレームのworkspace番号
  • フレームを指定のworkspaceに移動する関数 (set-frame-ns-workspace FRAME WORKSPACE)

まぁ、最初の一つだけで十分だが、後二つは組込まなくてもいいかも。

まとめ

上のパッチを適用した Emacs.app に適当な elispを書くと、1コマンドで複数のフレームを特定のワークスペース/特定の位置に開く事が出来るようになった。

screenshot-2010-05-26 17.54.51

うん〜〜。快適じゃ。

はぅ。。。

Cocoa Emacs で8フレームも開くと、キー入力が引っ掛かるようになり、Emacsプロセス自体のCPU利用率もイマイチ高い。イベント処理方法にまだ難があるのかなぁ。

4フレームくらいで抑えないとスムーズに使えないかなぁ。。。

追記 (2010/06/16)

複数のフレームを開いたときCPU利用率が高くなるのは、本パッチ内のframe-paramaters にワークスペース番号を追加するのが原因だった。。。frame-parameters の取得は不随に起きるらしくのでどうも軽くなくては行けない。

なので、workspace番号は取得関数から得るように変更し、workspace 絡みの部分を分けたパッチにしてみた。

  1. emacs-23-cg-window-id.diff
    • フレームパラメータns-window-idに、CGWindowIDと思われる値
  2. emacs-23-cgs-workspace.diff
    • 指定フレームのworkspaceを取得する関数 (frame-ns-workspace FRAME)
    • フレームを指定のworkspaceに移動する関数 (set-frame-ns-workspace FRAME WORKSPACE)

ふむ。
8フレームを開いても、キー入力が引っ掛かる症状は無くなった!!
すごく快適〜ん。

パッチを切ったり張ったり入れ替えたりする(1)のに、git rebase -i は極めて便利。git 優秀だなぁ

2010年5月18日

Emacs で文法チェック

Emacs でプログラムを書く人々は、リアルタイムに文法チェックをするために flymake を使うらしい。

以前聞き覚えがあるが、何をする物か分からないのでスルーした奴だが、結構使えるものだったのかぁ。

なので flymake の設定をしてみた。

Quick Start

詳細は info マニュアルに書かれているが、 使い始めの設定は次の通りになる。この状態で、何もせずに Perl/PHP の文法チェックは行なえる(perl/php コマンドがあればの話だが)。

(require 'flymake)

;; GUIの警告は表示しない
(setq flymake-gui-warnings-enabled nil)

;; 全てのファイルで flymakeを有効化
(add-hook 'find-file-hook 'flymake-find-file-hook)

;; M-p/M-n で警告/エラー行の移動
(global-set-key "\M-p" 'flymake-goto-prev-error)
(global-set-key "\M-n" 'flymake-goto-next-error)

;; 警告エラー行の表示
(global-set-key "\C-cd" 'flymake-display-err-menu-for-current-line)

次に C/C++ で文法チェックを可能にするには、 Makefile を使い、次の様な check-syntax ルールを追加すればよい。

PHONY: check-syntax
check-syntax:
    $(CC) -Wall -Wextra -pedantic -fsyntax-only $(CHK_SOURCES)

ここまですると、編集途中にリアルタイムに文法エラー/警告の部分に色が付き、分かり易い。

なるほど、、、これは素晴らしい。

以下の設定は、好きずきだと思う

警告エラー行の表示のカスタマイズ

警告エラー行の表示は、 プラットホーム毎のポップアップメニュー実装が使われるが、 色々検索すれば出てくるが、2通りのカスタマイズが良く知られている。

  1. Minibufに表示する。
  2. popup.el(auto-complete に含まれている)のpopup-tipsで表示する。

;; Minibuf に出力
(defun my-flymake-display-err-minibuf-for-current-line ()
  "Displays the error/warning for the current line in the minibuffer"
  (interactive)
  (let* ((line-no            (flymake-current-line-no))
         (line-err-info-list (nth 0 (flymake-find-err-info flymake-err-info line-no)))
         (count              (length line-err-info-list)))
    (while (> count 0)
      (when line-err-info-list
        (let* ((text       (flymake-ler-text (nth (1- count) line-err-info-list)))
               (line       (flymake-ler-line (nth (1- count) line-err-info-list))))
          (message "[%s] %s" line text)))
      (setq count (1- count)))))

;; popup.el を使って tip として表示
(defun my-flymake-display-err-popup.el-for-current-line ()
  "Display a menu with errors/warnings for current line if it has errors and/or warnings."
  (interactive)
  (let* ((line-no            (flymake-current-line-no))
         (line-err-info-list (nth 0 (flymake-find-err-info flymake-err-info line-no)))
         (menu-data          (flymake-make-err-menu-data line-no line-err-info-list)))
    (if menu-data
      (popup-tip (mapconcat '(lambda (e) (nth 0 e))
                            (nth 1 menu-data)
                            "\n")))
    ))

僕としては popup.el を使うのが結構好み

check-syntaxターゲットルール

先に述べて Makefile の check-syntaxターゲットルールでは一種類の文法チェックプログラムしか使えない。。。 gcc でチェックできるものは全てチェック出来るから、気を回す必要は無いかもしれない。

GNU make を使えば、拡張子毎に文法チェックプログラムを選べるルールの書き方がある。

CHECKSYNTAX.c = $(CC) $(CFLAGS) $(CPPFLAGS) -Wall -Wextra -pedantic -fsyntax-only
CHECKSYNTAX.cc = $(CXX) $(CXXFLAGS) $(CPPFLAGS) -Wall -Wextra -pedantic -fsyntax-only

check-syntax: $(addsuffix -check-syntax,$(CHK_SOURCES))

%.c-check-syntax:
	$(CHECKSYNTAX.c) $*.c

%.cc-check-syntax:
	$(CHECKSYNTAX.cc) $*.cc

まぁ、ここまで書く奴はいないかぁ。。。

Makefileが無くてもC/C++の文法チェック

Makefileが無ければ、直接 gcc で文法チェックをし、 Makefileがあればcheck-syntaxターゲットルールを使いたい場合は、 次の設定をすれば良い。

(defun flymake-simple-generic-init (cmd &optional opts)
  (let* ((temp-file  (flymake-init-create-temp-buffer-copy
                      'flymake-create-temp-inplace))
         (local-file (file-relative-name
                      temp-file
                      (file-name-directory buffer-file-name))))
    (list cmd (append opts (list local-file)))))

;; Makefile が無くてもC/C++のチェック
(defun flymake-simple-make-or-generic-init (cmd &optional opts)
  (if (file-exists-p "Makefile")
      (flymake-simple-make-init)
    (flymake-simple-generic-init cmd opts)))

(defun flymake-c-init ()
  (flymake-simple-make-or-generic-init
   "gcc" '("-Wall" "-Wextra" "-pedantic" "-fsyntax-only")))

(defun flymake-cc-init ()
  (flymake-simple-make-or-generic-init
   "g++" '("-Wall" "-Wextra" "-pedantic" "-fsyntax-only")))

(push '("\\.[cC]\\'" flymake-c-init) flymake-allowed-file-name-masks)
(push '("\\.\\(?:cc\|cpp\|CC\|CPP\\)\\'" flymake-cc-init) flymake-allowed-file-name-masks)

まとめ

取り敢えず、次いでに ruby/bash の文法チェックを追加したのが、 今現在の設定になっている。

45flymake.el

あとは Python/Java/HTML/CSS をチェックするのがあれば良いが、、、 これくらい素のflymakeに含まれていればいいのになぁ。。。

あとSemanticかぁ。。。

追記 (2010/05/24)

暫く使ってみたが、基本動作で2点だけイマイチな挙動を修正しないと、ストレスが溜まりまくる。

  1. ファイルもしくは上位ディレクトリに書き込み権限が無い場合、messageを吐いて開くのを諦めてしまう。。。
  2. 文法チェックプログラムが無い場合 flymake がオフになるが、それでも何かのプロセス?が残って、後々無意味な y の連打をしないといけない。。。
これも、素のflymakeで用意してくれれば良いのに、、、で場当たり的に次の設定を追加した。。。

;; flymake を使えない場合をチェック
(defadvice flymake-can-syntax-check-file
  (after my-flymake-can-syntax-check-file activate)
  (cond
   ((not ad-return-value))
   ;; tramp 経由であれば、無効
   ((and (fboundp 'tramp-list-remote-buffers)
         (memq (current-buffer) (tramp-list-remote-buffers)))
    (setq ad-return-value nil))
   ;; 書き込み不可ならば、flymakeは無効
   ((not (file-writable-p buffer-file-name))
    (setq ad-return-value nil))
   ;; flymake で使われるコマンドが無ければ無効
   ((let ((cmd (nth 0 (prog1
                          (funcall (flymake-get-init-function buffer-file-name))
                        (funcall (flymake-get-cleanup-function buffer-file-name))))))
      (and cmd (not (executable-find cmd))))
    (setq ad-return-value nil))
   ))

追記 (2010/05/25)

上の修正は、ちょっと上手く行かない場合があったので修正っと。

追記 (2010/05/27)

tramp経由の場合も、イマイチ上手く動かないので、除外に加えてみた。

2010年5月13日

Emacs Refcard 日本語版

Emacs のチートシートは、Emacs と一緒に配布されている。 refcard.tex から pdfを作って印刷すれば良い。 少し古いバージョンだが、日本語に翻訳されたものは「Emacs-20/21 Reference Card 」にある。

キー操作として、手に染み付いているものは半分くらいしか無い。。。 大抵 M-x コマンドで済まして場合が多いなぁ。

いかんなぁ。。。

再度覚え直す為に、先の日本語RefcardとEmacs23に入ってるrefcardと若干漏れている部分を補い、 一部語句を修正し、フォント関係を微調節してものを作ってみた。

refcardja.tex

次いでに ptex/dvipdfmx を使って PDF を作って、Google Docs に上げてみた。

refcardja.pdf

まとめ

うん、久しぶりに素のTeXを弄ったが本当にややこしい奴だな。

2010年5月12日

Cocoa Emacs が落ちる

Cocoa Emacs は安定していると思ったが、 どうもポップアップダイアログが出ると暫くして落ちてしまう。

flymake をチマチマ使えるように設定を弄ったら、時々でるポップアップに刺さる。。。

しようがないので、gdbで追っかけてみた。

調べてみたら、次のような簡単な処理でも、 ポップアップが出て暫くしてEmacsが落ちるようである。

どうも inline patch 側での処理抜けらしい。。。 こんな感じに修正すると落ちなくなった

うん、すこぶる快適

久しぶりの投稿

かなり期間が空いてしまったが、ブログを再開してみようと思う。 2013年3月が直前の投稿だったが、頻繁に更新していた時期が 2011年11月までなので、8年間ぶりとなる。 8年間なにをしていたのかと言えば、2回転職して未だにIT技術者の職を得ている。 その...