2011/01/31

git-svn

google closure library 入れたり、chaton のサンプルソース読みたいのに sourceforge の Web ソースビューワが動いてなかったり(2011/01/31 現在)で、調べたら git-svn というのがあったので入れました。

こんな感じで使えます。
git svn clone https://chaton.svn.sourceforge.net/svnroot/chaton chaton

便利。
yum から入りました。

実用Git

node.js で google closure library (node-goog)

こちらを読んでいて、node.js で closure 動かないのかなーと思ったら、それっぽいのがあったので入れてみました。

README 通りにすんなり入ったので、特に書くこともないんですけどね。

JavaScript 第5版

node.js を終了



取りあえず Ctrl + c してました。
どうやって終了するんだろうなーと思っていたのがわかったので書いておきます。
process.exit();

gauche だと (exit) だったり、python だと sys.exit() だったり、gs だと quit だったり、忘れるのでやっぱ C-c が手っ取り早いですかね。






Gauche で goo.gl api (httpsとか)

Gauche で URL 短縮したくて、せっかくなので最近公開された(?)goo.gl の api を使ってみました。

rfc.httpモジュールがhttpsコネクションをサポートします (今のところunix限定)。 コネクション自体は外部プログラム(stunnel) に依存します。

stunnel が入ってれば、サラッと動くようです。
入ってなければインストール。

自分の tumblr の quote をランダムにつぶやくボットとか、自分のふぁぼり(ふぁぼられではない)をランダムにつぶやくボットとかを serversman で動かしてるんですが、その url 短縮に使おうかなーと。

ソースはこんな感じ。
(use rfc.http)
(use rfc.json)
(use rfc.uri)


(define *goo.gl-server* "www.googleapis.com")
(define *goo.gl-request-uri* "/urlshortener/v1/url")

(define my-api-key "hoge")


