ラベル emacs の投稿を表示しています。 すべての投稿を表示
ラベル emacs の投稿を表示しています。 すべての投稿を表示

2009年12月8日火曜日

emacsのライブラリパッケージ取扱方針

多少調査したので、見えてきた。次の方針がよいように思う。

  • Ubuntu(Debian)のElispパッケージを採用する。(debian-emacs-policy)

    • 依存関係も管理しているので安心。
    • インストール/アンインストールも統一的。
    • ただし、パッケージをつくる手間は結構ある。

  • 補完的に、Auto Installを採用する。

    • Ubuntu(Debian)のElispで提供されていないものは、Auto InstallにてElispAreaなどから採用する。
    • パッケージ化の手間がないので、アジャイルにライブラリの導入ができる。

  • Auto Install -> Ubuntu(Debian)

    • Auto Installにて導入したライブラリが、有用であり安定しているならば、パッケージ化のプロセスに入る。

      • まず、Auto Install上での安定。依存関係があるなら、Auto Install上でbatch定義する。また、ライブラリのリビジョンを止めるために、ElispAreaではなく、ローカルに落として止めたリビジョンのみを見るなど。
      • 次に、debian-emacs-policyに準拠したdebian packageを作成する。これをプライベートリポジトリに置き運用する。
      • 最後に、debianパッケージメンテナ等に依頼して、公式リポジトリにアップロードしてもらう。



こつこつ。

debian-emacs-policyとXEmacs package systemの関係


* debian-emacs-policyとXEmacs package systemの関係
- debianのパッケージにXEmacs package systemのパッケージあり
- xemacs21-basesupport
- xemacs binary packages
- xemacs21-basesupport-el
- xemacs source packages

- ここにXEmacs package system公式提供のものはすべ
て入っているようだ。
- debian-emacs-policyに従ったpackagesと、XEmacs
package systemのpackageの両方に含まれているpackage
がけっこうある。
- どうやら、御互い無関係にやっているようだ。
- ユーザ自身が、どちらのパッケージシステムでいく
かの判断をしなければならない。


こつこつ。

XEmacs package system

XEmacs、ほぼ初めていじったといってよいのですが、このpackage systemは結構ちゃんとしていてびっくりです。依存関係管理を装備すれば、完備かと。

うーん。GNU Emacsにもこういうものが欲しい。。。


* XEmacs package system
- パッケージの置き場所
- パッケージの置き場所は、file system上のpathで
系統づけている。その系統を'パッケージ階層'と呼
ぶ。デフォルトでは3つの系統がある。
- startupの際に、パッケージ階層をXEmacsは見るこ
とができる。load-pathにする、ということではな
いようだ。M-x describe-installationでpackage
pathの値をみることができる。
- パッケージ階層 (package hierarchies)
- Local and 3rd party packages go here:
- $prefix/lib/xemacs/site-packages
- Only searched by MULE-enabled XEmacsen:
- $prefix/lib/xemacs/mule-packages
- Normal packages go here:
- $prefix/lib/xemacs/xemacs-packages
- Infodock development environments
- $prefix/lib/xemacs/infodock-packages

- $prefixはconfigure scriptに渡したパラメータ。
- 典型的には'/usr/local/'。
- ユーザのパッケージ階層
- '.xemacs/'配下
に、'site-packages'、'xemacs-packages'、
'mule-packages'ディレクトリをつくると、認識
される。
- パッケージ階層とload-path
- パッケージ階層達の優先度はXEmacsのコンパイ
ル時に指定する。
- 前項の指定順にしたがって、パッケージ階層を
調べて、load-pathを構成する。

- パッケージ
- バイナリパッケージとソースパッケージがある。
- ソースパッケージからバイナリパッケージを生成
する。'バイナリ'と言うが、実際はバイトコード
(コンパイルされたelispファイル)。

- バイナリパッケージアーカイブ
- XEmacs公式
- Official XEmacs Packages:
- XEmacs開発者によってテスト済み。
These packages have received testing from XEmacs developers and bleeding-edge users
and are available as documented in our Release Notice Archive.
- Pre-Release XEmacs Packages:
- テスト中またはテスト待ちのパッケージ。
- アーカイブではなく、パケージ個別に独立管理し
ているもの
- http://www.xemacs.org/Download/elispPackages.html
- ただし、このリストにあるもので、XEmacs
packagesに含まれることもあるとのこと。なん
のこっちゃ。
- http://ftp.xemacs.org/pub/packages/
- 130前後のパッケージあり。

- ソースパッケージリポジトリ
- XEmacs CVSリポジトリの一部。次の構造。

<repo-root>/
packages/
Makefile
iterate.rules
meta-iterate.rules
XEmacs.rules
Local.rules
Local.rules.template
Local.rules.mk
Local.rules.inc
package-compile.el
xemacs-packages/
Makefile
pkg-A-name/
pkg-B-name/
...
mule-packages/
Makefile
pkg-1-name/
pkg-2-name/
...
- 再帰的makeによって、パッケージ全体をビルドす
るようだ。

- パッケージの作法
- パッケージのflavor
- 2つのflavorがある。
- Regular Packages
- elispファイル達総体として機能をなすもの。
- 部分的に削除すると、機能しなくなる。
- Single-File Packages
- 個別elispファイルで機能するもの。そういっ
たものを共通テーマでくくったもの。
- 部分的に削除しても残りのものは機能する。
- ファイル名
- pkgname--pkg.tar.gz
- バイナリパッケージの中身の構成

_pkg.el
auto-autoloads.el
custom-load.el
ChangeLog
lib/pkgname/
lib-src/pkgname/
etc/pkgname/
info/
lisp/maybe-pkgname/
man/maybe-pkgname/
pkginfo/MANIFEST.pkgname

- _pkg.el
- パッケージ管理システム向け情報。
- auto-autoloads.el
- autoloadを中心に、pkgを使う(使えるように
する)ための設定を含む。
- custom-load.el
- customに対する設定を含む。
- pkginfo/MANIFEST.pkgname
- インストール対象ファイルの一覧を含む。

- ソースパッケージの構成
- バイナリパッケージの '_pkg.el' 、
'auto-autoloads.el'、'custom-load.el' は生
成物。そのかわりに、次のものがある。

Makefile
package-info.in

- 制御ファイル (Control Files)
- ソースとバイナリにまたがって、制御系のファ
イル達のことを制御ファイルと呼ぶ。具体的に
は、次のとおり。

Makefile
package-info.in
_pkg.el
auto-autoloads.el
custom-load.el

- インストール
- 基本的にはパッケージ階層のトップにてuntarする
だけ。
- elispによるインストールフロントエンドもあり。

- アンインストール
- 関数:package-admin-delete-binary-packageにて
削除可能。

- 依存関係
- 依存関係を扱う機構は無い。

こつこつ。

2009年12月7日月曜日

Auto Install

現在自分が使用しているRev.1.18を読んでみた。
印象は、EmacsWikiのElispAreaインターフェイス。


