xyzzyのLisp用例

xyzzyのLispコードのサンプルです。

Lispコードのファイルをロードする。

Lispコードのファイルの内容をLispオブジェクトの形でLisp環境に取り込みます。ロードするファイルのコードは、Lisp式のソースコードかバイトコンパイル済みコードである必要があります。

以下は、各種ロード関係の関数の違い [引用: xyzzy Reference より] についてです。

load
インタプリタでloadします。
load-library
*.lcがあればそれをロードします。*.lcがなければ*.lをロードします。
autoload
関数1つ単位で、呼ばれたときロードするようにできます。関数が呼ばれるまではロードされません。
require
あるライブラリをロードします。ただし、既にロード済みならロードしません。
*modules*
この変数を見ると今どのモジュールがロード済か分かります。既にロード済だともうロードしません。

次の例では、foo.lというファイルをロードする。

(load "foo.l")

ロードパスの追加

load-library等でライブラリをロードする対象パスを*load-path*にリストで設定することもできます。

;; ライブラリをロードするパスを追加する。
(setq *load-path*
      (cons (merge-pathnames "bar" (user-homedir-pathname))
            *load-path*))

この例は、ユーザのホームディレクトリにあるbarというサブディレクトリもライブラリをロードする際の検索対象となる。但し、追加されるパスのサブディレクトリについては、検索対象から除外される。

.xyzzyから.xyzzy.lをロードする。

.xyzzyに大量のLispコードを記述する場合には、.xyzzy.lという別の名前のファイルへ内容をコピーして、それをバイトコンパイルし、.xyzzyでは下記の様にloadでバイトコンパイル済みファイル(.xyzzy.lc)をロードする記述のみしておくと良い。

(load ".xyzzy.lc")

この例は、次の様に工夫すると何かと便利である。

(defvar *init-file-name* (merge-pathnames ".xyzzy.l" (user-homedir-pathname)))
;; コンパイル済みファイルがあれば、それを対象とする。
(if (file-exist-p (concat *init-file-name* "c"))
    (setq *init-file-name* (concat *init-file-name* "c")))
;; Lispファイルのロード
(if (file-exist-p *init-file-name*)
    (load *init-file-name*)
  ;; .xyzzy.lファイルが無い場合は、デフォルトの初期化ファイルを利用する。
  ;; 但し、user-homedir-pathname と si:system-root が異なる場合のみ。
  (unless (equalp (user-homedir-pathname) (si:system-root))
    (load (merge-pathnames ".xyzzy" (si:system-root)))))

この例は、.xyzzy.lc(コンパイル済みの.xyzzy.l)ファイルがあればそれをロードし、コンパイル済みで無ければ.xyzzy.lをロードするが、それも無ければ全てのユーザ共通の初期化ファイルを(マルチユーザ環境の場合のみ)ロードする。

次の例では、前記と同様の結果を得ることができる。

(unless (equalp (user-homedir-pathname) (si:system-root))
  (setq *load-path*
        (cons (merge-pathnames "site-lisp" (user-homedir-pathname))
              *load-path*))
  )

(if (file-exist-p (merge-pathnames ".xyzzy.*" (user-homedir-pathname)))
    (require "../.xyzzy")
  (unless (equalp (user-homedir-pathname) (si:system-root))
    (load (merge-pathnames ".xyzzy" (si:system-root)))))

この例では、マルチユーザ環境であれば、*load-path*~/site-lispディレクトリを追加するので、当該ユーザの為のライブラリの管理にも便利である。

バックアップファイル

メニューバーのツールより共通設定を選択してバックアップファイルのタブでバックアップファイルを作成するの項目にチェックを入れることで、保存するファイルのバックアップファイルを作成することができます。

初期設定では、保存するファイルと同じディレクトリにバックアップファイルを作成しますが、これを好みに応じて変更することができます。

次のLispコードでは、全てのバックアップファイルは c:/backup-files/ の下に作成される。

;;; 特定フォルダに全てのバックアップファイルを作成する。
(require "backup")
(setq *backup-directory* "c:/backup-files/")
(setq *hierarchic-backup-directory* nil)

ディレクトリ毎にバックアップファイルの作成先を変更することも次のような記述で可能である。

;;; バックアップファイルの作成先を好みの場所に変更する。
(require "backup")
(setq *backup-directory*
      '(("d:/foo/" . "d:/backup-files-foo/")
        ("" . "d:/common-backup/")))
(setq *hierarchic-backup-directory* t)

この例は、d:/foo/bar.txt, d:/foo/bar/baz.txt 等、d:/foo/ で始まるファイルは、すべて d:/backup-files-foo/ の下にバックアップファイルが作成され、マッチしないファイルは d:/common-backup/ の下にバックアップファイルが作成される。詳細は、backup.lファイルのコメントを見ると良い。

因みに私の場合、次の様な設定でバックアップを利用している。

(require "backup")
(setq *backup-directory*
      ;; siteinit.l に設定があれば、ユーザ設定を上書き利用する。
      (list
       (cons (merge-pathnames "public_html" (concat "D:/home/" (user-name)))
             (merge-pathnames "public_html-backup/" (concat "D:/home/" (user-name))))
       '("" . "d:/common-backup/")
       ))
(setq *hierarchic-backup-directory* t)
参考
$XYZZY/lisp/backup.l

辞書

英和/和英辞書を組み込む

辞書の導入方法については、$XYZZY/etc/README.gendicファイルに記載があります。記載内容に従って、次の辞書を導入することで辞書機能を利用することができます。

辞書ファイル

注釈

EDICT 辞書は必須です。他の辞書はあってもなくてもかまいません。

参考
$XYZZY/etc/README.gendic

辞書選択メニュー

次のLispコードでは、辞書を選択することを可能にする。

;;; 辞書選択
;; 辞書の位置
(defvar *dictionary-eijiro-path* (merge-pathnames "edict/eijiro/" (si:system-root)))
(defvar *dictionary-gene-path* (merge-pathnames "edict/gene/" (si:system-root)))
;; メニュー定義
(setq *my-dictionary-popup-menu*
      (define-popup-menu
        (:popup nil "英和(&E)"
         (:item nil "英辞郎(&E)"
          #'(lambda ()
              (interactive)
              (setq *edict-dictionary-path* *dictionary-eijiro-path*))
          #'(lambda ()
              (if (path-equal *edict-dictionary-path* *dictionary-eijiro-path*)
                  :check)))
         (:item nil "GENE(&G)"
          #'(lambda ()
              (interactive)
              (setq *edict-dictionary-path* *dictionary-gene-path*))
          #'(lambda ()
              (if (path-equal *edict-dictionary-path* *dictionary-gene-path*)
                  :check)))
         )))