(define (shorten-url url api-key)
  (body->json
   (^ _ (goo.gl-request http-post url api-key
                        :msg (construct-json-string
                              `(("longUrl" . ,url)))))))

(define (expand-url url api-key)
  (body->json
   (^ _ (goo.gl-request http-get url api-key
                        :more-req-uri #`"&shortUrl=,|url|"))))

(define (body->json req)
  (receive (status header body)
      (req)
    (parse-json-string body)))

(define (goo.gl-request method url api-key
                        :key (more-req-uri "")(msg #f))
  (let1 req-uri (string-append
                 *goo.gl-request-uri*
                 "?key=" api-key more-req-uri)
  (if msg
      (method *goo.gl-server* req-uri
              msg
              :content-type "application/json"
              :secure #t)
      (method *goo.gl-server* req-uri
              :secure #t))))


;; (shorten-url "http://valvallow.blogspot.com/" my-api-key)
;; (shorten-url "http://practical-scheme.net/" my-api-key)

;; (expand-url "http://goo.gl/wvWgf" my-api-key)
;; (expand-url "http://goo.gl/ZThO" my-api-key)

プログラミングGauche

2011/01/29

日記


仕事や職場に慣れてくるにつて疲れも蓄積してきた。
職場は、みんな定時に帰るような素敵なところなんだけど、1年以上毎日ゴロゴロしてた身としてはそれでも疲れは溜まってくる。



設計も難しくて放心することもしばしば。
「圧倒的な量は細切れに」とのアドバイスを頂きつつ、集中力が切れたらハンズオン。

いままでやったことのある「設計」が、せいぜいアプリケーションレベルやコードレベルでのもっとも下流に近い工程のものだったのだと改めて認識しつつ四苦八苦。
「しすてむ」の設計とか難しいれす(^p^)



疲れてくるとネットをダラ見しがち。
その時間を睡眠時間にあてた方がきっとマシ。

勉強したいことや作りたいものがあっても、寝る時間だけは削っちゃいけないと思う。
(反省を込めて)
短眠や寝不足はパフォーマンスの低下っぷりがすごい。すくなくとも私にとっては。



はてぶの新着とかホッテントリとかに飽きてきて、もっと別の方法でネットサーフィンしたいと思って昔ながらの方法(?)に逆戻りしてる。

(「はてぶがおもしろくなくなった」とか言いたいんじゃなくて、単に飽きてきた。ノイズ多いしジャンル広いし。)


その方法というのが、特定の人(主にすげぇーと思ってるプログラマの人)のブログや昔ながらのWeb日記的なものを辿れるだけ辿った過去のものから現在に向けて順番に読んでいくというもの。
で、暇なときとかボーっとしてるときに7つくらいのブログを過去の方から眺めてるんだけど、これすごいおもしろい。
漠然とした感覚だけど、2003 ~ 2007 年くらいに面白い記事が多いような印象がある。


で、やっぱすごい(すごそうな)人って、ずーっと何かモノを作り続けてるんだなーと感じる。射撃しつつ前進じゃないけど、そんな感じ。自分も何か実用的なものを作ることを始めたいと思う。

駄作が並ぶとは思うけど、初めからうまく作れるなんてことも考えにくいので仕方ない。
すごい人もきっと突然すごいものを作れるようになったわけではないと信じつつ。


org-remember で書き溜めてるメモのファイルが巨大化し始めた。
  • 私的なメモ
  • 職場でのメモ
  • 日報
  • 仕事用の日報
どれも dropbox にバックアップ。
私的なメモは職場から参照のみ、仕事用の日報は職場以外からは参照のみ、両方から編集するものは dropbox のファイルを直接参照するような設定にしている。evernote はまだ検討していない。
で、org-agenda すると全てのファイルから横断的に検索できるようにしてるので、ハッピー。
あとはタグがつけれたらなー・・・、と思っていたらあった。

以前は changelog メモを使っていたけど、数ヶ月前に org-mode に移行。
org-remember 素敵!

そういえば evernote も emacs から使えるとか。

tumblr までも。。

2011/01/28

Gauche で cgi

Web アプリっつったら ASP.NET と WCF しかしたことないゆとり仕様の私にもできました。

Serversman の Serversman にさよならして、cgi を置いてみたわけです。
GET に対して json を返すだけの簡単なお仕事。
rfc.json もあるし。

んで、これまた emacs + tramp が便利過ぎて感動しました。
tramp で接続した状態で run-scheme で gauche を起動するとサーバーの方の gauche が起動してくれるんですね><
ハンパねー便利。
(node.js も run-js がそうだった)

cgi は Gauche で書く分にはすごく簡単にキレイに書けて爽快だったんですが、apache とかそっちで苦戦しました。。
.scm な cgi が動く様はなかなか感慨深いですね。


cgi calendar もハンズオンしてみました。
修正されていく様がエレガント~。

with-db マクロとか素敵過ぎる。
parameterize ってこうやって使うんだ。。

それで思い出したんですが、そういやプログラミング Gauche にも同じようなのがあったなーと。
以前読んだ時は linux はおろか Emacs すら始めたばっかだったので飛ばしました。
ということでそっちもやってみよう。

プログラミングGauche

PostgreSQL のストアドを Scheme で

これも @kikuchan98 さんに教えてもらいました。
裏では Guile が動くみたいです。

まだ PostgreSQL 自体の扱い方がいまいちわかんないような状態なので、これを使うようなことはもう少し先のお話かも。
ようやく Serversman に入れた PostgreSQL にローカルからネットワーク越しにアクセスできるようになったところです。

余談

SQL で木構造扱うのって悩みの種だと思うんですが、RDB 向けのデザインパターンみたいなノリでサンプル集が欲しいなどと思うわけです。

こことか参考になります。
日本語ではこういう情報ってあまり見かけませんよね。

SQL で木構造や階層構造を扱うってんで以前、隣接モデルでやったことはあるんですが結構大変でした。
何回 join すんだよ、決め打ちか?みたいな。抽象度低くね?みたいな。

で、今回は Nested Set Model について一通り調べてみて、サンプル書いてみたりしたんですが、これもこれで大変そうな。。

「だったらストアドにすればいいじゃん。ポスグレなら Scheme でも書けるよ。」
「な、なんだってー!」 > ΩΩ Ω ザワザワ

別に Transacto-SQL とかを書くのは嫌いじゃないですけど、Scheme で書けるとなると書いてみたいですね。


あと、もう一つ気になったのが、DB のサンプル少なくないですか?
私が見つけられなかっただけでしょうか。。

「マ○ドナルドのメニューとか CSV で落ちてそうじゃね?」などと思って探してみたり。
郵便番号辞書から階層データ作るのも、なんだかなーだし。

今回は結局自分で手打ちすることに・・・。
最初に思いついた、ドリンクメニューにしました。

  • 飲み物
  • ジュース
    • オレンジ
    • コーラ
    • カルピス
  • アルコール
      • 美少年
      • ずいよう
    • 焼酎
        • 白岳
        • 伊佐錦
        • 伊佐美
        • 白波
        • 魔王
        • 森伊蔵
        • 佐藤
        • 霧島
        • 黒麹
          • 黒伊佐錦
          • 黒白波
          • 黒佐藤
          • 黒霧島
        • 二階堂
        • いいちこ
      • 黒糖
        • 喜界島
        • れんと
      • その他
        • たんたかたん
    • カクテル
    • ワイン
    • ブランデー
    • ウィスキー
    • ビール
      • 国内
      • 国外
  • コーヒー
  • お茶
  • ・・・
みたいな。
できあいのこういうデータがCSVか何かで複数あったらうれしくないですか?

こういうジョジョの系譜のデータとかね。


MSSQL だったら pubs, northwind, adventure works なんかもありますし、postgres でも sample DB があるにはありました。
でもなんか、あんまり親切じゃないようなイメージです。
詳しいドキュメントとか、ER 図とか、ER 図とか、あると嬉しいんですけどね。



PostgreSQL完全機能リファレンス―実行例を通して「理解」を深める。

node.js + postgreSQL

node.js 自体のインストールは特に問題なく。
CentOS と Cygwin に入れました。

python が入ってないと要求される

node_postgres の方。
(cygwin には入れてない)
  • MySQLもPostgreSQLもちゃんと使える
ダウンロードして展開して README よろしく
node-waf configure build
で入りました。

で、
npm install .
すると、node_postgres 同梱の test.js も無事動きました。
record は配列の配列で返ってくるみたいですね。

lisp.js

今日 @kikuchan98 さんに「node.lisp みたいなのがあるらしいよ」と教えてもらったので検索してみた。
これかな。

@kikuchan98 さんは既に node.js でいくつかモノを作られていて、一個見せてもらった。
node.js が動いてるサーバーにとある自作機器がつながっていて、Web 経由で node.js とお話して接続された機器経由でまた別のとあるモノを制御するという一品。
すげー。

もう一個はできてからのお楽しみということで教えてもらえなかった。
きっと #9LISP とかで見せてもらえるに違いない。

自分はといえば、写経とかハンズオンとかそんな状態。。

参考


JavaScript Patterns

2011/01/27

frame-arrange.el 設定例(再)

自分用の設定がまた変わったので、のせておきます。
(require 'frame-arrange)
(frame-arrange-mode t)

;; key-map - 「control + shift + 矢印 」で少しずつ位置を変更する
(define-key global-map [(C shift down)]
  'frange:increment-position-top/current-frame)
(define-key global-map [(C shift up)]
  'frange:increment-position-bottom/current-frame)
(define-key global-map [(C shift left)]
  'frange:increment-position-right/current-frame)
(define-key global-map [(C shift right)]
  'frange:increment-position-left/current-frame)

;; key-chord.el を使用した位置の変更
;; ;; (auto-install-from-emacswiki "key-chord.el")
;; (require 'key-chord nil t)
;; (setq key-chord-two-keys-delay 0.04)
;; (key-chord-mode 1)
(key-chord-define-global "qw" 'frange:arrange/top-left-most/current-frame)
(key-chord-define-global "we" 'frange:arrange/top-most/current-frame)
(key-chord-define-global "er" 'frange:arrange/top-right-most/current-frame)
(key-chord-define-global "as" 'frange:arrange/left-most/current-frame)
(key-chord-define-global "df" 'frange:arrange/right-most/current-frame)
(key-chord-define-global "zx" 'frange:arrange/bottom-left-most/current-frame)
(key-chord-define-global "xc" 'frange:arrange/bottom-most/current-frame)
(key-chord-define-global "cv" 'frange:arrange/bottom-right-most/current-frame)

;; 名前を付けて保存してある設定を復元する
;; この場合 min, max という名前で保存してある設定
(define-key global-map (kbd "C-c m")
  #'(lambda ()
      (interactive)
      (frange:restore-frame-position-parameter
       (selected-frame)
       'min)))

(define-key global-map (kbd "C-c M")
  #'(lambda ()
      (interactive)
      (frange:restore-frame-position-parameter
       (selected-frame)
       'max)))

;; 移動距離を設定する
(setq frange:position-incremental-value 10)

;; サイズを変更する関数を生成する
(def:frange/current-frame increment-size-top
  (nil height #'(lambda (v frame)
               (+ v frange:size-incremental-value))))
(def:frange/current-frame decrement-size-top
  (nil height #'(lambda (v frame)
               (- v frange:size-incremental-value))))
(def:frange/current-frame increment-size-left
  (nil width #'(lambda (v frame)
               (+ v frange:size-incremental-value))))
(def:frange/current-frame decrement-size-left
  (nil width #'(lambda (v frame)
               (- v frange:size-incremental-value))))

;; 「Alt + 矢印」でサイズを変更する
(define-key global-map [(M down)]
  'frange:increment-size/current-frame)
(define-key global-map [(M up)]
  'frange:decrement-size/current-frame)
(define-key global-map [(M down)]
  'frange:increment-size-top/current-frame)
(define-key global-map [(M up)]
  'frange:decrement-size-top/current-frame)
(define-key global-map [(M right)]
  'frange:increment-size-left/current-frame)
(define-key global-map [(M left)]
  'frange:decrement-size-left/current-frame)

;; M-x から呼ぶので短かい名前の関数でラップ
;; regist
(defun my-reg-frame ()
  (interactive)
  (frange:regist-frame-position-parameter-interactive))

;; restore
(defun my-res-frame ()
  (interactive)
  (frange:restore-frame-position-parameter-interactive))

;; remove
(defun my-rem-frame ()
  (interactive)
  (frange:remove-arrange-config-alist-interactive))

(defun my-print-frange ()
  (interactive)
  (frange:print-frame-position-parameter/current-frame))

(defun my-print-frange-n ()
  (interactive)
  (frange:print-arrange-config-names))

(defun my-print-frange-e ()
  (interactive)
  (frange:print-arrange-config-alist-entries))

;; F12 連打で保存してある設定(位置とサイズ)を順番に適用する
(define-key global-map [f12]
  (frange:cycle-arrange-config-gen))
設定(位置とサイズ)の保存は frange:regist-frame-position-parameter-interactive から。


入門 GNU Emacs 第3版

frame-arrange.el の保存してある設定を cycle する

こんな感じで。
frame-arrange.el に追加しました。
;; cycle
(defun frange:cycle-arrange-config-gen ()
  (lexical-let ((cur 0))
    #'(lambda ()
        (interactive)
        (let ((conf frange:arrange-config-alist))
          (when conf
            (let* ((len (length conf))
                   (next (if (<= len (+ cur 1))
                             0
                           (+ cur 1))))
              (frange:restore-frame-position-parameter
               (selected-frame)
               (car (nth next conf)))
              (setq cur next)))))))
例えば F12 を連打すると保存してある設定(位置とサイズ)を順番に適用します。
(設定の保存は frange:regist-frame-position-parameter-interactive )
(define-key global-map [f12]
  (frange:cycle-arrange-config-gen))

それと minor-mode-alist への登録を行なうコードがなかったので、追加しました。
(frame-arrange-mode が実行されていると、モードラインに frange と表示される)

余談

let じゃなくて lexical-let で囲まないとってのを、やっぱり忘れてハマります。
あー、あと rlet1, if-let1, let1 がデフォルトで欲しいですね。Emacs Lisp。

入門 GNU Emacs 第3版

2011/01/25

frame-arrange.el を更新しました(サイズのインクリメント、設定のシリアライズ)

サイズ

サイズをインタラクティブに変更する
  • frange:increment-size/current-frame
  • frange:decrement-size/current-frame
という関数を追加してあります。
好みのキーに割り当てるなどして使ってください。

increment される値は frange:size-incremental-value を書き換える(setq する)ことで変更できます。

frame-arrange.el の関数名はやたらと長いので、下記のように任意の名前の関数でラップしても良いかもしれません。
(setq frange:size-incremental-value 10)

(defun my-size-inc ()
  (interactive)
  (frange:increment-size/current-frame))

(defun my-size-dec ()
  (interactive)
  (frange:decrement-size/current-frame))

(define-key global-map (kbd "好みのキー") 'my-size-inc)
(define-key global-map (kbd "好みのキー") 'my-size-dec)

シリアライズ

シリアライズというか、alist をそのまま S 式としてファイルに読み書きするだけです。
下記のように呼び出すと、現在の位置とサイズに名前を付けて保存することができます。

(defun my-regist-frame ()
  (interactive)
  (frange:regist-frame-position-parameter-interactive))

(defun my-restore-frame ()
  (interactive)
  (frange:restore-frame-position-parameter-interactive))

(define-key global-map (kbd "好みのキー") 'my-regist-frame)
(define-key global-map (kbd "好みのキー") 'my-restore-frame)

保存先を変更する場合は frange:arrange-config-alist-file-name を setq してください。
保存した設定の削除は frange:remove-arrange-config-alist-entry で行なうことができます。

print

現在の状態を確認する関数も用意しました。
  • frange:print-arrange-config-names
  • frange:print-arrange-config-alist-entries
  • frange:print-frame-position-parameter/current-frame
M-x して呼び出すか、任意のキーに割り当てて使うことができます。

余談

略語を定義しなかったお陰で名前がすごく長くなって混乱しています。
たぶん結構バグがあると思うので、その都度直します。
何か気づいた点があったら @valvallow か blog のコメント欄などで教えて頂けると嬉しいです。

参考


追記

あとは保存した設定を cycle するようなのがあると良いかも。
-> 追加しました -> vallog: frame-arrange.el の保存してある設定を cycle する

追記2

M-down, M-up が空いてるなら割当てるのに調度良いかも。
(define-key global-map [(M down)] 'frange:increment-size/current-frame)
(define-key global-map [(M up)] 'frange:decrement-size/current-frame)

Emacsテクニックバイブル ~作業効率をカイゼンする200の技~

2011/01/24

Re:frame-arrange.el

現状ちょこちょこ書き換えたりしてるので、新しいのを持ってこないと動かないことがあるかもしれません。

key-chord.el を使わない場合の設定例

例えば下記の設定だと、C-c f q で左上端、C-c f c で右下端。
それと、C-Shift-矢印で矢印の方向にフレームを1ずつズラします。
(require 'frame-arrange)

;; key-map
(define-key global-map [(C shift down)]
  'frange:increment-position-top/current-frame)
(define-key global-map [(C shift up)]
  'frange:increment-position-bottom/current-frame)
(define-key global-map [(C shift left)]
  'frange:increment-position-right/current-frame)
(define-key global-map [(C shift right)]
  'frange:increment-position-left/current-frame)

(define-key global-map (kbd "C-c f q") 'frange:arrange/top-left-most/current-frame)
(define-key global-map (kbd "C-c f w") 'frange:arrange/top-most/current-frame)
(define-key global-map (kbd "C-c f e") 'frange:arrange/top-right-most/current-frame)
(define-key global-map (kbd "C-c f a") 'frange:arrange/left-most/current-frame)
(define-key global-map (kbd "C-c f d") 'frange:arrange/right-most/current-frame)
(define-key global-map (kbd "C-c f z") 'frange:arrange/bottom-left-most/current-frame)
(define-key global-map (kbd "C-c f x") 'frange:arrange/bottom-most/current-frame)
(define-key global-map (kbd "C-c f c") 'frange:arrange/bottom-right-most/current-frame)

マクロの使用例

上記の設定で、C-Shift-矢印では1ずつしかズレません。
下記のようにすると5ずつズラす関数が生成されます。

この場合生成される関数は、frange:arrange/increment-top5 と frange:arrange/increment-top5/current-frame です。
(def:frange/current-frame arrange/increment-top5
  (nil top #'(lambda (v frame)
               (+ v 5))))

(frange:arrange/increment-top5/current-frame)

例をもう一つ。
この場合、画面上部からの相対位置だけを指定する関数が生成されます。
生成される関数は、frange:arrange/top と frange:arrange/top/current-frame です。
(defun frange:identity (v frame)
  v)

(def:frange/current-frame arrange/top
  (top top #'frange:identity))

(frange:arrange/top/current-frame 3)

逆に画面下部からの相対位置だけを指定するのであればこんな感じ。
(def:frange/current-frame arrange/bottom-most
  (bottom top #'(lambda (v frame)
                  (- v))))

(frange:arrange/bottom-most/current-frame 15)
で、これを書いていて思ったのは、マクロの引数リストの第一要素・・・イラナイかもしれません。
マクロ自体も汚いので、そのうちごっそり修正するかもです。かも、です。

関数

マクロは関数呼び出しを行なう関数に名前をつけて生成しているだけなので、実はマクロ使わなくても関数使えばそれで済みます。

このように。
(frange:arrange/f (selected-frame)
                  (frange:arrange-partial-gen '(top left)'(0 0)))
(frange:arrange/alist (selected-frame) '((top . 30)))
(frange:arrange (selected-frame) :y 0)

で、結局最終的に Emacs 組み込みの set-frame-parameter を呼んでるだけです。

今後

実はフレームの位置とサイズに名前を付けて保存しておいて、あとで復元することが当初の目的でした。
位置やサイズをインタラクティブに動かしたり、マクロを書いたりというのは副産物です。

そのわりに、設定を書き出す機能は未実装です。
ということで、近いうちに設定をシリアライズできるようにします。

追記

設定のシリアライズ機能他を追加しました。

Emacsテクニックバイブル ~作業効率をカイゼンする200の技~

2011/01/22

キー操作で Emacs のフレーム位置やサイズを変更するマイナーモード frame-arrange.el を作りました

* 追記あります

C-c M (サンプルとして登録されているサイズ - 大きめ)

C-c m (サンプルとして登録されているサイズ - 小さめ)

qw 同時押し(左上端への移動 - 要 key-chord.el)

df 同時押し(右端への移動 -  要 key-chord.ell)

キー操作で、指定の位置に移動したり、位置やサイズを少しずつずらしたり、保存しておいた位置とサイズに復元したりできます。

ダウンロード

他に必要なものは、@podhmo さんの defmacro!.el 。

設定例

この例では、キーの同時押しにコマンドを割り当てる(例えば qw 同時押しに左上端に移動するコマンド)key-chord.el を使用しています。

また、C-Shift-矢印で矢印の方向にちびちび移動できます。
(require 'frame-arrange)
;; key-map
(define-key global-map [(C shift down)]
  'frange:increment-position-top/current-frame)
(define-key global-map [(C shift up)]
  'frange:increment-position-bottom/current-frame)
(define-key global-map [(C shift left)]
  'frange:increment-position-right/current-frame)
(define-key global-map [(C shift right)]
  'frange:increment-position-left/current-frame)

;; ;; (auto-install-from-emacswiki "key-chord.el")
;; (require 'key-chord nil t)
;; (setq key-chord-two-keys-delay 0.04)
;; (key-chord-mode 1)
(key-chord-define-global "qw" 'frange:arrange/top-left-most/current-frame)
(key-chord-define-global "we" 'frange:arrange/top-most/current-frame)
(key-chord-define-global "er" 'frange:arrange/top-right-most/current-frame)
(key-chord-define-global "as" 'frange:arrange/left-most/current-frame)
(key-chord-define-global "df" 'frange:arrange/right-most/current-frame)
(key-chord-define-global "zx" 'frange:arrange/bottom-left-most/current-frame)
(key-chord-define-global "xc" 'frange:arrange/bottom-most/current-frame)
(key-chord-define-global "cv" 'frange:arrange/bottom-right-most/current-frame)

(frange:regist-frame-position-parameter
 'example-min
 '((top . 20) (left . 70) (height . 30) (width . 110)))

(frange:regist-frame-position-parameter
 'example-max
 '((top + -4) (left + -4) (height . 35) (width . 126)))

(define-key global-map (kbd "C-c m")
  #'(lambda ()
      (interactive)
      (frange:restore-frame-position-parameter
       (selected-frame)
       'example-min)))

(define-key global-map (kbd "C-c M")
  #'(lambda ()
      (interactive)
      (frange:restore-frame-position-parameter
       (selected-frame)
       'example-max)))



デフォルトで用意されている機能

  • 右上端へ移動
  • 上端へ移動
  • 右上端へ移動
  • 左端へ移動
  • 右端へ移動
  • 左下端へ移動
  • 下端へ移動
  • 右下端へ移動
  • 上に1移動
  • 左に1移動
  • 右に1移動
  • 下に1移動
  • 現在の位置とサイズを取得
  • 現在の位置とサイズを名前をつけて保存
  • 保存した位置とサイズへ復元

frame-arrange.el に用意されている関数やマクロを使用すれば、任意の操作を実現する関数を定義及び生成することができます。

関数
  • frange:arrange/alist
  • frange:arrange/f
  • frange:arrange-partial-gen
  • frange:arrange
などを使って任意の移動ができます。

マクロ
  • def:frange
  • def:frange/current-frame
を使って任意の移動を行なう関数を生成することができます。
マクロはおまけみたいなものです。

フレームの移動やサイズ変更にはいろんな組み合わせがあるので、全部書くのが面倒でした。
欲しいものをマクロで生成できたら良いんじゃね?みたいな興味本位で書きました。

オレオレ仕様なので、どういうイメージで作ったかは以下のファイルをのぞいてみてください。
必ずしも同様のコードが生成されるわけではありませんので、あくまでイメージとして。

マクロの定義は frame-arrange.el の中にあります。
frame-arrange.el の最後の方で実際に使っているので、そこも参考になるかもしれません。

動機

frame-arrange.el を作った動機。

広い画面で Emacs を使っているとき、私は必ずしも最大化して使いません。
小さめのフレームサイズで使うことが少なくないのです。

Emacs と別のアプリやブラウザを並べて使ったりするのですが、Emacs が邪魔になったり、Emacs のサイズを変えたくなったときにわざわざマウスに手を伸ばすのが面倒でした。

Emacs の位置も毎回違うわけではなく、ブラウザと一緒のときはこの辺、IDE と一緒のときはこのくらいのサイズでこの辺、というのがある程度決まっていました。
なので、そういうことをしてくれる Emacs Lisp が欲しかったのですが、私が探した範囲では小さなコード片くらいしかなかったので自分用に作ることにしました。

Emacs Lisp で数十行以上のコードを書くのは初めてだったので面白かったです。
Scheme や Common Lisp とは結構違うので抵抗があったのですが、今ではなくなりました。
(でも名前空間はやっぱりちょっとアレですよね)

結果的に、コードは少し大袈裟になりましたが、マイナーモードとして公開してもよさそうな塊になった気がしたので公開してみることにしました。

参考


追記

マイナーモードとかライセンスとかよくわからないので、適当にコピペしたので、少し不安です。
何か不備(?)があったら教えてください。

追記2

上記設定例の場合の動作イメージ。
わかりやすく絵を描くのって難しいんですね。。

追記3

frange:initialize 関数が行方不明になってました。
gist のコードを修正しました。

追記4

いくつかバグ取りました。
byte-compileが通りませんでしたが、通るようになりました。

追記5

key-chord.el を使わない場合の設定例とかマクロの使い方とか書きました。

追記6

サイズのインクリメント/デクリメント関数追加、設定の永続化機能追加、バグの修正などを行ないました。

追記7

保存しておいた設定(位置とサイズ)を順番に切り替えて適用する機能を追加しました。
少し変更した設定例を載せました。

Emacsテクニックバイブル ~作業効率をカイゼンする200の技~

serversman(centos) に postgreSQL に Gauche-dbd-pg

会社では主に postgreSQL が使われているようです。

今までの仕事では SQL Server メインでした。
あとは MySQL を少し。

今のところ会社ではローカルに SQL Server を入れています。
せっかくなので ServersMan に postgreSQL を入れてみることにしました。

postgreSQL は当初 Lisp で書かれていたとかいないとか。
postgreSQL は Lisp でストアドが書けるとか書けないとか。
そういう話を聞いたことがありますが、まじですか?

postgreSQL

ここを参考に。

gauche-dbd-pg

Gauche-dbd-pg-0.2.1 は make でコケて入りませんでした。
trunk から持ってきたら、どうやらうまくいったみたいです。

$ gosh
gosh> (use dbi)
#<undef>
gosh> (use dbd.pg)
#<undef>
gosh> (let1 con (dbi-connect "dbi:pg:dbname=test")
        (values (dbi-open? con)
                (is-a? con <pg-connection>)
                (dbi-close con)
                (dbi-open? con)))
#t
#t
#<undef>
#f
gosh>

参考


プログラミングGauche

2011/01/20

Emacs の bookmark がもう少し便利だったら良いのに

Emacs の bookmark 機能をわりとよく使います。
でもデフォルトだと見た目もそっけないし、機能もそっけないです。

探してみたら、bookmark+.el というのと bookmark-extentions.el というのうのがあって、両方試してみました。
bookmark-extentions.el はコンパクトだけど、face の変更とかソートができるので、取りあえずこちらで良いかな。
これにタグ付けできる機能とかあれば良いんですが。
;; --- bookmark+ ---
;; (require 'bookmark+)

;; --- bookmark-extention ---
;; q : bmkext-bmenu-quit
;; j : bookmark-jump
;; o : bookmark-jump-other-window
;; t : bmkext-bmenu-toggle-marks
;; > : bmkext-bmenu-hide-unmarked
;; < : bmkext-bmenu-hide-marked
;; . :  bmkext-bmenu-show-all-bookmarks
;; E : bmkext-bmenu-edit-bookmark
;; F : bmkext-bmenu-list-only-file-bookmarks
;; I : bmkext-bmenu-list-only-info-bookmarks
;; B : bmkext-bmenu-list-only-non-file-bookmarks
;; O : bmkext-bmenu-list-only-last-org-bookmarks
;; S-V : bmkext-bmenu-sort-by-visit-frequency
;; S-T : bmkext-bmenu-sort-by-last-time-visited
;; S-S : bmkext-bmenu-sort-alphabetically
;; M-g : bmkext-bmenu-search
;; M-t : bookmark-bmenu-toggle-filenames
;; %m : bmkext-bmenu-regexp-mark

(require 'bookmark-extensions)
(set-face-foreground 'bmkext-local-directory
                     (face-foreground font-lock-function-name-face))
(set-face-background 'bmkext-local-directory
                     "black")
(set-face-foreground 'bmkext-local-file
                     (face-foreground font-lock-variable-name-face))

bookmark+.el は多機能っぽいんですが、使い方が把握できませんでした。

Emacsテクニックバイブル ~作業効率をカイゼンする200の技~

カラムのコメントを取得する(mssql)


ここにコメント書いておけば、簡単なテーブル定義書出せるんじゃね?


declare @tablename varchar (30)
set @tablename = 'employee'

select
  cols.column_id as col_id
  ,left(cols.name, 20) as col_name
  ,left(types.name, 15) as type_name
  ,cols.max_length as col_length
  ,(case cols.is_nullable
    when 0 then 'no'
    when 1 then 'yes'
    else 'nothing'
    end) as nullable
  ,left(cast(ext.value as varchar), 50) as comment
from
  sys.columns as cols
left outer join
  (select
    name
    ,types.system_type_id
  from
    sys.types as types
  where
    is_user_defined = 0
  group by
    types.system_type_id
    ,types.name) as types
on
  types.system_type_id = cols.system_type_id
left join
  sys.objects as obj
on
  obj.object_id = cols.object_id
left join
  sys.extended_properties as ext
on
  cols.object_id = ext.major_id
and
  cols.column_id = ext.minor_id
where
  obj.name like @tablename
order by
  column_id
go

sp_tables
sp_columns
sp_pkeys
sp_fkeys

参考


SQLパズル 第2版 プログラミングが変わる書き方/考え方

Re:Emacs でインタラクティブに SQL する

書き換えたので再掲。
  • sqlcmd を使ってるつもりが、osql だったので sqlcmd に
  • ちゃんと追求してないけど、2度目以降の run-mssql で sql-ms-options がおかしくなるので場当たり的な対応 reset/run-mssql 追加
  • sql-indent.el のインデントのための正規表現に join 系他を追加
  • hook を追加
あとは、改行する時に自動でインデントしてくれると嬉しいんだけどなぁ。。
それと、なぜか sql-indent-buffer, sql-indent-region するとインデントがなくなる・・・。
;; C-c C-c : 'sql-send-paragraph
;; C-c C-r : 'sql-send-region
;; C-c C-s : 'sql-send-string
;; C-c C-b : 'sql-send-buffer
(require 'sql)

;; starting SQL mode loading sql-indent / sql-complete
(eval-after-load "sql"
  '(progn
     (load-library "sql-indent")))

(custom-set-variables
 `(sql-indent-first-column-regexp
   ,(concat "^\\s-*" (regexp-opt
                      '("select" "update" "insert" "delete"
                        "union" "intersect"
                        "from" "where" "into" "group" "having" "order by"
                        "set"
                        "create" "drop" "truncate"
                        "left join" "right join" "inner join"  "cross join" "on"
                        "left outer join" "right outer join" "inner join"
                        "begin" "rollback" "commit"
                        "and" "or"
                        "go"
                        "--")
                      t)
            "\\(\\b\\|\\s-\\)")))

(setq auto-mode-alist
      (cons '("\\.sql$" . sql-mode) auto-mode-alist))
(sql-set-product-feature
 'ms :font-lock 'sql-mode-ms-font-lock-keywords)

(custom-set-variables
 '(sql-ms-program "sqlcmd"))
(custom-set-variables
 '(sql-ms-options  '("-U" "-P" "-S" "-d")))

(sql-set-product-feature
 'ms :sql-program 'sql-ms-program)
(sql-set-product-feature
 'ms :sqli-prompt-regexp "^[0-9]*>")
(sql-set-product-feature
 'ms :sqli-prompt-length 5)
(sql-set-product-feature
 'ms :sqli-login 'sql-ms-login-params)
(sql-set-product-feature
 'ms :sqli-connect 'sql-connect-ms)

(add-hook 'sql-mode-hook
          #'(lambda ()
              (setq sql-indent-offset 2)
              (setq sql-indent-maybe-tab t)
              (local-set-key "\C-cu" 'sql-to-update)
              (setq sql-pop-to-buffer-after-send-region nil)))
(add-hook 'sql-interactive-mode-hook
          #'(lambda ()
              (set-buffer-process-coding-system 'sjis-unix 'sjis-unix )
              (setq show-trailing-whitespace nil)
              (setq comint-buffer-maximum-size 500)
              (setq comint-input-autoexpand t)
              (setq comint-output-filter-functions
                    'comint-truncate-buffer)))

(defun sql-connect-ms ()
  (let ((login-params (mapcar #'(lambda (e)
                                  (symbol-value (symb 'sql- e)))
                              sql-ms-login-params)))
    (let* ((options (mapcar* #'cons
                             sql-ms-options
                             login-params))
           (params (fold-right
                    #'(lambda (e acc)
                        (if (cdr e)
                            (append (list (car e)(cdr e))
                                    acc)
                          acc))
                    nil options)))
      ;; (setq sql-ms-options (append params (list "-W")))
      (setq sql-ms-options params)
      (sql-connect-1 sql-ms-program sql-ms-options))))

(defun run-mssql ()
  (interactive)
  (sql-product-interactive 'ms))

(defvar backup:sql-ms-options sql-ms-options)
(defvar backup:sql-ms-login-params sql-ms-login-params)

(defun sql:reset-parameters ()
  (interactive)
  (setq sql-ms-options backup:sql-ms-options)
  (setq sql-ms-login-params backup:sql-ms-login-params)
  (setq sql-user nil)
  (setq sql-password nil)
  (setq sql-server nil)
  (setq sql-database))

(defun reset/run-mssql ()
  (interactive)
  (sql:reset-parameters)
  (run-mssql))

他に必要なもの

(defun fold (kons knil ls &rest more)
  (do ((ls ls (cdr ls)) (more more (mapcar #'cdr more))
       (knil knil (apply
                   kons
                   (apply #'list (car ls) (append (mapcar #'car more) (list knil))))))
      ((null ls) knil)))

(defun fold-right (kons knil ls &rest more)
  (apply #'fold kons knil (reverse ls) (mapcar #'reverse more)))

(defun mkstr (&rest args)
  (with-output-to-string
    (dolist (a args) (princ a))))

参考


SQL Hacks ―データベースを自由自在に操るテクニック

2011/01/18

frame-arrange.el にしようと思っているもの

Emacs のフレームの位置やサイズをキー操作で変更したかったので、Emacs Lisp の練習がてら書いてみました。
取りあえずロードすれば使えるので、貼っておきます。

オレオレ仕様のマクロもありますので、一見して使い方がわからないと思います。
後日、マイナーモードかメジャーモードにできそうならしたいと思っているので、使い方はその時に書きたいと思います。
マイナーモードもメジャーモードもよくわかってないので、しばらくかかるかもしれません。

@podhmo さんの defmacro!.el をお借りしているので、ロードパスの通ったところに置いておく必要があります。
また、frange:foldl の定義はこちらの fold の定義を拝借しました(していいのか?)。

簡単に使い方を書きます。
例えば、現在の frame-arrange.el の最後の方で定義されている下記のコード。
(def:frange/current-frame arrange/bottom-right-most
  (nil top frange:-1)
  (nil left frange:-1))
からは2つの関数定義が生成されるのですが、そのうちの一つを下記のように呼び出すと Emacs のフレームが右下隅に移動すると思います。
(frange:arrange/bottom-right-most/current-frame)

また、
(frange:increment-position-left/current-frame) 
と呼び出すとフレームが右に少し動く、といった具合です。

あとは、登録しておいたサイズを復元できます。
(ホントはこれがメイン。。)
(frange:restore-frame-position-parameter (selected-frame) 'example-1)
(frange:restore-frame-position-parameter (selected-frame) 'example-2)
を交互に実行すると、フレームのサイズが変わると思います。


入門 GNU Emacs 第3版

2011/01/14

Emacs: モードラインじゃなくタイトルバーに日付と時間を表示する


小ネタ。
日付と時間は表示したいけど、モードラインに表示するのは何かと邪魔ですよね。

tittle-time.el は auto-install-from-emacswiki から。
(defadvice title-time-set (around title-time-set-around)
  (setq frame-title-format
      (concat "%b" " - "  display-time-string)))

(ad-activate 'title-time-set)
(setq display-time-interval 30)

(setq display-time-string-forms
      '((format " [ %s/%02d/%02d (%s) - %s:%s ] "
                year (string-to-number month)(string-to-number day)
                dayname 24-hours minutes)))

(require 'title-time)
(display-time)

Emacsテクニックバイブル ~作業効率をカイゼンする200の技~

2011/01/12

RDB Design Patterns : 「リレーショナルデータベースのデザインパターン」ってないの?

プログラマのためのSQL 第2版

データベースやテーブル設計にもデザインパターン集とかあってもよくね?と思って検索したら、Stack Overflow にスレッドがありました。
メモがてら。

リファクタリング―プログラムの体質改善テクニック」のマーティン・ファウラー先生はデータベースのことも書いてらっしゃるんですね。

この本が評判良いの?
これが和訳?
作者のところに名前はないけど、原書の最後の(Flowler)ってマーティン・ファウラー先生のこと?


他のスレッドに出てた本
  1. SQL Design Patterns: Expert Guide to SQL Programming (It in-Focus Series)
  2. Data Model Patterns: Conventions of Thought
  3. Data Model Patterns: A Metadata Map (The Morgan Kaufmann Series in Data Management Systems)
  4. Joe Celko's SQL Programming Style (The Morgan Kaufmann Series in Data Management Systems)
  5. Data Modeling Essentials, Third Edition (The Morgan Kaufmann Series in Data Management Systems)
  6. Applied Mathematics for Database Professionals (Expert's Voice)
どれも重そうだー。1の本とかタイトルからしてモロ。4の本も内容が気になる。

ウェブサイト

さっきの本の。

ER 図たくさん。正直、よくわからん。

これはデータベース初級者から上級者への道的な何か?

これはまさにデータベースデザインパターン?

わからん。けど取りあえずそれっぽいものを。

プログラマのためのSQL第四版

プログラマのためのSQL 第2版」は本屋でもよく見かけますね。ぶ厚いやつですよね。これって、第二版なのか。第三版、第四版は翻訳されないんでしょうか。
この辺りって、日本語の情報が少なくないですか?誰か和訳たのむ。。

ER図エディタ


Refactoring Databases: Evolutionary Database Design (Addison-Wesley Signature Series (Fowler))データベース・リファクタリング

2011/01/11

Emacs でインタラクティブに SQL する (Microsoft SQL Server 2005 編)


下記の設定は Microsoft SQL Server ですが、少し書き換えれば他の RDB でも使えるはずです。
今回対象にしたのは, SQL Server 2005 です。

必要なものは
auto-install で入りました。なかなか便利になりました。
Management Studio は重苦しいので少し不満でした。Emacs キーバインドになりそうもありませんし。Enterprise Manager の軽さが懐かしいです。

以下設定。

.emacs

;; C-c C-c : 'sql-send-paragraph
;; C-c C-r : 'sql-send-region
;; C-c C-s : 'sql-send-string
;; C-c C-b : 'sql-send-buffer
(require 'sql)

(add-hook 'sql-interactive-mode-hook
          #'(lambda ()
              (interactive)
              (set-buffer-process-coding-system 'sjis-unix 'sjis-unix )
              (setq show-trailing-whitespace nil)))

;; starting SQL mode loading sql-indent / sql-complete
(eval-after-load "sql"
  '(progn
     (load-library "sql-indent")
     (load-library "sql-complete")
     (load-library "sql-transform")))

(setq auto-mode-alist
      (cons '("\\.sql$" . sql-mode) auto-mode-alist))

(sql-set-product-feature
 'ms :font-lock 'sql-mode-ms-font-lock-keywords)

(defcustom sql-ms-program "sqlcmd"
  "Command to start sqlcmd by SQL Server."
  :type 'file
  :group 'SQL)

(sql-set-product-feature
 'ms :sql-program 'sql-ms-program)
(sql-set-product-feature
 'ms :sqli-prompt-regexp "^[0-9]*>")
(sql-set-product-feature
 'ms :sqli-prompt-length 5)

(defcustom sql-ms-login-params
  '(user password server database)
  "Login parameters to needed to connect to mssql."
  :type '(repeat (choice
                  (const user)
                  (const password)
                  (const server)
                  (const database)))
  :group 'SQL)

(defcustom sql-ms-options '("-U" "-P" "-S" "-d")
  "List of additional options for `sql-ms-program'."
  :type '(repeat string)
  :group 'SQL)

(defun sql-connect-ms ()
  "Connect ti SQL Server DB in a comint buffer."
  ;; Do something with `sql-user', `sql-password',
  ;; `sql-database', and `sql-server'.
  (let ((f #'(lambda (op val)
               (unless (string= "" val)
                 (setq sql-ms-options
                       (append (list op val) sql-ms-options)))))
        (params `(("-U" . ,sql-user)("-P" . ,sql-password)
                  ("-S" . ,sql-server)("-d" . ,sql-database))))
    (dolist (pair params)
      (funcall f (car pair)(cdr pair)))
    (sql-connect-1 sql-ms-program sql-ms-options)))

(sql-set-product-feature
 'ms :sqli-login 'sql-ms-login-params)
(sql-set-product-feature
 'ms :sqli-connect 'sql-connect-ms)

(defun run-mssql ()
  "Run mssql by SQL Server as an inferior process."
  (interactive)
  (sql-product-interactive 'ms))


初めは osql を使おうとしていたのですが、クエリを投げたあと戻ってきませんでした。。
osql をやめて sqlcmd に変えたらうまく動いたみたいです。

SQL Server の設定


画像のデータは定番の pubs のデータです。

osql, sqlcmd

osql, sqlcmd を単体で使う場合。
>osql -U username -S servername
>osql -U usename -S servername -d pubs -i test.sql
sqlcmd も同様。

Emacs version

Emacs のバージョンは (emacs-version) してみたら
"GNU Emacs 24.0.50.1 (i386-mingw-nt5.1.2600)
of 2010-07-02 on YAMALOK"
でした。

追記

sqli-prompt-regexp のとこと、sql-connect-ms を少し書き換えました。

プログラマのためのSQL 第2版

Emacs: 自分用かるふわ face (calfw.el, calfw-ical.el)

dark 系なので、自分用に変更してみました。
自分の quack.el の face を参考にしました。
(require 'japanese-holidays)
(setq calendar-holidays
      (append japanese-holidays local-holidays other-holidays))
(setq calendar-weekend-marker 'diary)
(add-hook 'today-visible-calendar-hook 'calendar-mark-weekend)
(add-hook 'today-invisible-calendar-hook 'calendar-mark-weekend)


;; --- calfw ---

;; (cfw:open-calendar-buffer)
;; (cfw:contents-debug-data)

;; face
(custom-set-faces
 '(cfw:face-title ((t (:foreground "darkgoldenrod3" :weight bold :height 2.0 :inherit variable-pitch))))
 '(cfw:face-header ((t (:foreground "maroon2" :weight bold))))
 '(cfw:face-sunday ((t :foreground "red" :weight bold)))
 '(cfw:face-saturday ((t :foreground "blue" :weight bold)))
 '(cfw:face-holiday ((t :background "grey10" :foreground "purple" :weight bold)))
 '(cfw:face-default-content ((t :foreground "green2")))
 '(cfw:face-regions ((t :foreground "cyan")))
 '(cfw:face-day-title ((t :background "grey10")))
 '(cfw:face-today-title ((t :background "red4" :weight bold)))
 '(cfw:face-today ((t :foreground: "cyan" :weight bold)))
 '(cfw:face-select ((t :background "blue4")))
;;  '(cfw:face-grid ((t :foreground "DarkGrey")))
;;  '(cfw:face-default-day ((t :weight bold :inherit cfw:face-day-title)))
;;  '(cfw:face-annotation ((t :foreground "RosyBrown" :inherit cfw:face-day-title)))
 )

(require 'calfw)
(require 'calfw-ical)
(defvar cfw:ical-url '("http://www.google.com/calendar/ical/---hoge---/basic.ics"))
(setq cfw:ical-calendar-contents-sources cfw:ical-url)
;; (setq cfw:ical-calendar-annotations-sources cfw:ical-url)
(cfw:install-ical-schedules)
;; (setq calendar-month-name-array
;;       ["January" "February" "March"     "April"   "May"      "June"
;;        "July"    "August"   "September" "October" "November" "December"])
;; (setq calendar-day-name-array
;;       ["Sunday" "Monday" "Tuesday" "Wednesday" "Thursday" "Friday" "Saturday"])
;; (setq calendar-week-start-day 0)

入門 GNU Emacs 第3版

継続の実装方針

継続の実装は、何を重視するかでかなり違ってくるせいでしょうね。

full continuationの実装は、スタックエリアのコピーという観点
から見ると、次のように分類されます。

(1) 継続作成時にスタックからヒープへのコピーを行い、
継続呼び出し時にヒープからスタックへのコピーを行う

(2) 継続作成時にスタックからヒープへのコピーを行うが、
継続呼び出し時にはコピーを行わない

(3) 継続作成時にはコピーを行わず、
継続呼び出し時にコピーを行う

(4) 継続作成時にも継続呼び出し時にもコピーは行わない

guileやSCMは(1)のタイプです。このタイプは、CとSchemeの
スタックが自由にインターリーブできるのが特徴です(Scheme
ルーチンから呼んだCルーチンからさらにSchemeルーチンを
簡単に呼べる)。したがってC APIが単純になります。また、
スタックエリアのGCを必要としません。しかしコピーの回数が
多いため、継続は非常に重くなります。
SCMよりguileがかなり重いのは何故だかわかりません。

Gaucheは(2)の方法を利用しています。(1)と同様にスタック
エリアのGCが不要で、コピーの回数が少ないのが特徴です。
しかし、呼ばれない継続でも作られる時点でコピーする必要が
あるのであまり良い方法ではないです。将来、スタックエリア
のGCを実装できたら(3)か(4)に移りたいと考えています。

(3)はChez Schemeへの実装の論文があります。Petite Chez
Schemeで使われているかどうかは知りませんが、おそらく
使われているんではないでしょうか。スタックエリアのGCと、
スタックアンダーフローを検出する一種のバリアが必要です。
継続の作成はほぼノーコストです。継続の呼び出しには若干の
オーバヘッドがあります。

(4)は実装技術的にはさらに2つに分かれます。継続を全て
ヒープアロケートする方法と、スタックフレームをポップしない
方法です。完全なcontinuation passing styleなので、
継続の作成、起動ともに理論上ノーコストでできる方法です。
しかし、継続を全てヒープアロケートするのはメモリアクセスの
ローカリティが悪く、最近のCPUでは不利になります。
Chickenは後者の方法 (ポップしないスタックフレーム)を使って
います。理屈の上ではこれが一番良い方法のはずですが、スタック
エリアのGC回数が(3)よりずっと多くなるため、総合的な性能で
比較すると微妙なところです。

--shiro


プログラミングGauche

2011/01/08

windows(cygwin) + emacs + tramp + ssh(plink)

気軽に導入を試みたらハマったのでメモ。

何ができるのか

emacs で普段通り C-x C-f で下記のように
/ssh:[email protected]#22:~/.emacs
とか
/plink:[email protected]#22:~/cap/dev/js/hello.js
というように入力すると、ssh で入って編集するようなサーバのファイルを手元の emacs からローカルファイルを扱うかのように編集できたりします。
  • ファイルの編集
  • ディレクトリを開く
  • ローカルファイルをサーバへコピーする
など、たいていのことはできそうです。
めちゃくちゃ便利ですねコレ。。

これまで TeraTerm を使っていましたが、今後出番が減りそうです。

インストール

現時点(2011/01/08)で最新の tramp-2.2.0.tar.gz を cygwin の bash で make するとコケるみたいです。
複数のバージョンを試してみましたが、tramp-2.1.19.tar.gz(tramp-2.1.9.tar.gz ではない)でうまくいきました。
の download から落として展開したディレクトリで
$ LANG=C ./configure --prefix=/cygdrive/c/emacs/tramp --with-emacs=/cygdrive/c/emacs/bin/emacs --with-lispdir=/cygdrive/c/emacs/site-lisp/tramp
$ LANG=C make
$ make install
で完了。
prefix とか lispdir はお好みで。

plink は putty から windows 用の最新のバイナリを落としてインストールすれば OK です。

Emacs

私の場合。
(prefer-coding-system 'utf-8-unix)
(modify-coding-system-alist 'process "plink" 'utf-8-unix)

(setenv "PATH"
        (apply #'concat
               `(,@(intersperse ";" (expand-file-names
                                     "~/../Program Files/PuTTY"
                                     "~/../Program Files/PuTTY"
                                     "~/../Program Files/PuTTY"
                                     "~/../Program Files/PuTTY"
                                     "~/../cygwin/usr/local/bin"
                                     "~/../cygwin/usr/bin"
                                     "~/../cygwin/bin"))
                 ,(getenv "PATH"))))

(require 'tramp)
(setq tramp-debug-buffer t)
(setq tramp-completion-without-shell-p t)
(setq tramp-shell-prompt-pattern "^[ $]+")

(defvar tramp-ssh-ppk (expand-file-name "~/.ssh/private-key.ppk"))
(defvar tramp-serversman `("serversman"
                           (tramp-login-program "plink")
                           (tramp-login-args (("%h")
                                              ("-l" "%u")
                                              ("-P" "%p")
                                              ("-ssh")
                                              ("-i" ,tramp-ssh-ppk)))
                           (tramp-remote-sh "/bin/sh")
                           (tramp-copy-program nil)
                           (tramp-copy-args nil)
                           (tramp-copy-keep-date nil)
                           (tramp-password-end-of-line "xy")
                           (tramp-default-port 22)))

(add-to-list 'tramp-methods tramp-serversman)

家ではもっぱら serversman に接続するのですが、会社でも使いたいので tramp-methods にそれぞれの設定を追加しました。上記の設定は serversman のものだけです。

よって使い方もこのようになります。
C-x C-f
/serversman:[email protected]#22:~/cap/dev/js/hello.js
ポートの指定の仕方がわからず四苦ハックしました。。
[email protected]#22 の「#」以降に指定すれば OK です。
デフォルトの設定で 22 にしてあるようなので、特に指定がなければ [email protected] だけでも可。

補足1

ppk ファイルは秘密鍵を plink と同じディレクトリにある puttygen に通せば生成できます。

補足2

expand-file-names, intersperse は私的に定義しているものなので、上記の設定をそのままコピペしても動きません。
一応貼っておきます。。
(defun expand-file-names (&rest rpaths)
  (mapcar #'(lambda (rpath)
             (expand-file-name rpath))
          rpaths))

(defun pair-fold1 (proc seed ls)
  (loop
     for e on ls by #'cdr
     for acc = (funcall proc ls seed)
     then (funcall proc e acc)
     finally (return acc)))

(defun single? (ls)
  (and (not (null ls))
       (null (cdr ls))))

(defun intersperse (item ls)
  (pair-fold1 #'(lambda (pr acc)
                  (if (single? pr)
                      (cons (car pr) acc)
                      (cons item (cons (car pr) acc))))
              '() (reverse ls)))

蛇足

plink 自体はこんな感じで使えました。
plink -ssh -P port -i private-key.ppk [email protected]

参考

Emacsテクニックバイブル ~作業効率をカイゼンする200の技~