* Auto Install
- ソースがきれい。ちゃんとしている雰囲気。
** パッケージの取得先
- auto-install-emacswiki-base-url
- "http://www.emacswiki.org/cgi-bin/wiki/download/"
- auto-install-gist-base-url
- "http://gist.github.com/"
- auto-install-filter-url
- '(("color-grep" "http://www.bookshelf.jp/elc/"))
- auto-install-batch-list
- バッチインストールのためのパッケージ情報。
** パッケージのデフォルト保存場所
- auto-install-directory
- "~/.emacs.d/auto-install/"
- 新規に導入するelispファイルの置き場所。
** 基本的な動作
- emacswikiのelisp areaをelispの主たるアーカイブと
位置付けている。副次的なものとして、gist、
filter-urlがある。
- elisp areaから、'.el'ファイルの一覧を取得し、こ
れを取扱い可能ライブラリの名前として利用する。
- 基本動作としては、この名前でライブラリを指定し
て、ダウンロード-中身確認-採用-配置となる。
- ライブラリの指定は、mini-bufferで指定する方法と、
既存のelispをdired上で指定する方法の二種類がある。
- 配置場所も二種類ある。すでにそのライブラリが
load-path上に存在するなら、それへの上書き配置が
可能である。load-path上に存在しないなら、
auto-install-directory内に配置される。
- 依存関係を自動処理する方法は無いようだ。
- ただし、複数ファイルで構成されるライブラリについ
ては、auto-install-batch-listにて明示的にelisp
ファイルのグループをつくることによって、一括イ
ンストールが可能。

あとはXEmacsのPackage Systemだ。
こつこつ。

2009年12月5日土曜日

ELPA (Emacs Lisp Package Archive)


* ELPA (Emacs Lisp Package Archive)
- 次の2つのファイルがパッケージ一覧の基本情報。
package-list-packagesを呼ぶと、
package-refresh-contentsによってWebから取得され
る。
- http://tromey.com/elpa/archive-contents
- これがELPA提供のパッケージの一覧を含むファ
イル。依存関係も記述されている。
- 104個のパッケージを含む。
- http://tromey.com/elpa/builtin-packages
- Emacs組込パッケージと衝突しているものについ
て、整理情報を記述。22.0用と23.0用が含まれ
ている。
- バージョンを考慮した依存関係管理をしている。
- パッケージの様式
- <package-user-dir>/<NAME-VERSION>/にそれぞれのパッ
ケージをダウンロードする。
- .el
- ELPA上では'NAME-VERSION.el'というファイル名
をもつ。
- DLすると、'NAME-VERSION'というディレクト
リに'NAME.el'というファイル名で格納する。
- .tar
- "PACKAGE-pkg.el"を含まなければならない。
- このファイルの中では、define-packageが
呼ばれている。
- define-package
- パッケージを定義して、package-alistにパッケー
ジ情報を格納する関数。


こつこつ。

Emacs Lisp List


* Emacs Lisp List
- http://www.damtp.cam.ac.uk/user/sje30/emacs/ell.html
- さて、前回ell.elをローダと書いたが、ローダでは
なかった。
- これは、ell.xmlをemacsのbufferにきれいに表示す
るものだ。いくつか機能を提供している。
- 著者名によるソート機能。
- ell.xmlに更新があった場合、更新項目に"<new>"
をつける。
- すでに導入済みのライブラリについては、項目の頭
に"*"をつける。
- ちなみに、Emacsではelispを含んだファイルをお
しなべてライブラリと呼ぶ。
- avltree
- ell.xmlをパースしてavltreeにする。
- 作成したavltreeは'~/.ell-last-read'にファイル
として保持して差分確認にも利用する。


こつこつ。

2009年12月4日金曜日

Emacsのパッケージング事情

debian emacs policyを理解できてきたところで、他のパッケージ管理機構についてざっと調べてみた。結構いろいろな情報がある。

何かひとつをちゃんと知るということは、やっぱり大変なことだなぁと再認識した。


* Emacsのパッケージング事情
** ヘッダ等の慣習
*** Conventional Headers for Emacs Libraries
- http://www.gnu.org/software/emacs/manual/html_node/elisp/Library-Headers.html#Library-Headers
- GNU Emacs Lisp Referenceの一部。
- Elispファイルを書くときの慣習。
- ライブラリのメタデータ(著者等)をコメントとして
記述するための慣習。
- ライブラリの中身をコメントで構造化するための慣習。
- 例:メタデータ

;;; lisp-mnt.el --- minor mode for Emacs Lisp maintainers

;; Copyright (C) 1992 Free Software Foundation, Inc.

;; Author: Eric S. Raymond <esr@snark.thyrsus.com>
;; Maintainer: Eric S. Raymond <esr@snark.thyrsus.com>
;; Created: 14 Jul 1992
;; Version: 1.2
;; Keywords: docs

;; This file is part of GNU Emacs.
...
;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.

ここに本体コード。

;;; filename --- description

- 例:構造化コメント

;;; Commentary:
;;; Documentation:
;;; Change Log:
;;; Code:
;;; filename ends here

*** Elisp Area Conventions
- http://www.emacswiki.org/cgi-bin/wiki/ElispAreaConventions
- EmacsWikiのElisp Areaに置くelispのかきぶりの慣
習の説明。
- GNU Emacs Lispの慣習をベースにして、詳細化や拡
張を実施している。

** ヘッダツール
*** Automatic File Headers
- http://www.emacswiki.org/emacs/AutomaticFileHeaders
**** auto insert mode
- ユーザが定義したテンプレートにしたがって、ファイ
ル作成時にヘッダを自動的に挿入する。
auto-insert-alistでファイル名パターンとテンレプー
トを紐付ける。
**** header2.el
- Elisp Area Conventionsに対応したヘッダを自動挿入
や自動更新するelisp。
- そのライブラリが必要とするfeaturesを記述する欄を
設けている。(これは他のConventionsでは定義されて
いない)
- ;; Features that might be required by this library:
**** lib-requires.el
- ライブラリの依存情報を調査して、木構造をつくる
elisp。
**** elisp-depend.el
- elispファイルをparseして、そのelispで依存してい
るライブラリを探索し、それぞれについて、それが
providedならば、require式を出力し、そうでなけれ
ばautoload式を出力する。
**** checkdoc
- http://www.emacswiki.org/emacs/CheckDoc
- elispファイルのヘッダをチェックする。GNU慣習と
EmacsArea慣習の双方に対応している。

** パッケージ管理機構
*** Emacs Lisp List
- http://www.damtp.cam.ac.uk/user/sje30/emacs/ell.html
- http://www.damtp.cam.ac.uk/user/sje30/emacs/ell.xml
- http://www.damtp.cam.ac.uk/user/sje30/emacs/ell.el
- パッケージ一覧ファイル(ell.xml)とそれを参照する
ローダ(ell.el)を提供。
- ell.elではavltreeをつかってパッケージのキャッシュ
を作成し管理している。興味深い。

*** Auto Install
- http://www.emacswiki.org/emacs/AutoInstall
- フルセットのパッケージ管理が可能。
- パッケージの取得先はEmacsWiki他、いくつか指定可
能。
- パッケージの依存関係の管理などがどうなっている
のかは要調査。

*** ELPA
- http://tromey.com/elpa/
- パッケージアーカイブとそれを参照するローダを提
供。
- Web上の説明が簡素なため、理解するためには使って
みる必要がありそう。
- パッケージアーカイブの仕様を調べてみたい。

*** Install Lisp
- http://www.emacswiki.org/emacs/InstallElisp
- Auto Installの前身と考えてよさそう。

*** XEmacs package system
- http://www.xemacs.org/Documentation/packageGuide.html
- XEmacsはパッケージ管理機構を組み込みでもってい
る。専用のパッケージアーカイブも存在する。
- debian-emacs-policyとはどういう関係になるのだろ
う。
- 詳細は要調査。


こつこつ。

2009年12月1日火曜日

debian-emacs-policyのポイント (2)