;; フローティングポップアップメニュー
(defun init-dictionary ()
  (interactive)
  (track-popup-menu *my-dictionary-popup-menu*))

このLispコードは、フローティングポップアップメニューにて辞書選択メニューを提供する。

更に、必要ならば次の例の様な記述を追加することで、辞書選択メニューを辞書のメニュー項目に追加することができる。

;; [ツール] → [辞書] にポップアップメニューを追加
(add-hook '*init-app-menus-hook*
          #'(lambda ()
              (add-popup-menu *dictionary-popup-menu*
                              *my-dictionary-popup-menu* "辞書の切り替え(&C)")))

他にも、辞書のツールバーを登録したい場合もあるだろう。

;; tool-bar: 辞書
(defun dictionary-tool-bar ()
  (create-tool-bar
   'dictionary-tool-bar
   (merge-pathnames "toolbar.bmp" (etc-path))
   '(("辞書" 36 edict-mode (lambda () (when edict-mode :check))))))
(define-command-bar 'dictionary-tool-bar "辞書引きモード(&D)")
参考
Memo/dictionary -- Xyzzy Wiki

各バーに表示する情報の設定

タイトルバーのフォーマットを設定する。

;; タイトルバーのフォーマット
;(setq-default title-bar-format "%p %v %#h - %#F") ; 標準
(setq-default title-bar-format "%b %#*(%M) [%k:%l] - %p %v%#h")

表示する情報を指定する文字列は、文字の並び順に表示されます。

モードラインのフォーマットを設定する。

;; モードラインフォーマット
;(setq-default mode-line-format "--%*- %b (%M) [%k:%l] %P %f") ; 標準
(setq-default mode-line-format "--%*- %b (%M) [%k:%l] %P %f [%i]")

表示する情報を指定する文字列は、タイトルバーのフォーマットと同様です。

ステータスバーのフォーマットを設定する。

;; ステータスバーに表示する情報
;(setq *status-bar-format* "T") ; 標準
(setq *status-bar-format* "cupT")

表示する情報を指定する文字列は、文字の並び順に表示されます。

パラメータについて

下記は、タイトルバーのフォーマット及びモードラインのフォーマットで表示する情報を指定する文字列の一覧である。

%*
**(変更あり)、%-(書込禁止)、%*(変更あり・書込禁止)、--(それ以外)
%#*
*(変更あり)、空白(変更なし)
%r
空白(書込可)、%(書込禁止)
%#r
空白(書込可)、%(書込禁止)、#(不完全バッファ)
%p
プログラム名
%v
バージョン
%h
ホスト名
%#h
@ホスト名
%b
バッファ名
%f
File: ファイル名
%#f
ファイル名
%F
File: ファイル名(ファイル名がなければバッファ名)
%#F
ファイル名(ファイル名がなければバッファ名)
%M
モード(マイナーモード含む)
%m
モード
%k
エンコーディング
%l
改行コード
%i
IMEの状態(mode-line-formatのみ)
%P
カーソル位置(mode-line-formatのみ)

下記は、ステータスバーのフォーマットで表示する情報を指定する文字列の一覧である。

t
時計(月/日 時:分)
p
カーソル位置(行:桁)
c
カーソル位置の文字コード(内部コード)
u
カーソル位置の文字コード(ユニコード)
T
時計(月/日(曜日) 時:分)
出典
$XYZZY/html/OChangeLog.html (Wed Aug 09 2000 Version 0.2.1.153)
xyzzy Reference

メニューを非表示にする。

次の例では、起動時からメニューを非表示にする。

;; 起動時からメニューを非表示
(add-hook '*post-startup-hook*
          #'(lambda ()
              (set-menu nil)))

メニュー表示状態切り替えスイッチ

次の例では、メニューの表示状態の切り替えを行う事ができる。

;;; メニューいらんよなの切り替えスイッチ
(add-hook '*init-app-menus-hook*
          #'(lambda ()
              (let ((toggle-app-menu *app-menu*))
                (defun toggle-app-menu ()
                  (interactive)
                  (set-menu (setq toggle-app-menu
                                  (unless toggle-app-menu *app-menu*)))))))
出典
メニューのカスタマイズ -- xyzzy の音

メニューにクローズボックス

次の例は、メニューにカレントバッファを閉じる為のクローズボックスを追加することができる。

;;; メニューにクローズボックス
(add-hook '*init-app-menus-hook*
          #'(lambda ()
              (add-menu-item *app-menu* 'close-box :close-box
                             #'kill-selected-buffer)))
出典
xyzzy [151]
$XYZZY/html/ChangeLog.html (Fri Feb 16 2001 Version 0.2.1.180)

表示状態切り替えメニュー

次の例では、フローティングポップアップメニューより選択された項目の表示状態を変更することができる。

;;; 表示状態切り替えメニュー
(defun my-apps-popup ()
  (interactive)
  (track-popup-menu
   (define-popup-menu
     (:item nil "メニュー(&A)"
      'toggle-app-menu)
     (:item nil "垂直スクロールバー(&V)"
      'toggle-vscroll-bar)
     (:item nil "水平スクロールバー(&H)"
      'toggle-hscroll-bar)
     (:item nil "行番号(&#)"
      'toggle-line-number)
     (:item nil "ルーラー(&+)"
      'toggle-ruler)
     (:item nil "折り返し(&F)"
      'toggle-fold-line)
     (:item nil "行カーソル(&O)"
      'toggle-cursor-line)
     (:item nil "モード行(&M)"
      'toggle-mode-line)
     (:item nil "ファンクションキー(&B)"
      'toggle-function-bar)
     (:item nil "リードオンリー(&R)"
      'toggle-read-only))))
;; C-RBtnUpで独自のポップアップメニューにします。
(global-set-key #\C-RBtnUp 'my-apps-popup)
;;; 表示状態切り替えメニュー
(defvar *my-toggle-popup-menu*
  (define-popup-menu
    (:item nil "行番号(&#)"
     'toggle-line-number
     #'(lambda ()
         (or (zerop (logand (get-window-flags) *window-flag-line-number*)) :check)))
    (:item nil "ルーラ(&+)"
     'toggle-ruler
     #'(lambda ()
         (or (zerop (logand (get-window-flags) *window-flag-ruler*)) :check)))
    (:item nil "モード行(&M)"
     'toggle-mode-line
     #'(lambda ()
         (or (zerop (logand (get-window-flags) *window-flag-mode-line*)) :check)))
    ;------------------------------
    :sep
    (:popup nil "ファンクションキー"
     (:item nil "表示しない(&N)"
      'toggle-function-bar
      #'(lambda ()
          (and (zerop (logand (get-window-flags) ed::*window-flag-function-bar*)) :check)))
     :sep
     (:item nil "&4個"
      #'(lambda ()
          (interactive)
          (set-number-of-function-bar-labels 4))
      #'(lambda ()
          (if (= 4 (number-of-function-bar-labels))
              :check
            )))
     (:item nil "&5個"
      #'(lambda ()
          (interactive)
          (set-number-of-function-bar-labels 5))
      #'(lambda ()
          (if (= 5 (number-of-function-bar-labels))
              :check
            )))
     (:item nil "&8個"
      #'(lambda ()
          (interactive)
          (set-number-of-function-bar-labels 8))
      #'(lambda ()
          (if (= 8 (number-of-function-bar-labels))
              :check
            )))
     (:item nil "1&0個"
      #'(lambda ()
          (interactive)
          (set-number-of-function-bar-labels 10))
      #'(lambda ()
          (if (= 10 (number-of-function-bar-labels))
              :check
            )))
     (:item nil "1&2個"
      #'(lambda ()
          (interactive)
          (set-number-of-function-bar-labels 12))
      #'(lambda ()
          (if (= 12 (number-of-function-bar-labels))
              :check
            )))
     (:item nil "&15個"
      #'(lambda ()
          (interactive)
          (set-number-of-function-bar-labels 15))
      #'(lambda ()
          (if (= 15 (number-of-function-bar-labels))
              :check
            )))
     )
    ))

(defun toggle-setting-menu ()
  (interactive)
  (track-popup-menu *my-toggle-popup-menu*))

(global-set-key #\C-RBtnUp 'toggle-setting-menu)

(add-hook '*init-app-menus-hook*
          #'(lambda ()
              (let ((view (get-menu *app-menu* 'ed::view)))
                (insert-popup-menu view 5 *my-toggle-popup-menu* "表示する?(&V)")
                )))

ミニバッファに入ったときIMEをOFFにする

次の例では、ミニバッファに入ったときIMEを自動的にOFFにすることができる。

;;; ミニバッファに入ったときIMEをOFFにする
(export '(*ime-mode-into-minibuffer*))
(defvar *ime-mode-into-minibuffer* nil)

(defun ime-state-get-and-setoff (bef-buffer file-name)
  (interactive)
  (setq *ime-mode-into-minibuffer* (get-ime-mode))
  (toggle-ime nil))

(defun ime-state-set (bef-buffer file-name)
  (interactive)
  (toggle-ime *ime-mode-into-minibuffer*))

(add-hook '*enter-minibuffer-hook* 'ime-state-get-and-setoff)
(add-hook '*exit-minibuffer-hook* 'ime-state-set)
出典
バッファーリスプ系 -- しょぼしょぼすくりぷと

C-z でアイコン化

次の例では、xyzzy自身をEmacs同様にC-zキーでタスクバーにアイコン化する方法を示す。

;;; C-z でアイコン化
(require "wip/winapi")
(c:define-dll-entry winapi:BOOL ShowWindow (winapi:HWND c:int) "user32")
(global-set-key #\C-z #'(lambda () (interactive)
                          (ShowWindow (get-window-handle) 6)))

同様に、タスクトレイ(タスクバーの通知領域)にアイコンを表示したいのであれば、ttrayを導入すると良い。

出典
xyzzy [36]
xyzzy Reference

ファイラ

取り敢えず設定例のみ。

ファイラの各種設定

ファイラの初期ディレクトリ

;; ファイラの初期ディレクトリ
(setq *filer-primary-directory* (si:system-root)) ; 左側
(setq *filer-secondary-directory* (user-homedir-pathname)) ; 右側

ファイラの初期ファイルマスク

;; ファイラの初期ファイルマスク
;; 2画面用
(setq *filer-primary-file-mask* '("*"))   ; 左側
(setq *filer-secondary-file-mask* '("*")) ; 右側
;; 1画面用
(setq *filer-last-file-mask* '("*"))

ファイラのパスマスクリスト

;; ファイラのパスマスクリスト
(setq *filer-path-masks*
      '(("すべてのファイル" "*")
        ("ドキュメント" "*.doc" "*.txt" "*.man" "*readme*")
        ("C/C++" "*.c" "*.h" "*.cpp" "*.cxx" "*.cc" "*.inl")
        ("Lisp" "*.l" "*.el" "*.lsp" "*.lisp")
        ("Visual Basic" "*.bas" "*.frm" "*.vbp")
        ("実行ファイル" "*.exe" "*.com" "*.bat" "*.pif")
        ("アーカイブ" . ("*.lzh" "*.zip" "*.arj" "*.tar" "*.bz2" "*.gz"
                     "*.Z" "*.tbz" "*.taz" "*.tgz" "*.cab" "*.rar"
                     "*.gza" "*.bza" "*.yz1" "*.7z"))
        ("バックアップ" "*~" "*.bak")
        ("自動セーブ" "#*#")))

削除時のゴミ箱使用

;; 削除時のゴミ箱使用
(setq *filer-use-recycle-bin* t)

ファイラのステータスウィンドウへのファイル名の表示

;; ファイラのステータスウィンドウへのファイル名の表示
(setq *filer-echo-filename* t)

ファイラのジャンプ用のディレクトリ

;; ファイラのジャンプ用のディレクトリ(連想リスト)
(setq *filer-directories*
      (list
       (cons "home" (concat "D:/home/" (user-name)))
       (cons "homedir" (user-homedir-pathname))
       (cons "xyzzy" (si:system-root))
       (cons "lisp" (merge-pathnames "lisp" (si:system-root)))
       (cons "site-lisp" (merge-pathnames "site-lisp" (si:system-root)))
       (cons "Windows" (get-windows-directory))
       ;(cons "System" (get-system-directory))
       (cons "DeskTop" (get-special-folder-location :desktop))
       (cons "Personal" (get-special-folder-location :personal))
       ;(cons "Program Files" (get-special-folder-location :programs))
       ;(cons "Recent" (get-special-folder-location :recent))
       ;(cons "SendTo" (get-special-folder-location :send-to))
       ;(cons "Start Menu" (get-special-folder-location :start-menu))
       ;(cons "Startup" (get-special-folder-location :startup))
       ;(cons "ShellNew" (get-special-folder-location :templates))
       (cons "Temp" (or (map-backslash-to-slash (si:getenv "TEMP"))
                        (map-backslash-to-slash (si:getenv "TMP"))))
       (cons "public_html"
             (merge-pathnames "public_html" (concat "D:/home/" (user-name))))
       '("share" . "d:/share/")
       ))

ファイラの送るのリンク先

;; ファイラの送るのリンク先
(setq *filer-send-to-list*
      (list
       '("C:/" . "C:/")
       '("D:/" . "D:/")
       (cons "homedir" (user-homedir-pathname))
       ))

ファイラのガイドテキスト

;; ファイラのガイドテキスト
(setq *filer-guide-text*
      '("A:属性  C:コピー  D:削除  E:解凍  F:検索  J:DIR移動  \
K:mkdir  L:ドライブ  M:移動  N:ファイル名  O:圧縮  P:DIR??"
        "R:名前変更  S:DIR??  T:ショートカット  U:DIRサイズ  V:リスト  X:実行  .:マスク  \
/:マーク  *:load  Home:トグル  S-Home:クリア  End:リロード  F3:実行  M-h:ヘルプ"))

ファイラのガイドテキストを表示する必要の無い場合には、次の様に変数の値をnilと示せば良い。

(setq *filer-guide-text* nil)
;;; ガイドテキストをポップアップ表示
(setq *popup-filer-guide-text*
      (concat
       "A:属性\t\tB:バイトコンパイル\tC:コピー\t\tD:削除\t\tE:解凍\n"
       "F:検索\t\tG:ファイル名検索\tJ:DIR移動\tK:mkdir\t\tL:ドライブ\n"
       "M:移動\t\tN:ファイル名\tO:圧縮\t\tP:DIR??\t\tQ:終了\n"
       "R:名前変更\tS:DIR??\t\tT:ショートカット\tU:DIRサイズ\tV:リスト\n"
       "W:閲覧\t\tX:実行\t\tY:ショートカット\tZ:プロパティ\n"
       "\n"
       "*:load\t\t.:マスク\t\t/:マーク\t\t<:先頭\t\t>:末尾\n"
       "@:別名コピー\t\:ルート\t\t=:比較\t\t^:イジェクト\t]:送る\n"
       "\n"
       "C-h:上ディレクトリ\tC-r:後isearch\tC-s:前isearch\tC-u:ディレクトリサイズ\n"
       "C-1:ファイル広\tC-2:サイズ広\tC-3:日時広\tC-4:属性広\n"
       "C-M-1:ファイル狭\tC-M-2:サイズ狭\tC-M-3:日時狭\tC-M-4:属性狭\n"
       "\n"
       "M-g:grep\tM-r:gresreg\tM-v:リードオンリー\n"
       "\n"
       "F3:実行\t\tF5:マークトグル\tF6:ソート\t\tS-F10:ポップアップメニュー\n"
       "\n"
       "TAB:移動\tSPC:マーク\n"
       "Home:トグル(ファイル)\tS-Home:クリア\tC-Home:トグル(含Dir)\tS-C-Home:全ファイルマーク\n"
       "End:リロード\n"
       "\n"
       ))

(define-key filer-keymap #\M-h
            #'(lambda () (interactive)
                (message-box *popup-filer-guide-text*)
                ))

追加登録しているキーがあれば、次の様に記述しておくと良い。

;; カスタマイズ
(setq *popup-filer-guide-text*
      (concat
       *popup-filer-guide-text*
       "\n"
       "M-f:diff\t\tM-h:ガイド\tM-j:dir選択\tM-s:小文字\t"M-x:実行\n"
       "M-Home:トグル(Dir)\n"
       "\n"
       ))
出典
ファイラ -- xyzzy の音

大文字のファイル名をファイラで一括して小文字へ

;;; 大文字のファイル名をファイラで一括して小文字へ
(defun filer-downcase-filename ()
  (let ((files (filer-get-mark-files)))
    (when (and files (yes-or-no-p "小文字にしまっせ"))
      (filer-subscribe-to-reload (filer-get-directory))
      (mapc #'(lambda (x) (rename-file x (string-downcase x))) files)
      (filer-demand-reload)
      (filer-goto-file (file-namestring (car files))))
    t))
(define-key filer-keymap #\M-s 'filer-downcase-filename)
出典
ファイラ -- xyzzy の音

ディレクトリ全部を選択

;;; ディレクトリ全部を選択
(defun filer-directory-select ()
  (filer-mark-all nil)
  (filer-toggle-mark-files))
(define-key filer-keymap #\M-Home 'filer-directory-select)
出典
ファイラ -- xyzzy の音

二画面ファイラから選択してテキストの比較

;;; 二画面ファイラから選択してテキストの比較
(defun my-filer-diff-file ()
  (let ((file1 (ed::filer-fetch-file nil nil))
        (file2 (ed::filer-fetch-file nil t)))
    (unless (and file1 file2)
      (error "diffするファイルを指定して"))
    (diff file1 file2)
    (and (find-buffer ed::*diff-new-buffer-name*)
         (find-buffer ed::*diff-old-buffer-name*)
         (filer-cancel))))
(define-key filer-keymap #\M-f 'my-filer-diff-file)
出典
tips -- 66MHz.com

ディレクトリ選択ダイアログ

;;; ディレクトリ選択ダイアログ
(define-key filer-keymap #\M-j
            #'(lambda ()
                (setq dir (directory-name-dialog :title "ディレクトリ移動"
                                                    :default (filer-get-directory)))
                (when dir
                  (filer-set-directory dir nil)
                  (filer-reload))))

ファイラの起動方法の拡張

一画面ファイラから二画面ファイラを開く

;;; 一画面ファイラから二画面ファイラを開く
(defun filer-open-dual-window ()
  (interactive)
  (unless (filer-dual-window-p)
    (let ((*filer-primary-directory* (filer-get-directory))
          (*filer-secondary-directory* (filer-get-directory)))
      (filer-cancel)
      (open-filer))))
(define-key filer-keymap #\M-2 'filer-open-dual-window)
出典
ファイラ -- xyzzy の音

一画面ファイラの表示

;;; 一画面ファイラの表示
;; 現在開いているファイルのディレクトリを表示する。
(defun open-single-filer ()
  (interactive)
  (toggle-ime nil)
  (multiple-value-bind (files result)
      (filer nil t nil nil)
    (when result
      (dolist (f files t)
        (unless (file-directory-p f)
          (find-file f)
          (add-history f '*minibuffer-file-name-history*))))))
(define-key ctl-x-map #\d 'open-single-filer)
出典
ファイラ -- xyzzy の音

エクスプローラの表示

;;; エクスプローラの表示
(defun open-explorer ()
  (interactive)
  (call-process
   (concat "c:/windows/EXPLORER.EXE /e," ; for Windows 9x/Me
           ;; 現在開いているファイルのディレクトリ
           (map-slash-to-backslash
            (directory-namestring (or (get-buffer-file-name)
                                      (si:system-root)))
            ))))

ファイラ選択メニュー

;;; ファイラ選択メニュー
(add-hook '*init-app-menus-hook*
          #'(lambda ()
              (let ((tools (get-menu *app-menu* 'ed::tools)))
                ;; [ツール] → [ファイラ] のカスタマイズ
                (delete-menu tools 18 t) ; 元々のメニューを削除
                (insert-popup-menu tools 18
                                   (define-popup-menu
                                     (:item nil "二画面ファイラ(&D)" 'open-filer)
                                     (:item nil "一画面ファイラ(&C)" 'open-single-filer)
                                     (:item nil "エクスプローラ(&E)" 'open-explorer)
                                     ) "ファイラ(&F)..."))))

ファイラから「ファイルの実行」後にファイラを閉じる

;;; ファイラから「ファイルの実行」後にファイラを閉じる
(define-key filer-keymap #\M-x
            #'(lambda ()
                (interactive)
                (ed::filer-shell-execute)
                (ed::filer-cancel)))
参考
ファイラ -- xyzzy の音

起動時のディレクトリ

次の例は、find-file するときに最初に表示されるディレクトリをホームディレクトリに設定している。

(cd "~/")

上記の例は、xyzzyでは次の様に記述することもできる。

(set-default-directory "~/")

これらの例は、作業中のバッファのファイルパスが無効の場合にのみ有効である。

バイトコンパイルを便利にする。

カレントバッファのファイルをバイトコンパイル

;;; カレントバッファのファイルをバイトコンパイル
(defun byte-compile-this-file ()
  (interactive)
  (if (string= "l" (pathname-type (get-buffer-file-name)))
      (byte-compile-file (get-buffer-file-name))))

siteinit.lのバイトコンパイルとダンプファイルの削除

;;; siteinit.lのバイトコンパイルとダンプファイルの削除
(defun compile-and-delete-dump-file ()
  (interactive)
  (and (find-buffer "siteinit.l")
       (eval-buffer "siteinit.l"))
  (byte-compile-file
   (concat (si:system-root) "site-lisp/siteinit.l"))
  (let ((dumpfile
         (concat (si:system-root) "xyzzy."
                 (case (os-platform)
                   (whistler "wxp")
                   (windows-2000 "w2k")
                   (windows-nt "wnt")
                   (windows-me "wme")
                   (windows-98 "w98")
                   (windows-95 "w95")
                   (win32s "32s")
                   (t "nt")))))
    (and (file-exist-p dumpfile)
         (delete-file dumpfile)
         (princ (concat "delete " (file-namestring dumpfile) "..."))))
  (princ "done.\n"))
(global-set-key '(#\C-c #\b) 'compile-and-delete-dump-file)
出典
xyzzy Note -- HIE no Page
;;; siteinit.lのバイトコンパイルとダンプファイルの削除
(defun byte-compile-and-delete-dump-file ()
  (interactive)
  (and (find-buffer "siteinit.l")
       (eval-buffer "siteinit.l"))
  (byte-compile-file
   (merge-pathnames "site-lisp/siteinit.l" (si:system-root)))
  (let ((path (namestring (si:dump-image-path))))
    (and (file-exist-p path)
         (princ (concat "delete "
                        (if (path-equal (directory-namestring path) (si:system-root))
                            (file-namestring path)
                          path)
                        "..."))
         (delete-file path)))
  (princ "done.\n"))
(global-set-key '(#\C-c #\b) 'byte-compile-and-delete-dump-file)

この例では、起動時の引数に [-config config-directory] を指定していてもダンプファイルの削除が行える。

全てのバッファのファイルをバイトコンパイル

;;; bufferら(*.l)をコンパイル
(defun byte-compile-open-buffers()
  (interactive)
  (let ((b-n) (error-msges))
    (with-output-to-temp-buffer ("*byte-compile*" nil)
      (dolist (a-b (buffer-list))
        (setq b-n  (get-buffer-file-name a-b))
        ;(pathname-type(file-namestring b-n))
        (if(and b-n
                (string= "l" (pathname-type b-n)))
            (if ;(msgbox "do ~A" b-n)
                (byte-compile-file b-n)
                (setq error-msges (concat error-msges "\n compiled:" b-n))
              ;(setq error-msges (concat error-msges "\n not :" b-n))
              )
          )))
    (msgbox "do compile\n~A" error-msges)))
出典
バッファーリスプ系 -- しょぼしょぼすくりぷと

保存時に自動的にバイトコンパイル

;;; 保存時に自動的にバイトコンパイル
(add-hook '*after-save-buffer-hook*
          #'(lambda ()
              (interactive)
              (let ((bn (get-buffer-file-name)))
                (if (and (string= "l" (pathname-type bn))
                         (file-exist-p (format nil "~Ac" bn)))
                    (if (path-equal bn (merge-pathnames "site-lisp/siteinit.l" (si:system-root)))
                        (byte-compile-and-delete-dump-file)
                      (save-excursion
                        (byte-compile-file bn)))))))

バッファ

デバッグ

(defun debug ()
  (interactive)
  (setq *error-output* (make-buffer-stream (create-new-buffer "*Stack Trace*")))
  (setq si:*trace-on-error* t))

emacs 風のバッファ名指定

以下を .xyzzy に書いておけば emacs 風のバッファ名指定ができる。

;; emacs 風のバッファ名指定
(pushnew '(#\B . emacs-interactive-buffer-name)
         *interactive-specifier-alist* :test #'equal)
(pushnew '(#\b . emacs-interactive-exist-buffer-name)
         *interactive-specifier-alist* :test #'equal)
参考
$XYZZY/lisp/buffer.l (241行辺り)

漢字コード・改行コードの初期設定

次の例は、デフォルトの漢字コードをEUC-JP、改行コードをLFに設定している。

;; 漢字コード・改行コードの初期設定(euc-jp/lf)
(setq *default-fileio-encoding* *encoding-euc-jp*
      *default-eol-code* *eol-lf*)
参考
$XYZZY/lisp/encoding.l

*scratch* バッファ

Lispコードを評価する

M-x: eval-buffer
当該バッファ全体のLispを評価します。
eval-print-last-sexp
行末で実行することで、行毎にLispを評価します。また、評価の結果をバッファに出力します。
キー設定は、C-j にバインドされています。
eval-last-sexp
行末で実行することで、行毎にLispを評価します。
キー設定は、C-x C-e にバインドされています。
M-x: eval-region
リージョン間のLispを評価します。任意の場所を評価したい場合に便利です。
eval-defun
ポイントの位置付近のLisp式を評価します。
キー設定は、C-M-x にバインドされています。
eval-expression
Lisp式を評価します。対話的に呼び出された場合はミニバッファで入力された式を評価します。
キー設定は、ESC-ESC にバインドされています。

*scratch* バッファの削除許否の設定

;;; *scratch* バッファの削除許否 [t:許|nil:否] の設定
(setq *kill-buffer-kills-scratch* t)

デフォルトでは、nil になっています。

*scratch* バッファを自動で保存・復元する。

;;; *scratch* バッファを自動で保存・復元する。
;; *scratch* バッファの漢字コード・改行コードの設定
(save-excursion
  (set-buffer "*scratch*")
  (change-fileio-encoding *encoding-euc-jp*) ; EUC-JP
  (change-eol-code *eol-lf*)) ; LF
;; *scratch* を終了時に保存
(add-hook '*kill-xyzzy-hook*
          #'(lambda ()
              (set-buffer (find-buffer "*scratch*"))
              (write-file "~/.scratch")))
;; *scratch* を起動時に復元
(add-hook '*post-startup-hook*
          #'(lambda ()
                (let ((file "~/.scratch"))
                  (when (file-exist-p file)
                    (set-buffer (find-buffer "*scratch*"))
                    ;(erase-buffer (selected-buffer))
                    (insert-file-contents file t)
                    (message "*scratch* restored")))))

内容をより強化した scratch-plus.l を配布中です。

ウインドウ

フォーカスのないウィンドウで右クリックするとそれを閉じる

;;; フォーカスのないウィンドウで右クリックするとそれを閉じる
(defun mouse-right-press (&optional apps)
  (interactive)
  (if (eq (selected-window) *last-mouse-window*)
      (mouse-menu-popup apps)
    (let ((l (selected-window)))
      (set-window *last-mouse-window*)
      (delete-window)
      (set-window l)
      (cancel-mouse-event))))
(global-set-key #\RBtnUp 'mouse-right-press)
出典
まいくろちっぷすxyzzy部門 -- Micro Tips
(setq *popup-completion-list-default* :always)
(setq *minibuffer-popup-completion-list* :always)

尚、各変数の値を :always では無く :never にすると、初期値同様の*Completion*バッファでの表示となる。

出典
$XYZZY/html/ChangeLog.html (Tue Sep 25 2001 Version 0.2.2.211)
xyzzy Reference

編集

一発インデント

次の例は、バッファ全体を一発でインデントし直すのに便利である。

;;; 一発インデント
(defun indent-current-buffer ()
  (interactive)
  (when mode-specific-indent-command
    (indent-region (point-min) (point-max))
    (message "indent buffer")))
(global-set-key #\C-F8 'indent-current-buffer)
(set-function-bar-label #\C-F8 "一発インデント")

一発インデントの為のツールバーが必要ならば、次の例の様な記述を追加しておくと良いだろう。

;;; tool-bar: 一発インデント
(defun indent-current-buffer-tool-bar ()
  (create-tool-bar
   'indent-current-buffer-tool-bar
   (merge-pathnames "toolbar.bmp" (etc-path))
   '(("一発インデント" 32 indent-current-buffer (lambda () (or mode-specific-indent-command :disable))))))
(define-command-bar 'indent-current-buffer-tool-bar "一発インデント(&I)")
参考
xyzzy [141]
;;; バッファ全体のインデント
(defun indent-buffer ()
  (interactive)
  (when mode-specific-indent-command
    (save-excursion
      (goto-char (point-min))
      (funcall mode-specific-indent-command)
      (indent-region (point-min) (point-max)))))
出典
xyzzy Part12 [538]

タブ <=> スペース変換

リージョンを選択し、M-x: tabify でスペースをタブに、M-x: untabify でタブをスペースに変換できます。

また、セレクションでは、M-x: tabify-selection 及び M-x: untabify-selection で相互に変換が行えます。同様に 編集変換 メニューからも実行できます。

地味な機能ですが、覚えておくと非常に便利です。

ナローイングした領域の表示設定

;; ナローイングした領域の表示状態
(setq hide-restricted-region nil)

ナローイングした領域の表示状態は、デフォルト設定と同じ nil ならば薄く表示し、non-nil ならば非表示となる。

セレクションでナローイング

リージョンを指定して、C-x n (narrow-to-region) とすると、指定した範囲以外を移動・編集できないようにすることができます。

以下の例では、セレクションで範囲の指定を行いナローイングすることができる。

;;; セレクションでナローイング
(defun narrow-to-selection ()
  (interactive "*")
  (let ((type (get-selection-type)))
    (if type
      (let ((pre (pre-selection-p)))
        (selection-start-end (start end)
            (narrow-to-region start end)
            (cond ((< start end)
                   (goto-char (point-min))
                   (start-selection type pre (point-max)))
                  (t
                   (goto-char (point-max))
                   (start-selection type pre (point-min))))))
      (error "範囲が選択されていません。"))))

ワイディング(制限された領域を元に戻す)操作は narrow-to-region と同じく C-x w (widen) です。

モード関連

デフォルトのモード

次の例では、新規に作成したバッファのデフォルトのモードをtext-modeにする。

;; デフォルトのモード
(setq *default-buffer-mode* 'text-mode)

特定の処理に対し、処理を追加する。

次の例では、テキストモードやそれに関するモードでは、自動詰め込みモードを有効にする。

(add-hook '*text-mode-hook*
          '(lambda () (auto-fill-mode t)))

これは、ノーマルフック変数にフック関数を追加する場合の一例である。フックとは、ある特定の状況で既存のプログラムから呼び出される関数/関数群を格納しておく変数のことで、xyzzyには、設定用のフックが数多くあります。

特定のファイルに対し、メジャーモードを指定する。

ファイルの名称や拡張子とメジャーモードとの対応関係は、*auto-mode-alist*変数に格納されます。

次の例では、ファイルを開く際に.txtというファイル拡張子ならば、自動的にtext-modeになる。

(setq *auto-mode-alist*
      (append '(("\\.txt$" . text-mode))
              *auto-mode-alist*)

次の例では、前記と同様の結果を得ることができる。

(pushnew '("\\.txt$" . text-mode) *auto-mode-alist*)

また、複数のファイルや拡張子に対する指定を同時に加えるのであれば、次の様に記述すると良い。

(setq *auto-mode-alist*
      (append '(("\\.\\(xht[ml]?\\|rdf\\|rss\\)" . xml-mode)
                ("\\.s?html?" . html-mode))
              *auto-mode-alist*)

次の例では、前記と同様の結果を得ることができる。

(pushnew '("\\.\\(xht[ml]?\\|rdf\\|rss\\)" . xml-mode) *auto-mode-alist*)
(pushnew '("\\.s?html?" . html-mode) *auto-mode-alist*)

キーワードファイルの場所指定

(setq *keyword-load-path* '("~/keywords"))

この例では、キーワードファイルを使う場合に、ユーザのホームディレクトリにある keywordsディレクトリ内に格納されたキーワードファイルを優先的に使用することができる。

shell-modeでCygwinのbashを使用する。

(setq *eshell* "bash -i")
(setq *shell-command-option* (concat "/E:2048" *shell-command-option*))

shell-modeでCygwinのbashを使用する場合には、Cygwinをインストールし、環境変数のPATHとSHELLを適切に設定しておく必要ある。

PATH
$PATH;d:\cygwin\bin;d:\cygwin\usr\local\bin;
SHELL
/bin/bash

尚、Cygwinについての詳細は、本サイト内のCygwin備忘録をご覧下さい。

インクリメンタルサーチ

インクリメンタルサーチを使うには、初期化ファイルに次のコードを追加すると良い。

(require "isearch")

dabbrev

(require "dabbrev")
(global-set-key #\M-/ 'dabbrev-expand)
(global-set-key #\C-\; 'dabbrev-popup)

dabbrev-popupについては、補完の候補のポップアップ設定もしておくと良い。

英語のスペルチェック(Ispell)

英語のスペルチェックを行いたい場合には、ispellが必要になります。最も手っ取り早いのは、xyzzyの作者・亀井氏のサイトにて入手できる Ispell for Win32 を導入することです。

Ispellを導入したら、初期化ファイルに実行ファイルのパスを次のように指定しておきましょう。

;; Ispell --- スペルチェック
(setq *ispell-command*
      (map-slash-to-backslash (merge-pathnames "bin/ispell.exe" (si:system-root))))

また、ツールバーを登録しておくと手軽にIspellを使用できます。

;; Ispell --- ツールバー
(defun ispell-tool-bar ()
  (create-tool-bar
   'ispell-tool-bar
   (merge-pathnames "toolbar.bmp" (etc-path))
   '(("ispell" 15 (lambda () (interactive)
                    (ed::map-selection #'ispell-region)) :selection))))
(define-command-bar 'ispell-tool-bar "Ispell(&I)")

尚、ツールバーを削除したい場合には、ESC-ESCとキーを押してミニバッファに Eval: と表示されたら (delete-command-bar 'ispell-tool-bar) と入力し、Enterキーを押します。最後にIspellの為のツールバーの記述を削除してください。

テキストの比較(diff)

xyzzyにてテキストの比較を行いたい場合には、diffが必要になります(diff関連の拡張Lispを導入する場合も同様)。その際、Cygwinを導入してそのdiff.exeを使うのも良いが、態々Cygwinを導入したくないならば、Cygwinから必要なファイルだけを抜き出して使う方法もあるので、その方法を次に説明する。

尚、Cygwinを導入する際には、本サイト内のCygwin備忘録を参考にしてみて下さい。

  1. $XYZZY/bin ディレクトリを作成する。
  2. diff.exe, cygwin1.dll, cygintl-1.dll$XYZZY/bin ディレクトリに置く。
  3. $XYZZY/site-lisp/siteinit.lに下記のLispコードを書いておく(要:再ダンプ)。
  4. diffを使用する場合は、M-xdiff
;; diff --- テキストの比較
(in-package "editor")
(setq *diff-command-name*
      (map-slash-to-backslash (merge-pathnames "bin/diff.exe" (si:system-root))))
(in-package "user")

注釈

GNU patch 2.5.4 と GNU diff 2.7 を Win32 用に Make した GNU patch GNU diff for Win32 を使用すれば、Cygwinから必要なファイルだけを抜き出す手間が省けます。

css-mode

css-modeで@規則や最重要指定に色付けする。

css-modeでCSS2@規則@import@pageなど)や最重要指定!important)を色付けしたい場合には、初期化ファイルにシンタクッステーブルを指定すると良い。

;; @規則や!に色付けする。
(set-syntax-word ed::*css-mode-syntax-table* #\@)
(set-syntax-word ed::*css-mode-syntax-table* #\!)

更に、キーワードファイル(*keyword-load-path*/CSS)にキーワードを下記例の様に追加しておく必要がある。

···
;;; At-rules
;*0b
@charset
@font-face
@import
@media
@page
;;; Inheritance
;*2b
!important
inherit
···

css-mode 強化版

css-enhance.l
xyzzyでタグ打ってる人の数 [339-340] に掲載のサンプルを、autoload で利用可能な様にちょっとだけ手を加えたもの。

CSS Validator を使って構文チェックする。

W3C CSS Validation Service より CSS Validator のソースを入手して導入することで、CSSの構文チェックが気軽に行えます。これをxyzzyのcss-modeで利用できる様にすると非常に便利です。

次の例では、カレントバッファのモードがcss-modeの時、CSS Validator コマンドラインヴァージョン(validator.zip)を利用したCSSの構文チェックを行える。

;;; CSS Validator
          ;; for the Command line version
          (add-hook 'ed::*css-mode-hook*
          #'(lambda ()
          (defvar *css-validator-file* "D:/usr/local/CssValidator.bat")
          (defun css-validator-exec ()
          (interactive)
          (let ((file (get-buffer-file-name)))
          (when file
          (pipe-command
          (format nil "~A ~A"
          (map-slash-to-backslash *css-validator-file*)
          (map-slash-to-backslash file))))))
          (define-key ed::*css-mode-map* '(#\C-c #\v) 'css-validator-exec)))

この例で用いているCssValidator.batの内容は、次の様なものである。

@echo off
          set classpath=D:\usr\local\css-validator\validator.zip
          Java org.w3c.css.css.StyleSheetCom %1
          rem pause

次の例では、カレントバッファのモードがcss-modeの時、CSS Validator サーヴレットヴァージョン(sites.zip)を利用したCSSの構文チェックが行える。

;;; CSS Validator
          ;; for the Servlet version
          (add-hook 'ed::*css-mode-hook*
          #'(lambda ()
          (defvar *css-validator-string*
          "http://127.0.0.1:8001/servlet/css-validator/validator?warning=2&uri=")
          (defun css-validator-servlet ()
          (interactive)
          (let ((file (get-buffer-file-name)))
          (when file
          (shell-execute (concat *css-validator-string* file) t)
          )))
          (define-key ed::*css-mode-map* '(#\C-c #\C-v) 'css-validator-servlet)))

この例では、デフォルトのブラウザに検証結果を表示するが、browser.dll或いはbrowser.dll 拡張版 + browserexを活用する場合には、当該行を次の様に修正することでxyzzy上に表示することもできる。

;(shell-execute (concat *css-validator-string* file) t)
          (bx:close-browser)
          (bx:navigate (concat *css-validator-string* file))

この例は、browserexを活用することができる。

注釈

  • 上記のLispコードの動作には、CSS Validator version 2.0 を用いています。
  • ローカル環境でJigsawと連動しての実行やコマンドラインでの実行を行う為には、CSS Validator を予め導入しておく必要があります。(現在ダウンロードより、sites.zip及びvalidator.zip、各zipファイルへの参照リンクは消滅しています。)
  • CSS Validator の導入及び使用方法については、RUN日本語版)をご覧下さい。

lisp-mode

-*- encoding: UTF-8N -*- 認識

(setf (gethash "UTF-8N" *mime-charset-name-hash-table*) *encoding-utf8n*)

html-mode

Another HTML-lint を使って構文チェックする。

Another HTML-lint のソースを入手して導入することで、HTMLの文法チェックが気軽に行えます。これをxyzzyのhtml-modeで利用できる様にすると非常に便利です。

次の例では、カレントバッファのモードがhtml-modeの時、AHL コマンドラインヴァージョン(htmllint)を利用したHTMLの構文チェックを行える。

;;; Another HTML-lint
;; for the Command line version
(add-hook 'ed::*html-mode-hook*
          #'(lambda ()
              (defvar *htmllint-file* "D:/usr/local/htmllint/htmllint")
              (defun htmllint-exec ()
                (interactive)
                (let ((file (get-buffer-file-name (selected-buffer))))
                  (when file
                    (pipe-command
                     (format nil "perl \"~A\" \"~A\""
                             (map-slash-to-backslash *htmllint-file*)
                             (map-slash-to-backslash file))))))
              (define-key ed::*html-mode-map* '(#\C-c #\l) 'htmllint-exec)))

次の例では、カレントバッファのモードがhtml-modeの時、AHL ゲートウェイCGIヴァージョン(htmllint.cgi)を利用したHTMLの構文チェックが行える。

;;; Another HTML-lint
;; for the gateway version
(add-hook 'ed::*html-mode-hook*
          #'(lambda ()
              (defvar *htmllint-string*
                "http://127.0.0.1/htmllint/htmllint.cgi?V;X=w3m;URL=")
              (defun htmllint-cgi ()
                (interactive)
                (let ((file (get-buffer-file-name)))
                  (when file
                    (shell-execute (concat *htmllint-string* file) t)
                    )))
              (define-key ed::*html-mode-map* '(#\C-c #\C-l) 'htmllint-cgi)))

この例では、デフォルトのブラウザに検証結果を表示するが、browser.dll或いはbrowser.dll 拡張版 + browserexを活用する場合には、当該行を次の様に修正することでxyzzy上に表示することもできる。

;(shell-execute (concat *htmllint-string* file) t)
(bx:close-browser)
(bx:navigate (concat *htmllint-string* file))

この例は、browserexを活用することができる。また、html+-modeを導入しそれで利用したい場合には、html-modeに関する記述部分を変更する必要がある。

html+-modeを導入する際にsiteinit.lに追加するLispコードの例を以下に示す。

(in-package "editor")
(export 'html+-mode)
(autoload 'html+-mode "html+-mode" t)
(pushnew '("\\.s?html?" . html+-mode) *auto-mode-alist* :test 'equal)
;; charsetで指定された文字コードの使用
(setq *html+-detect-charset* t)
;; DOCTYPE毎に異なる補完リストの生成
(setq *html+-use-html-kwd* t)
(setq *html-default-doctype* "HTML4.01 strict") ; 初期値及び未指定時
;; インデント付けの対象外とするタグ
(setq *html+-tags-list-no-indent* '("PRE" "XMP" "CODE" "SAMP"))
(in-package "user")
参考
xyzzy [581]
xyzzy part2 [407]
browserex -- 雑記帖

注釈

  • ローカル環境でWWWサーバと連動しての実行やコマンドラインでの実行を行う為には、Another HTML-lint を予め導入しておく必要があります。

拡張

clickable-uri

拡張lispのclickable-uriを導入すると、マウスの左ダブルクリック操作によるウェブブラウザ、メーラー等の起動が可能になります。

私の場合、browserexも愛用させて頂いているので、コマンド指定にそれを指定して利用しています。

(when (find "clickable-uri" *modules* :test #'string-equal)
  (when (and (packagep (find-package "browserex"))
             (symbolp (find-symbol "navigate" "browserex")))
    (push '("^https?:" . bx:navigate)
          *clickable-uri-open-command-alist*)
    (push '("^file:" . bx:navigate)
          *clickable-uri-open-command-alist*)))
        

xml-mode

XHTMLHTMLで適切なモードを自動選択する。

次の例では、XHTMLファミリ文書に対してHTML文書の為のファイル拡張子を含む場合に、ファイルを開く時点で自動的にxml-modeに切り替えることができる。

;;; XHTML/HTMLで適切なモードを自動選択する。
(defun html-select-mode ()
  (interactive)
  (save-excursion
    (goto-char (point-min))
    (if (scan-buffer "<\\?xml[^>]+>" :regexp t)
        (xml-mode)
      (if (scan-buffer "<!DOCTYPE[ \t\r\n]+" :regexp t)
          (html+-mode)))))
(pushnew '("\\.s?html?" . html-select-mode) *auto-mode-alist* :test 'equal)
参考
xyzzyの使い方がわからぬやし 励ましあえ その4 [660]

更に、コンテント・ネゴシエーション等による拡張子無しのURIのソースを開く際に、XHTML/HTMLの適切なモードを自動選択するには、次の様な記述もしておくと良い。

;; 拡張子無しのソースを開く場合の設定(コンテント・ネゴシエーションへの対処)
;; MsIE や Mozilla (XUL of "ContextMenu Extensions") で有効。
(pushnew '("(/Temporary Internet Files/\\|/TEMP(.*)$)" . html-select-mode)
         *auto-mode-alist* :test 'equal)

尚、XHTMLの為の拡張子をxml-modeに関連付けするには、次の様な記述を初期化ファイルに追加記載しておく必要がある。

(pushnew '("\\.xht[ml]?" . xml-mode) *auto-mode-alist* :test #'equal)

注釈

.html [RFC2854] は元来 HTML の為のファイル拡張子であり、XHTML の為のファイル拡張子ではない。一般に、この拡張子を XHTML に対して使用するのは適切ではない。然しながら、XHTML1Appendix C. HTML Compatibility Guidelines (所謂、互換ガイドライン)に基づく XHTML 1.0 に対してのみは、HTML のファイル拡張子も許されるようである。

The file extensions 'html' or 'htm' are commonly used, but other extensions denoting file formats for preprocessing are also common.

[引用: The 'text/html' Media Type -- RFC 2854 より]

There are three known file extensions that are currently in use for XHTML 1.0; ".xht", ".xhtml", and ".html".

[引用: The 'application/xhtml+xml' Media Type -- RFC 3236 より]

その他

xyzzy lisp言語を弄る際に、知っておくと便利なコマンド。

M-x: apropos
キーワードを入力すると、そのキーワードを名前に含む全ての関数や変数をリストアップします。
M-x: describe-bindings
キーバインドの一覧を表示します。
M-x: describe-function
キーワードを入力すると、そのキーワードと一致する関数の説明文を表示します。
M-x: describe-variable
キーワードを入力すると、そのキーワードと一致する変数の値とその説明文を表示します。

関連リンク