perlを思い出しつつ、スクリプトを多少調べてみた。


* emacsen-commonのスクリプト
- debian-emacs-policyにある例を理解できない。それ
を理解したい。
- 例1

1) Xemacs21 and the add-on packages tm and auctex are already installed,
and now someone installs emacs21.

In it's postinst, emacs21 would make this call:

/usr/lib/emacsen-common/emacs-install emacs21

which would result in calls to

/usr/lib/emacsen-common/packages/install/auctex emacs xemacs21
/usr/lib/emacsen-common/packages/install/auctex emacs21 xemacs21
/usr/lib/emacsen-common/packages/emacs21/install/tm emacs xemacs21
/usr/lib/emacsen-common/packages/emacs/install/tm emacs21 xemacs21

- わからないところの特定
- /usr/lib/emacsen-common/emacs-install emacs21
- これはわかる。これをpostinstで実行するとがポ
リシーだから。
- しかし、上の呼出しが、

/usr/lib/emacsen-common/packages/install/auctex emacs xemacs21
/usr/lib/emacsen-common/packages/install/auctex emacs21 xemacs21
/usr/lib/emacsen-common/packages/emacs21/install/tm emacs xemacs21
/usr/lib/emacsen-common/packages/emacs/install/tm emacs21 xemacs21

これになるのはわからない。特に、なんで'emacs
が呼ばれるの?というところ。具体的には、

/usr/lib/emacsen-common/packages/install/auctex emacs21 xemacs21
/usr/lib/emacsen-common/packages/emacs/install/tm emacs21 xemacs21

こうじゃないの? と。

- ソース解読
- 解決。私の「こうじゃないの?」で正しそう。
- 根拠。
- install済みのflavorsは、

/var/lib/emacsen-common/installed-flavors

に記載されており、emacs-install
scriptも'other-flavors'の値はこれを使用してい
る。なので、ここに何が書いてあるかが、展開し
て実行する命令群を決める。
- すると、ポイントは、meta packageである'emacs'
がここに含まれるかどうか、だ。私の環境では、

i emacs - The GNU Emacs editor (metapackage)
i emacs22 - The GNU Emacs editor (Emacs 22)

というinstall状況だが、installed-flavors
は'emacs22' のみを内容として含んでいる。
- 実証。
- 'emacs22'と'xemacs21'がinstall済みの状態で、
'emacs21'にて、emacs-install scriptをdry
runさせてみる。を入れてみよう。
- emacs-installをcopyしてemacs-install-testと
して、my $dry_run = 1;とする。

emacsen-common $ ./emacs-install-test emacs21
emacs-install emacs21
/usr/lib/emacsen-common/packages/install/apel emacs21 emacs22 xemacs21
/usr/lib/emacsen-common/packages/install/cedet-common emacs21 emacs22 xemacs21
/usr/lib/emacsen-common/packages/install/debian-el emacs21 emacs22 xemacs21
/usr/lib/emacsen-common/packages/install/dictionaries-common emacs21 emacs22 xemacs21
/usr/lib/emacsen-common/packages/install/emacs-extra emacs21 emacs22 xemacs21
/usr/lib/emacsen-common/packages/install/emacs-goodies-el emacs21 emacs22 xemacs21
/usr/lib/emacsen-common/packages/install/emacsen-common emacs21 emacs22 xemacs21
/usr/lib/emacsen-common/packages/install/global emacs21 emacs22 xemacs21
/usr/lib/emacsen-common/packages/install/latex-cjk-common emacs21 emacs22 xemacs21
/usr/lib/emacsen-common/packages/install/lookup-el emacs21 emacs22 xemacs21
/usr/lib/emacsen-common/packages/install/mdk emacs21 emacs22 xemacs21
/usr/lib/emacsen-common/packages/install/mew emacs21 emacs22 xemacs21
/usr/lib/emacsen-common/packages/install/mmm-mode emacs21 emacs22 xemacs21
/usr/lib/emacsen-common/packages/install/octave3.0-emacsen emacs21 emacs22 xemacs21
/usr/lib/emacsen-common/packages/install/paredit-el emacs21 emacs22 xemacs21
/usr/lib/emacsen-common/packages/install/prolog-el emacs21 emacs22 xemacs21
/usr/lib/emacsen-common/packages/install/ruby1.8-elisp emacs21 emacs22 xemacs21
/usr/lib/emacsen-common/packages/install/w3m-el emacs21 emacs22 xemacs21
/usr/lib/emacsen-common/packages/install/flim emacs21 emacs22 xemacs21
/usr/lib/emacsen-common/packages/install/elscreen emacs21 emacs22 xemacs21
/usr/lib/emacsen-common/packages/install/ddskk emacs21 emacs22 xemacs21
/usr/lib/emacsen-common/packages/install/speedbar emacs21 emacs22 xemacs21
/usr/lib/emacsen-common/packages/install/eieio emacs21 emacs22 xemacs21
/usr/lib/emacsen-common/packages/install/dpkg-dev-el emacs21 emacs22 xemacs21
/usr/lib/emacsen-common/packages/install/slime emacs21 emacs22 xemacs21
/usr/lib/emacsen-common/packages/install/nxml-mode emacs21 emacs22 xemacs21
/usr/lib/emacsen-common/packages/install/maxima-emacs emacs21 emacs22 xemacs21
/usr/lib/emacsen-common/packages/install/latex-cjk-thai emacs21 emacs22 xemacs21
/usr/lib/emacsen-common/packages/install/ede emacs21 emacs22 xemacs21
/usr/lib/emacsen-common/packages/install/semantic emacs21 emacs22 xemacs21
Installed flavors are now: emacs22 xemacs21 emacs21
emacsen-common $
- うむ。実証できた。

- 例2
- これは例1のremove版なのでinstallと同様の動作
であろう。内容確認は割愛。

- 例3
- an add-on packageをremoveする例。
- 'emacs22'と'xemacs21'がinstall済みとする。
- 'wget-el' add-on packageがinstall済みとする。
- 'wget-el'をremoveする。
- 例の挙動は、次のとおり。
- prermにて、emacsen-package-removeが'wget-el'を
引数にて呼ばれる。
- その結果、次の命令群が生成される。

/usr/lib/emacsen-common/packages/remove/wget-el emacs emacs22 xemacs21
/usr/lib/emacsen-common/packages/remove/wget-el emacs22 emacs22 xemacs21
/usr/lib/emacsen-common/packages/remove/wget-el xemacs21 emacs22 xemacs21

- ここでも、'emacs'が何故存在するのかがわから
ない。次のものならわかる。

/usr/lib/emacsen-common/packages/remove/wget-el emacs22 xemacs21
/usr/lib/emacsen-common/packages/remove/wget-el xemacs21 emacs22
- dry run。
- 今度は先にdry runしてみる。

emacsen-common $ ./emacs-package-test-remove wget-el
/usr/lib/emacsen-common/packages/remove/wget-el emacs emacs22 xemacs21
/usr/lib/emacsen-common/packages/remove/wget-el emacs22 emacs22 xemacs21
/usr/lib/emacsen-common/packages/remove/wget-el xemacs21 emacs22 xemacs21
emacsen-common $

- なんと。。。

- ソース解読。
- あ、

map {
my $script = $lib_dir . "/packages/$action/$_";
execute($script, 'emacs', @installed_flavors) if -e $script;
} @pkgs_to_handle;

なるものがいる。
- なので、add-on packagesについては
install/removeにおいて、'emacs'がかならず引
数に入ってくるのだな。
- そもそも、なんでothersをならべる必要がある
のか?
- packages/remove/wget-elをみてみる。

#!/bin/sh -e
# /usr/lib/emacsen-common/packages/remove/emacs-wget

FLAVOR=$1
PACKAGE=wget-el

if [ ${FLAVOR} != emacs ]; then
# if test -x /usr/sbin/install-info-altdir; then
# echo remove/${PACKAGE}: removing Info links for ${FLAVOR}
# install-info-altdir --quiet --remove --dirname=${FLAVOR} /usr/info/emacs-wget.info.gz
# fi

echo remove/${PACKAGE}: purging byte-compiled files for ${FLAVOR}
rm -rf /usr/share/${FLAVOR}/site-lisp/${PACKAGE}
fi
- うむー。$1しか使っていない。


こつこつ。

2009年11月30日月曜日

debian-emacs-policyのポイント

ざっとポイントをまとめた。
これ以上理解するには、perlを多少勉強せねばならない。
うーん。どうしたものか。


* debian-emacs-policyのポイント
- debian-emacs-policyでは、debian systemにてemacs
関連のpackagesを作成/管理するためのpolicyが規程
されている。
- 簡明にまとまっている文書なので、メモ化する必要は
ないのだが、確実な理解のためにあえてメモを作成す
る。
- policyの所在
- emacsen-common:
/usr/share/doc/emacsen-common/debian-emacs-policy.gz
- またはWeb。debian.org。

** policyにおける用語
- <emacs>

emacs
xemacs21
emacs21
emacs22

- <flavor>

xemacs21
emacs21
emacs22

- すなわち、<emacs> - 'emacs'。

** policyが求めるload-path
- load-path
- debian emacs policyでは、最低、次の場所が次の
順(優先度が高い順)にload-pathに含まれることを求めている。
これはどのemacsenにおいても、である。

/etc/<flavor>
/etc/emacs
/usr/local/share/emacs/<upstream>/site-lisp
/usr/local/share/emacs/site-lisp
/usr/share/emacs/<flavor>/site-lisp
/usr/share/emacs/site-lisp

- ここで、<upstream>は、'22.2'などのupstream
version number。

** emacsen-common package
- emacsen-commonパッケージは、debian emacs policy
に従ったemacs packagesの管理のためのfacilityを提
供している。
- 提供物一覧

~ $ apt-file list emacsen-common
emacsen-common: /etc/emacs/site-start.d/00debian-vars.el
emacsen-common: /etc/emacs/site-start.el
emacsen-common: /usr/lib/emacsen-common/emacs-install
emacsen-common: /usr/lib/emacsen-common/emacs-package-install
emacsen-common: /usr/lib/emacsen-common/emacs-package-remove
emacsen-common: /usr/lib/emacsen-common/emacs-remove
emacsen-common: /usr/lib/emacsen-common/generate-install-list
emacsen-common: /usr/lib/emacsen-common/packages/install/emacsen-common
emacsen-common: /usr/lib/emacsen-common/packages/remove/emacsen-common
emacsen-common: /usr/share/doc/emacsen-common/changelog.gz
emacsen-common: /usr/share/doc/emacsen-common/copyright
emacsen-common: /usr/share/doc/emacsen-common/debian-emacs-policy.gz
emacsen-common: /usr/share/emacs/site-lisp/debian-startup.el
~ $

- /etc/emacs/site-start.el
- これはpackageに含まれてはいるが、local admin
が中身を管理するもの。

*** 提供物の概要
**** /usr/lib/emacsen-common/emacs-install
- perl script。
- コメント。

# Call emacsen-common/packages/install/* install-flavor other-flavor ...
# for every installed emacs add-on package.

**** /usr/lib/emacsen-common/emacs-remove
- emacs-installの別名。

**** /usr/lib/emacsen-common/emacs-package-install
- perl script。
- コメント。

# Was this called because we're installing/removing a new emacs
# flavor? This should probably be handled with getopt and a command
# line opt, but it's freeze time, and I'm tired...

**** /usr/lib/emacsen-common/emacs-package-remove
- emacs-package-installの別名。

**** /usr/lib/emacsen-common/generate-install-list
- perl script。
- ライブラリ。
- コメント。

# depends on: dpkg, tsort, perl

# This script should be handed a list of add-on packages on stdin, and
# it will sort them according to their dependencies. It will also add
# in other add-on packages that aren't mentioned, but are needed.

# Test code
# my @input_packages = <STDIN>;
# my @result = generate_add_on_install_list(@input_packages);
# print " " . join("\n ", @result);

**** /usr/lib/emacsen-common/packages/install/emacsen-common
- shell script。
- 使い方。
- /usr/lib/emacsen-common/packages/remove/emacsen-common <flavor>
- emacsen-commonパッケージが提供しているelファイ
ルについて、flavor用バイトコンパイルを実施する。
**** /usr/lib/emacsen-common/packages/remove/emacsen-common
- shell script。
- 使い方。
- /usr/lib/emacsen-common/packages/remove/emacsen-common <flavor>
- emacsen-commonパッケージが提供しているelファイ
ルのflavor用バイトコンパイルを削除する。

** emacsen main packages
- 'emacs22'とか'xemacs21'とか、emacsen本体を提供
するパッケージのこと。
*** 必須作法
**** メンテナスクリプト
- postinst
- postinstに記述するもの。
- "/usr/lib/emacsen-common/emacs-install <flavor>"
- この記述によってemacs-installは次のものを実
行する。
- "/usr/lib/emacsen-common/packages/install/<pkg> <flavor> <others>"
- prerm
- prermに記述するもの。
- "/usr/lib/emacsen-common/emacs-remove <flavor>"
- この記述によってemacs-removeは次のものを実
行する。
- "/usr/lib/emacsen-common/packages/remove/<pkg> <flavor> <others>"
**** バイナリシムリンク
- /usr/bin/<package-name>から
/usr/bin/<emacs-binary>へのsymbolic linkが必須。
- というのはadd-on packagesがinstall/removeすると
き、/usr/bin/$ARGV[0]を使ってバイトコンパイルな
どをするから。
**** 依存関係 "Provides: emacsen"
- emacsen main packageは、debian packageとして
controlファイルにおいて、"Provides:"に
"emacsen"と記述する。
- 例:emacs22

Provides: editor, emacsen, info-browser, mail-reader, news-reader

** add-on packages
*** 基本作法
- 必須な作法は少い。
- 何故かというと、もしadd-onしようとしている機能に
ついて、バイトコンパイルが不要であったり、インストー
ル時の調整(emacs毎)も不要であったりするならば、
単にそのadd-on packageは、しかるべき場所にしか
るべきファイルを置くだけで目的をはたせるからだ。
- ここでは必須なものを含めて基本的なものを書く。
**** 設置場所
- add-on packagesが設置できる場所はつぎのとおり。
/etc/<emacs>/site-start.d
/usr/share/<emacs>/site-lisp/<package-name>
- これは必須作法である。
**** load-path
- add-on packagesはload-pathをいじってはいけない。
- これは必須作法である。
**** 依存関係
- 'emacsen-common'をdependsするべきではない。その
かわりに、'emacsen'をdependsするか、対応している
flavorsをdependsする。
**** 初期化ファイルの中身
- site-start.dなどにおく初期化ファイルでは、load
ではなくautoloadを使うべし。

*** 応用作法
- 「バイトコンパイルが必要」など、flavorに依存した
install/remove処理が必要なものの作法。

**** メンテナスクリプト
- まず、次のファイルをパッケージにて提供すべし。

/usr/lib/emacsen-common/packages/install/<pkg>
/usr/lib/emacsen-common/packages/remove/<pkg>

- サンプル
- 仮想的なfooというパッケージに対するもの。
- flavor毎にバイトコンパイルをするもの。
- install

#!/bin/sh
# /usr/lib/emacsen-common/packages/install/foo
# [ This particular script hasn't been tested, so be careful. ]
set -e

FLAVOR=$1
echo install/foo: Handling install of emacsen flavor ${FLAVOR}

byte_compile_options="-batch -f batch-byte-compile"
el_files="some-file.el some-other-file.el etc.el"
el_dir=/usr/share/emacs/site-lisp/foo/
elc_dir=/usr/share/${FLAVOR}/site-lisp/foo/

if [ ${FLAVOR} != emacs ]
then
echo install/foo: byte-compiling for ${FLAVOR}

[ -d ${elc_dir} ] || mkdir ${elc_dir}

# Copy the temp .el files
(cd ${el_dir} && cp ${el_files} ${elc_dir})

# Byte compile them
(cd ${elc_dir} \
&& ${FLAVOR} ${byte_compile_options} ${el_files} 2> /dev/null)

# remove the redundant .el files
# presumes that any .el files in the <flavor> dir are trash.
rm ${elc_dir}/*.el
fi
exit 0;

- remove

#!/bin/sh
# /usr/lib/emacsen-common/packages/remove/foo
# [ This particular script hasn't been tested either, so be careful. ]
set -e

FLAVOR=$1
elc_dir=/usr/share/${FLAVOR}/site-lisp/foo

echo remove/foo: Handling removal of emacsen flavor ${FLAVOR}

if [ ${FLAVOR} != emacs ]
then
echo emacsen-common: purging byte-compiled files for ${FLAVOR}
rm -f ${elc_dir}/*.elc
[ -d ${elc_dir} -a `ls -la ${elc_dir}|wc -l` -gt 3 ] && rmdir ${elc_dir}
fi
exit 0;

- その上で、メンテナスクリプトは次のようにすべき。
- postinst
- /usr/lib/emacsen-common/emacs-package-install <pkg>
- prerm
- /usr/lib/emacsen-common/emacs-package-remove <pkg>


こつこつ。

2009年11月29日日曜日

Ubuntu/GNU Emacs22の起動プロセスにおけるload-pathの構築と利用

ソースを探ったり、いろいろビルドしたりして、結構わかった。
完全とまではいきませんが、現状では十分。

load-pathに限らず、Emacsの起動プロセスをいろいろ調べた。結果として、Emacsの仕組みについて多少詳しくなったのも嬉しい。


* Ubuntu/GNU Emacs22の起動プロセスにおけるload-pathの構築と利用
** src/epaths.in
- epaths.hの素。
- この中のPATH_LOADSEARCHがload-pathの素。
- GNU配布状態:
#define PATH_LOADSEARCH "/usr/local/lib/emacs/lisp"

** src/epaths.h
- makeによって、epaths.inを素に生成される。
- GNU配布状態: [./configure, makeの結果]
#define PATH_LOADSEARCH "/usr/local/share/emacs/22.2/site-lisp:/usr/local/share/emacs/site-lisp:/usr/local/share/emacs/22.2/lisp:/usr/local/share/emacs/22.2/leim"
- Ubuntu: [debuildの結果]
#define PATH_LOADSEARCH "/etc/emacs22:/etc/emacs:/usr/local/share/emacs/22.2/site-lisp:/usr/local/share/emacs/site-lisp:/usr/share/emacs/22.2/site-lisp:/usr/share/emacs/site-lisp:/usr/share/emacs/22.2/leim:/usr/share/emacs/22.2/lisp:/usr/share/emacs/22.2/leim"

** src/emacs.c
- main
- init_lread関数[lread.c]の実行
- normal = PATH_LOADSEARCH;
- Vload_path = decode_env_path ("EMACSLOADPATH", normal);
- dcode_env_pathはパス達のリストを返す。
- Vtop_level変数の構成
- 起動時に評価するlispを格納。
- 値の形式は(load . (hoge))。すなわちhogeをロー
ドする。
- hogeは、
- emacsオプションで'-l'指定があればそのelファ
イル。
- そうでなければ、'loadup.el'。
- GNU:
(load "loadup.el")
- Frecursive_edit関数の実行
- editor command loop に入る。
- recursive_edit_1 [keyboard.c]
- command_loop [keyboard.c]
- internal_catch (Qtop_level, top_level_1, Qnil)
- top_level_1 [keyboad.c]
- internal_condition_case (top_level_2, Qerror, cmd_error) [eval.c]
- top_level_2 [keyboard.c]
- Feval (Vtop_level) [eval.c]
- ここにいたり、先にVtop_level
で設定した(load "loadup.el")が
評価される。

** lisp/loadup.el
- このelispに入った時点では、emacs.cのVload_path
がload-pathの値である。

*** load-path変数の調整
- bootstrappingするときだけ、load-pathを次のように
加工する。通常はこの加工はしない。

(let ((dir (car load-path)))
;; We'll probably overflow the pure space.
(setq purify-flag nil)
(setq load-path (list dir
(expand-file-name "emacs-lisp" dir)
(expand-file-name "language" dir)
(expand-file-name "international" dir)
(expand-file-name "textmodes" dir))))

*** (load "startup") [lisp/startup.el]
- (defcustom site-run-file "site-start" ...)
- (defconst debian-emacs-flavor 'emacs22 ...)
[*debian patch*]
- (setq top-level '(normal-top-level))
- normal-top-level関数を定義
- この関数の中で次の処理が定義されている。
- load-pathの拡張
- load-pathに含まれるパスを順次処理する。
- 処理は、そのパスに、subdirs.elや
leim-list.elがあれば、それらをloadするとい
うもの。
- subdirs.elの中身の典型は、次の2つ。
- normal-top-level-add-subdirs-\
to-load-path を引数無しで呼ぶ。これは
カレントディレクトリ配下のサブディレク
トリを全てload-pathに追加する。
- normal-top-level-add-subdirs-\
to-load-path を引数有で呼ぶ。これはカ
レントディレクトリ配下のサブディレクト
リについて、引数で指定されたものを
load-pathに追加する。
- leim-list.elの中身の典型は、次のよう。
- register-input-method関数の実行を列記。
- loadやautoloadをここに記述することも
ある。
- command-line関数を実行する。
- emacs-starup-hookを呼ぶ。
- term-startup-hookを呼ぶ。
- command-line関数を定義
- この関数の中で次の処理が定義されている。
- (load site-run-file t t)
- (load "debian-startup" t t nil) [*debian patch*]
- "debian-startup.el"の中身は関数群定義のみ。
- 定義される関数の一覧。
- debian-pkg-add-load-path-item
- debian-unique-strings
- debian-run-directories
- debian-startup
- (debian-startup debian-emacs-flavor)の実行 [*debian patch*]
- (let ((common-dir "/etc/emacs/site-start.d")
(flavor-dir (concat "/etc/" (symbol-name flavor) "/site-start.d")))
(debian-run-directories flavor-dir common-dir))))
- (debian-run-directories flavor-dir common-dir)
- flavor-dirやcommon-dirに入っているすべての
ディレクトリについて、NNfilename.elや
NNfilename.elcの形のファイル名のものを探索
収集し、アルファベティカルにソートして、重
複を削除したリストを作成する。このリス
トをbase-namesと呼ぶ。
- load-pathに、flavor-dirとcommon-dirを追
加する。
- base-namesの中身(file)をひとつずつloadす
る。
- 前項のloadをした結果として、load-pathが
さらに拡張されているかもしれない。そこで、
load-pathをflavor-dirとcommon-dirを追加
しただけの状態に戻す。
- (load site-run-file t t nil) [*debian patch*]

- user-init-file-1の調整
- user-init-file-1は、いわゆる'~/.emacs'となる。
- (load user-init-file-1 t t)
- otherfileの調整
- いわゆる'~/.emacs.d'の中の'init'というファイ
ル。
- (load otherfile t t)
- (load "default" t t)
- inihibit-default-initがnilのときは読み込まな
い。

*** (load "site-load" t)
- 'site-load.el'がload-pathのどこかに存在すれば
それをloadする。

- これはtemacsからemacsをdumpするときに含めたい
elispを指定するために存在している。計算機の速度
が向上しているため最近は使わない。
- そもそもの目的はdumpに含めることなのだが、起動時
に読み込ませるelispの設置場所としても使えると言
えば使える。
- ホストのelisp共通設定は、ここではなく
て'default.el'に書くべきである。そちらはユーザ
によって読み込みの制御ができるから。

*** (load "site-init" t)
- 'site-init.el'がload-pathのどこかに存在すれば
それをloadする。

- これもsite-loadと同種の目的のもの。タイミングが
違う。site-initに書いたものはdumped imageにdoc
stringsが読み込まれる。こちらに書いたものは
dumped imageには読み込まれない。
- そもそもの目的はdumpに含めることなのだが、起動時
に読み込ませるelispの設置場所としても使えると言
えば使える。
- ホストのelisp共通設定は、ここではなく
て'default.el'に書くべきである。そちらはユーザ
によって読み込みの制御ができるから。

- site-init.el [*debian patch*]
- flavor-specificなinfo dirの追加処理が記述され
ている。

*** (eval top-level)
- (eval top-level)
- normal-top-level関数[startup.el]の実行


こつこつ。

2009年11月4日水曜日

UbuntuとDebianではEmacs22は別パッケージング

Emacs22のソースをしらべていたら差異があった。

なんと、forkしている。

https://wiki.ubuntu.com/MichaelOlson/WhyDifferentEmacs

ただ、lennyとinterpidでは、documentの分離とかに違いはないような?、なんだけどpatchesが微妙に違う。

add-onなelispについてはどちらもdebian emacs policy準拠なようだ。

そこで、debian emacs policyを仕様としては参照しつつ、パッケージは日頃使っているUbuntuで探ってみることにする。

Emacs22 の起動処理

仕事でやっていることが、勉強とだんだんかぶってきた。
ごりごりやっているのだが、ここに書けない。。。これはどうしたらよいか考えてみる。
さて、仕事とは無関係なこととして、Emacs22の環境整備をはじめた。まず、起動プロセスの調査から。


** Emacs22の起動プロセス

- infoに情報あり。Elisp, 39.1 Starup Emacs。
- 詳細を知るにはソースを読む。次のものがメイン。
- configure
- src/emacs.c
- lisp/loadup.el
- lisp/startup.el
- 呼び出しというか実行順はこんな感じ。
call src/emacs.c
...
load lisp/loadup.el
...
load lisp/startup.el
...
load lisp/loaddefs.el
...
load lisp/site-load.el
...
load lisp/site-init.el
call normal-top-level (eval top-level)
[normal-top-level (startup.el)]
...
call command-line (startup.el)
...
...
call Frecursive_edit (keyboard.c)

- loadup.elに含まれるものは、通常、temacsによっ
てdumpされ、emacsのイメージに含まれている。
昔はマシンのスピードが遅かったので、
site-load.elやsite-init.elをカスタマイズした
上で、自分用のイメージをdumpしていた。今はマ
シンのスピードが速いので、これらを使うのは得
策ではない。

- ここでは、EmacsおよびElisp librariesのデプロイ
を検討するための基礎情報に重点を置く。


0-1. 標準ライブラリパス

the standard library path.

- Emacsのcompile時にデフォルト値を決定。

- サイトのライブラリの置き場所として(デフォルト
では)、

- `/usr/local/share/emacs/VERSION/site-lisp'
- `/usr/local/share/emacs/site-lisp'

が設定される。前者はemacsのVERSIONに特化したも
の。後者はVERSIONに関わらないもの。

しかし、サイトのライブラリの置き場所だけでなく
設定ファイルの置き場所も兼ねている。configure
の中は次のとおり。

ac_default_prefix=/usr/local
# prefixを確定する機構
datarootdir='${prefix}/share'
datadir='${datarootdir}'
lispdir='${datadir}/emacs/${version}/lisp'
locallisppath='${datadir}/emacs/${version}/site-lisp:'\
'${datadir}/emacs/site-lisp'
lisppath='${locallisppath}:${lispdir}:${datadir}/emacs/${version}/leim'

- Emacs内では'load-path'変数にてこの値は管理され
る。よって、起動の途中でこの変数の値が変更され
れば、それ以降は変更された値が有効になる。

- debianのコンパイルではどういう設定になっている
かは要調査。


0-2. system type

- Emacsのcompile時に決定。
- emacs.cにて定義。

----
DEFVAR_LISP ("system-type", &Vsystem_type,
doc: /* Value is symbol indicating type of operating system you are using.
Special values:
`gnu/linux' compiled for a GNU/Linux system.
`darwin' compiled for Darwin (GNU-Darwin, Mac OS X, ...).
`macos' compiled for Mac OS 9.
`ms-dos' compiled as an MS-DOS application.
`windows-nt' compiled as a native W32 application.
`cygwin' compiled using the Cygwin library.
`vax-vms' or
`axp-vms' compiled for a (Open)VMS system.
Anything else indicates some sort of Unix system. */);
----


1-1. サブディレクトリ

subdirectories.

- loadup.elの所作。
- lispディレクトリのサブディレクトリを設定する。
設定するのはつぎのもの。
- emacs-lisp
- language
- international
- textmodes


1-2. サブディレクトリ

subdirectories.

- normal-top-level関数(startup.el)の所作。
- load-pathに含まれている各ディレクトリについて、
そこにsubdirs.elまたはleim-list.elがあれば、そ
れを実行する。通常subdirs.elには、関数
normal-top-level-add-subdirs-to-load-pathの呼
び出しがあり、そこにあるサブディレクトリを
load-pathに追加する。


2. ウィンドウシステムの初期化

loading the initialization library for the
window system.

- a windows systemでEmacsを起動しているなら、
`term/WINDOWSYSTEM-win.el'をloadする。

3. 言語環境と端末コーディング

the language environment and the terminal
coding system.

- Infoの説明では、これはウィンドウシステムの初
期化の前だが、sourceだと順番が逆。
- normal-top-level関数(startup.el)が、
set-locale-environment関数
(international/mew-cmds.el)を呼び出すことによ
り実現。

3-2. ユーザの特定

- comman-line関数 (startup.el) の所作。
- 環境変数などにアクセスするための基礎として、
userを特定する。


4. 初期化オプションの処理 (後半)

- comman-line関数 (startup.el) の所作。

- emacs.cが前半処理を実施。それはloadup.el部分
に入るまえに実施される。

5. before-init-hook

- Infoでは5と6は逆。sourceではこの順番。

- comman-line関数 (startup.el) の所作。
- before-init-hookを実行する。


6. ウィンドウフレームとフェイス

- comman-line関数 (startup.el) の所作。
- ウィンドウフレームとフェイスを初期化する。


7. site-start.elの特定とload

- comman-line関数 (startup.el) の所作。

- 標準ライブラリパスを順番に探す。みつかったとこ
ろで探索をやめ、それをload する。
- '--no-site-file'を起動オプションに指定すると、
このファイルはloadされない。


8. ユーザのInit Fileの特定とload

- comman-line関数 (startup.el) の所作。

ここで特定したホームディレクトリへのパスを"~"で
あらわす。
- 次の順でInit Fileを探す。みつかったところで探
索をやめて、みつかったものをloadする。

a. '~/.emacs'
b. '~/.emacs.elc'
c. '~/.emacs.el'
d. '~/.emacs.d/init.elc'
e. '~/.emacs.d/init.el'

- '-q'すなわち'--no-init-file'を起動オプションに
指定すると、このファイルはloadされない。
- また'-Q'すなわち'--batch'を起動オプションに指
定すると、このファイルはloadされない。
- '-u'にてユーザを指定すると'~'はそのユーザのホー
ムディレクトリを参照するためInit Fileが変更さ
れる。
- load関数の機構なら、'~/.emacs.d/init'も探索対
象になるはずだが、どうなのか。(要調査)


9. サイトのdefault.elの特定とload

- comman-line関数 (startup.el) が支配。

- 標準ライブラリパスを順番に探す。みつかったとこ
ろで探索をやめ、それをloadする。
- '-q'すなわち'--no-init-file'を起動オプションに
指定すると、このファイルはloadされない。
- 変数'inihibit-default-init'がnon-nilだと、こ
のファイルはloadされない。


10. after-init-hook

- comman-line関数 (startup.el) の所作。
- after-init-hookの実行。


11. initial-major-mode

- comman-line関数 (startup.el) の所作。
- *scratch*がまだfundamental-modeなら、
initial-major-mode関数を呼び出してこれを変更。


12. TERMTYPEの特定とterm/TERMTYPEのload

- normal-top-level関数 (startup.el) の所作。
- 次の手順で特定しloadする。

a. (getenv "TERM")にて環境変数TERMの値を得る。
b. aで得た文字列について、一番最初のハイフン以前
の値をTERMTYPEとする。例えば、TERMが'aaa-48' な
らば、TERMTYPEは'aaa'。
c. term/TERMTYPEがloadすべきファイルとなる。こ
れを標準ライブラリパスから探してloadする。

- 変数term-file-prefixがnilだと、このファイルは
loadされない。


13. initial echo area message

- これはsourceには無いような?


14. processing the action arguments

- これもsourceには無いような?


15. emacs-startup-hook, term-setup-hookの実行

- normal-top-level関数 (startup.el) の所作。

- emacs-startup-hookの実行。
- term-setup-hookの実行。


16. frame-notice-user-settings

- normal-top-level関数 (startup.el) の所作。
- user-settingsが有効になるようにnoticeをかける。


17. window-setup-hookの実行

- normal-top-level関数 (startup.el) の所作。
- window-setup-hookの実行。


18. initial scratch message、display startup screenの表示

- normal-top-level関数 (startup.el) の所作。
- 画面にメッセージ表示。



** Emacs22のloadとrequire

*** load

(load FILE &optional NOERROR NOMESSAGE NOSUFFIX MUST-SUFFIX)

FILEに含まれているLisp codeを実行する。
load-suffixes変数に定義されている順にsuffixをFILE
にファイルを探す。最後にsuffixをつけないでFILEその
ままで探す。探す対象ディレクトリはload-path変数に
含まれているもの。

*** autoload

(autoload FUNCTION FILE &optional DOCSTRING INTERACTIVE TYPE)

FUNCTIONが呼び出されたら、FILEをloadする。
DOCSTRINGを書けば、未load状態でもFUNCTIONの説明を
表示することができる。

autoload cookie `;;;###autoload' を関数定義の直前
に書いておくと、update-file-autoloads関数によって、
その関数に対するautoloadがloaddefs.elに追加される。

*** require

(require FEATURE &optional FILENAME NOERROR)

FEATUREがload済みでなければ、それをFILENAMEから
loadする。FEATUREがfeatures変数の値(list)に含まれ
えていないなら、loadは実行されない。

FILENAMEが省略されている場合は、FEATUREのprint name
(おそらくシンボルの印字名)がFILENAMEの代替となる。

*** provide

(provide FEATURE &optional SUBFEATURES)

FEATUREがこのEmacsの a feature であることを周知す
る。SUBFEATURES はシンボルのリスト。このFEATUREに
付随して実現されている features を周知する。

*** package

Emacs22にCLのようなpackageシステムは存在しない。

2009年9月10日木曜日

eli の使いこなし [起動済みのLispにEmacsを接続]


  • まず localhost 上。
  • Lisp にて

    (excl:start-emacs-lisp-interface t 1 7666 "~/.eli-startup")

    を評価。すると~/.eli-startup というファイルができる。
    このファイルの中身は、

    ^A7666 542496 :upper (8 (1) :FINAL 7) 1^A

    というシンプルなもの。Emacs に渡す接続情報である。
  • 次に、Emacs で、

    (fi:start-interface-via-file "localhost" "*common-lisp*" "~/.eli-startup")

    を評価。これでREPLが立ち上がる。メジャーモードは、TCP Common Lisp モード。このモードは、keymap は fi:lisp-listener-mode-map を使っている。

  • この方法で接続した場合も、fi:common-lisp-mode で開いたソースファイルとの連携ができる。
  • "localhost"をFQDNまたはIPアドレスに変更すれば、リモートの Lisp に接続できる。ただし起動情報ファイル(ここでは.eli-startup) をEmacsがあるホストで参照できるようにしておくこと。これは、ファイルを転送してもいいし、NFSやsambaで共有してもよい。
  • この方法で、複数 Lisp に単一 Emacs からREPL接続することができる。ただし、fi:common-lisp-mode で開いた Lisp ソースと連携するのは一番最後に開いた REPL だけ。
  • listenerを増やすことができるのも、一番最後に開いた REPL の Lisp だけ。

  • この方法で、2つ以上の Emacs をひとつの Lisp につなぐこともできる。そのときも、

    (excl:start-emacs-lisp-interface t 1 7666 "~/.eli-startup")

    これは一個でよい。

  • さて、

    (excl:start-emacs-lisp-interface t 1 7666 "~/.eli-startup-1")
    (excl:start-emacs-lisp-interface t 1 7667 "~/.eli-startup-2")

    として、それぞれに別の Emacs をつなぐこともできる。ただし、

    (excl:start-emacs-lisp-interface t 1 7666 "~/.eli-startup")

    これひとつに2つの Emacs をつなぐのと、機能上の違いはない。:processes 的には、Editor Server が2つできるので違いはある。

  • こうしてみると、かなり自由自在というか柔軟なんだな。

時間ができたときに、整理して 逆引きCommon Lisp に書こう。
こつこつ。

2009年9月7日月曜日

eli の使いこなし [fi:common-lisp によるリモートLispの起動]


  • これ、M-x fi:common-lisp の引数指定で ホストを指定してあげればよいだけなのですが、うまく起動できない。
  • ソースを調べてみると、どうやら ssh ではなく rsh 専用になっているようだ。
  • eli のためだけに、ssh とは別に rsh を運用するというのはちょっと避けたい。
  • リモート Lisp は fi:start-interface-via-file に一元化かな。

こつこつ。

eli の使いこなし [複数listener]


  • fi:common-lisp で REPL を起動済みなことが前提。
  • M-x fi:open-lisp-listener で対話的に新しい listener を起動できる。このときバッファ名は、*lisp-listener* になる。
  • M-x fi:open-lisp-listener を使ってさらに listener を起動するのはやめたほうがよい。この方法の場合、事前に作成した listener のバッファ名を *lisp-listener* 以外に変更しておいて、M-x fi:open-lisp-listener を実施することになるが、このバッファ名の変更が、Common Lisp に伝わらないからだ。

  • 2つ以上新規に listener を起動する場合は、対話的ではなく、

    (fi:open-lisp-listener -1 "*my-lisp-listener*")

    などを評価する方がよい。-1 は buffer-number という引数だが、Gnu Emacs 22 の Info では記述されていない。負数を設定すると自動的に空き番号を使うとのことなので、負数運用がいいのかもしれない。
  • fi:open-lisp-listener で起動した REPL はfi:inferior-common-lisp-mode ではなく、fi:lisp-listener-mode である。

  • さて、listener は プロセスとどういう関係があるのかというと、まず listener を増やしても、OS上の alisp のプロセスは増えない。Common Lisp 内のスレッドが増える。
  • listener を終了するときは、:kill で Common Lisp の内部スレッドを停止する。
  • どの listener においても、:exit すると、全ての listener というか Lisp 本体が停止してしまう。


時間があるときに、整理しながら逆引きCommon Lispに書こう。
こつこつ。

2009年9月5日土曜日

Emacsでlispファイルを開くときのこと (2)

Franz の fi:common-lisp-mode (eli)ではどうなんだろ、ということで、多少追ってみる。
まず、マニュアルによると、

;; -*- mode: fi:common-lisp-mode; package: mypack; readtable: myrt -*-
(in-package :mypack)
(eval-when (compile
load
eval)
(setq *readtable* (named-readtable :myrt)))

というのがフルな使い方のようだ。

mode: は eli に関わらない標準的なこと。これ以降は eli 独自だ。

mode specification で package と readtable を指定するということは、これらをEmacsに教えてあげるということだ。これらをEmacsが知っていることによって、eli を通じてEmacsとCommon Lispのやりとりが成り立つということ。

ただし、packageについてはソースを読み込み時にパースして(in-package ...)があれば、それも見てくれる。

ちなみに、Franzのマニュアルでは、'mode line'を'display mode line'、'mode specification' を 'file mode line' と読んで区別している。どうやら以前は両方とも'mode line' と呼ばれていてname conflicts があったようだ。

packageの指定が、file mode line にもなく、(in-package ...)としてもない場合は、

fi:default-package
fi:package

が参照され、readtableの指定がない場合は、

fi:readtable

が参照される。

こつこつ。

Emacsでlispファイルを開くときのこと

EmacsでLispファイルを開くときに妙な確認がでる。それを調べてみる。

まず、出るものはこれ。

The local variables list in paip-study.lisp
contains values that may not be safe (*).

Do you want to apply it? You can type
y -- to apply the local variables list.
n -- to ignore the local variables list.
! -- to apply the local variables list, and
permanently mark these
values (*) as safe (in the future, they will
be set automatically.)

* Syntax : Common-Lisp

これは該当Lispファイルの一行目に、

-*- Mode: Lisp; Syntax: Common-Lisp -*-

を書いているからだろう。この行のことを「mode line」と言うのかと思っていたら、正確には「mode specification」なんですね。「mode line」はmini bufferの上にあるやつのこと。Redshankもこれをmode lineと読んでいるから、結構用語が混乱しているのかも。

mode specification を info で調べて整理しよう。形式は、

-*- mode: MODENAME; VAR: VALUE; ... -*-

であり、VAR VALUEの組は、File Variablesと呼ぶものだ。これはこのファイルが読み込まれる際に自動的に解釈されてそのbufferのローカル変数となる。

さて、info の Emacs に 57.3.4.2 Safety of File Variables としてまさに疑問に答える節があった。これによると、

  • Emacsは、variable/value pairs について、safe なもの risky なもの、というようにグループ分けしている。
  • それによって、上記の確認画面が出たり出なかったりと制御している。
  • その制御は、enable-local-variables enable-local-eval と safe-local-eval-forms によってカスタマイズできる。

というわけで、内容を確認した上で、"y"を入力すればいいだけですね。

こつこつ。

2009年8月30日日曜日

端末で論理記号がずれる (3)

UnicodeとEmacsの仕様を多少読んでみた。

以前、EastAsian ambiguous width characters が根源、と書いたが、これは少し乱暴だった。

というのは、あたりまえなのですが、論理記号は EastAsian というカテゴリではないから。

端末上のEmacsを多少いじってみてわかったのだが、mathematical symbols と その supplemental なものどもについて、'small'とついているものが、half width であるというのがルールであるとするならば、単純に、Emacsとフォント(X?)の双方がUnicode標準に精確に準拠していないために発生していることがわかった。

で、そういうルールは無いということであれば、根源はEastAsianの場合と同じだ。

これ、keymapやabbrevをつかって ad hoc な解決はできるのだけど、やっぱり根本解決しないと気持ち悪い。しかし curses 含めて対応されるのは時間がかかりそう。。。

そろそろGtkなEmacsに移行すべきかもしれない。

2009年8月17日月曜日

端末で論理記号がずれる (2)

Webで調べた。Unicodeでいうと、

EastAsian ambiguous width characters

というところが問題の根源らしい。

Emacs上での対応状況は、

[mule-ja-2009:09575]

以下のスレッドにくわしい。

2009年1月28日水曜日

XMLを扱う (その7) [Atom]

Atomを例に名前空間の理解の確認を。

Atomでは、xhtmlの要素も使える。

それにはまずxhtmlの語彙を指定する。

---
namespace xhtml = "http://www.w3.org/1999/xhtml"
---

これで語彙は使えるようになるが、その語彙が母体たるAtomの中でどのよ
うな構造の一部となるかは、AtomのSchemaの中で指定しなければならない。

それにはまず、xhtml:*の形の要素の定義が必要。

---
# XHTML

anyXHTML = element xhtml:* {
(attribute * { text }
| text
| anyXHTML)*
}

xhtmlDiv = element xhtml:div {
(attribute * { text }
| text
| anyXHTML)*
}
---

それを母体の要素でどのように使えるかは次のように定義。

---
atomXHTMLTextConstruct =
atomCommonAttributes,
attribute type { "xhtml" },
xhtmlDiv

atomTextConstruct = atomPlainTextConstruct | atomXHTMLTextConstruct

atomTitle = element atom:title { atomTextConstruct }
---

これをatom上で利用するには次のよう。

---
...
<title type="xhtml" xmlns:xhtml="http://www.w3.org/1999/xhtml">
<xhtml:div>
Less: <xhtml:em> < </xhtml:em>
</xhtml:div>
</title>
...
<summary type="xhtml">
<div xmlns="http://www.w3.org/1999/xhtml">
This is <b>XHTML</b> content.
</div>
</summary>
...
<summary type="xhtml">
<xh:div xmlns:xh="http://www.w3.org/1999/xhtml">
This is <xh:b>XHTML</xh:b> content.
</xh:div>
</summary>
...
---

ふむ。理解に間違いはなさそうだ。
それにしても、

anyXHTML = element xhtml:* ...

と書けるRelax NGって便利だなぁ。


なかなかCLに辿りつけないが、こつこつ。