Tips on Emacs

Contents

~/.emacs の基本

~/.emacs と歴史的に呼びますが、現状は以下のファイルのいずれかを指します。

  1. ~/.emacs
  2. ~/.emacs.el
  3. ~/.emacs.d/init.el

元々は最初のものだけでしたが、拡張子を必要とするシステムやオフライン検索のため .el が加わり、他にも色々と格納する場所が必要なのでディレクトリが掘られました。

これらすべてではなく、この順序でいずれか一つが有効となります。今や ~/.emacs.d/init.el をお勧めします。

~/.emacs に自動的に put される内容

Emacs を使っていると勝手に内容が ~/.emacs.d/init.el に追記されていることがあります。例えば、以下のようなものです。

(put 'narrow-to-region 'disabled nil)
(put 'downcase-region 'disabled nil)
(put 'upcase-region 'disabled nil)
(put 'scroll-left 'disabled nil)

これらは、初心者向けに機能がオフになっているコマンドを実行しようとして、Emacs に促されて機能をオンにしたために ~/.emacs の末尾に書き加えられた行です。

~/.emacs に自動的に挿入される内容

さらに、Emacs のカスタマイズ機能で促されるまま変数をいじると以下のような領域が ~/.emacs.d/init.el に追加されます。

(custom-set-variables
 ;; custom-set-variables was added by Custom.
 ;; If you edit it by hand, you could mess it up, so be careful.
 ;; Your init file should contain only one such instance.
 ;; If there is more than one, they won't work right.
 '(case-fold-search nil)
 '(desktop-save-mode t)
 '(js-indent-level 2)
 '(scroll-conservatively 1)
 )
(custom-set-faces
 ;; custom-set-faces was added by Custom.
 ;; If you edit it by hand, you could mess it up, so be careful.
 ;; Your init file should contain only one such instance.
 ;; If there is more than one, they won't work right.
 )

コメント行は結局、ここは手動でいじるとしたら、このように単純な形式で書くことと、~/.emacs 他があってもそれらは動かないよ、ということが書いてあります。

セッション保存機能 ~/.emacs.desktop

表題では「セッション保存機能」と書きましたが、Emacs の desktop save mode という機能で、Emacs を終了し立ち上げ直しても、例えば ~/.emacs.d/.emacs.desktop から以前のセッションから再開できる機能です。これは非常に便利です。

Emacs のカスタマイズ機能から Environment - Frames - Desktop - Desktop Save ModeEnable とすると、先の custom-set-variables 内に '(desktop-save-mode t) の行が追加されます。

あとは、立ち上げ直して促されたことに答えたりすれば、OS デスクトップにログインし直しても編集状態から再開できます。

Emacs いくつかのトグル達

Emacs の便利なキーバインドについては、上部ナビゲーションエリアの「備忘録」に(すべてではないですが)詳細にまとめてあります。ここでは、そこへの記載を検討している機能について記します。

  1. M-x toggle-case-fold-search … 検索にて大文字小文字を区別する/しない
  2. M-x isearch-toggle-case-fold … インクリメンタル検索で大文字小文字を区別する/しない
  3. M-x isearch-toggle-lax-whitespace … インクリメンタル検索で緩い空白としない/する
  4. M-x toggle-truncate-lines … 長い行を折り返して表示する/しない
  5. M-x toggle-horizontal-scroll-bar … 水平スクロールバーを表示する/しない

1.〜3. は既定値として厳しい設定を維持しておきたいところですが、M-x menu-bar-options-save にて維持されるのは 1. のみのようです。4.〜5. は、今時は有り得る改行がないファイルを編集する場合に、Emacs が重くなるときの回避策になり、必要となる水平スクロールも使えるようになります。すると、以下のような設定も ~/.emacs に欲しくなるかもしれません。

(global-set-key (kbd "<mouse-6>") 'scroll-right)
(global-set-key (kbd "<mouse-7>") 'scroll-left)
(global-set-key [wheel-left] 'scroll-right)
(global-set-key [wheel-right] 'scroll-left)

筆者も昔は ~/.emacs をブラッシュアップして使いやすいようにショートカットなどをとことん整備したりしました。初心者は勉強のためにも、そうした工夫はした方がいいと思います。しかし、環境を新しくしたり別の環境に一時的になったときに、慣れたオペレーションが出来なくなるストレスの方が大きいものですから、もう、なるべく既定値のまま Emacs 生活をするように心がけるようになりました。

キーボードマクロを実行する C-x e なんかは2ストロークなのと、のちに導入された C-x e e ... の連続実行も、ともすると途切れちゃうので、他のキーに割り当ててたのですが、ときを経て既定値を侵してしまうし、気づくと F4 に割り当てられたりしてるので、いずれは一旦リセットする勇気も必要だったと思います。

よって、筆者の Emacs 環境は、そうした我慢を重ねて、もうどうしても、と言う設定のみが生き抜いています。そうした例を次に紹介します。

web-mode の導入

Emacs に web-mode を導入して素の HTML の編集を快適にしましょう。但し、web-mode はまだ Emacs 標準ではなく、標準の GNU ELPA パッケージにも登録されていません。

Emacs パッケージによる方法

アーカイブサイトの追加

web-mode のような標準ではないサイトにアーカイブされている elisp をパッケージ管理でインストールしたい場合、アーカイブサイトの追加を行う必要があります。~/.emacs.d/init.el の冒頭の方に以下を加えておきます。

(when (require 'package nil t)
  (add-to-list 'package-archives '("melpa"		. "http://melpa.org/packages/") t)
  (add-to-list 'package-archives '("melpa-stable"	. "http://stable.melpa.org/packages/") t)
  (package-initialize)
)

melpa, melpa-stable は片方だけでなく両方入れておいた方がよろしいかと思います。リポジトリのタグ付や最終更新の双方からパッケージの成熟具合がなんとなく推測できるときもあるからです。

Emacs パッケージのインストール

Emacs パッケージを利用するには、主に以下のコマンドを使います。

M-x package-list-packages
パッケージ管理バッファを開く
M-x package-refresh-contents
パッケージリストの更新
M-x package-install
パッケージのインストール

パッケージ管理バッファからでも、M-x package-installweb-mode でもよいので、web-mode をインストールしましょう。

パッケージ管理なしの方法

筆者の事情として、Emacs.app と Aquamacs.app の両方を利用しており、導入する elisp をどちらでも有効にしたいので、パッケージ管理なしの昔ながらの方法をとります。

elisp の個人的な設置場所を ~/.emacs.d/lisp とします。Emacs にそのディレクトリを知らしめましょう。以下を ~/.emacs.d/init.el の最上位に書いておきます。

(add-to-list 'load-path "~/.emacs.d/lisp")

次にターミナルから web-mode.el~/.emacs.d/lisp/ に配置しましょう。単一ファイルの elisp なので簡単です。

% [ -d ~/.emacs.d/lisp ] || mkdir -p ~/.emacs.d/lisp
% cd ~/.emacs.d/lisp/ &&
curl -ROL -C - https://raw.github.com/fxbois/web-mode/master/web-mode.el

web-mode の使い方

筆者がよく使うショートカットを紹介しておきます。

M-;
行頭(のタグ)をコメント化
C-c C-s
後述のスニペットの挿入
C-c C-w C-l
空白文字の可視化トグル
C-c C-e /
要素を閉じる(既定値では閉じかければ自動的に閉じる)
C-c C-e i
要素の挿入
C-c C-a i
属性の挿入
C-c C-e r
カーソル位置の要素の置換
C-c C-e a
カーソル位置の要素の先頭に移動
C-c C-e e
カーソル位置の要素の末尾に移動

web-mode の優れているところはマルチ言語に対応していることです。Emacs 標準の html-mode などと違って、web-mode だと style や script タグ内、Javascript, PHP などにおいても気兼ねなくエンターキーを押せます。

しかし、Emacs 標準でないこともあるでしょうが、字下げのスタイルが HTML5 以降の現状や Emacs の慣わしに合っていない気もします。

web-mode のカスタマイズ

字下げの調整

よって、筆者の好みの設定ですが、字下げのスタイルが HTML5 以降の現状や Emacs の慣わしを考慮した設定にします。HTML5 の article, section などを守るとタグでいちいち字下げするのは現実的ではないので、字下げはしないでおいて、その他の字下げは多くのモードでのインデントレベル 2 に従います。

以下を ~/.emacs.d/init.el に加えます。

(defun local-web-mode-hook ()
  (setq web-mode-markup-indent-offset 0)
  (setq web-mode-css-indent-offset 2)
  (setq web-mode-code-indent-offset 2)
  (setq web-mode-part-padding 0)
  (setq web-mode-script-padding 0)
  (setq web-mode-style-padding 0)
  (setq web-mode-enable-auto-indentation nil)
  (setq web-mode-enable-block-face t)
  (setq web-mode-enable-element-content-fontification t)
  (setq web-mode-enable-element-tag-fontification t)
  (setq web-mode-enable-html-entities-fontification t)
  (setq web-mode-enable-part-face t)
  )

(when (require 'web-mode nil t)
  (add-hook 'web-mode-hook 'local-web-mode-hook)
  (add-to-list 'auto-mode-alist '("\\.\\(html?\\|css\\|js\\|php\\)\\'" . web-mode))
  )

*-face t*-fontification t は他にも多くある見栄えに関するものですが、邪魔にならないものを選んで有効化しました。

web-mode が導入されていない環境でもエラーで停止はしないようになっています。

php と書いてある箇所はファイル名の拡張子でモードを自動設定するための「正規表現」ですので、PHP のように適宜追加してください。

web-mode のスニペットを追加

実は、筆者はこれをやろうとして出来なくて悩みました。上記の local-web-mode-hook 内の setq では効かなかったのでした。

さて、C-c C-s によるスニペットの挿入ですが、非常に便利なのに、HTML に関しては html5, table, ul の3つしかありません。いや、これだけでもかなり便利なのですが、この便利さを推し進めてみましょう。

以下の変数を ~/.emacs.d/init.el にて定義します。

(setq web-mode-extra-snippets
      '((nil . (
		("html"		. "<!doctype html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\"/>\n<title></title>\n</head>\n<body>\n|\n</body>\n</html>")
		("html-lang"	. "<!doctype html>\n<html lang=\"|\">\n<head>\n<meta charset=\"utf-8\"/>\n<title></title>\n</head>\n<body>\n\n</body>\n</html>")
		("title"	. "<title>|</title>")
		("meta-charset"	. "<meta charset=\"|\"/>")
		("meta-viewport"	. "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"/>")
		("meta-IE=edge"	. "<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\"/>")
		("base-href"	. "<base href=\"|\"/>")
		("base-target"	. "<base target=\"_|\"/>")
		("template"	. "<template>|</template>")
		("slot"		. "<slot>|</slot>")
		("stylesheet"	. "<link rel=\"stylesheet\" href=\"|\"/>")
		("touch-icon"	. "<link rel=\"apple-touch-icon\" href=\"|\"/>")
		("touch-icon-precomposed"	. "<link rel=\"apple-touch-icon-precomposed\" href=\"|\"/>")
		("preload"	. "<link rel=\"preload\" href=\"|\" as=\"\" type=\"\" crossorigin=\"anonymous\"/>")
		("script-src"	. "<script src=\"|\"></script>")
		("style"	. "<style>\n|\n</style>")
		("script"	. "<script>\n|\n</script>")
		("noscript"	. "<noscript>\n|</noscript>")
		("header"	. "<header>\n|</header>")
		("footer"	. "<footer>\n|</footer>")
		("nav"		. "<nav>\n|</nav>")
		("aside"	. "<aside>\n|</aside>")
		("main"		. "<main>\n|</main>")
		("article"	. "<article>\n<section>|\n</section>\n<section>\n</section>\n</article>")
		("section"	. "<section>|\n</section>")
		("section-h2"	. "<section><h2>|</h2>\n<p></p>\n</section>")
		("section-h3"	. "<section><h3>|</h3>\n<p></p>\n</section>")
		("section-h4"	. "<section><h4>|</h4>\n<p></p>\n</section>")
		("h1"		. "<h1>|</h1>")
		("h2"		. "<h2>|</h2>")
		("h3"		. "<h3>|</h3>")
		("h4"		. "<h4>|</h4>")
		("h5"		. "<h5>|</h5>")
		("h6"		. "<h6>|</h6>")
		("h2-id"	. "<h2 id=\"|\"></h2>")
		("h3-id"	. "<h3 id=\"|\"></h3>")
		("h4-id"	. "<h4 id=\"|\"></h4>")
		("h5-id"	. "<h5 id=\"|\"></h5>")
		("h6-id"	. "<h6 id=\"|\"></h6>")
		("p"		. "<p>|</p>")
		("div"		. "<div>|</div>")
		("div-style"	. "<div style=\"|\"></div>")
		("div-align"	. "<div style=\"text-align: |;\"></div>")
		("div-align-left"	. "<div style=\"text-align: left;\">|</div>")
		("div-align-center"	. "<div style=\"text-align: center;\">|</div>")
		("div-align-right"	. "<div style=\"text-align: right;\">|</div>")
		("div-float"	. "<div style=\"float: |;\"></div>")
		("div-float-left"	. "<div style=\"float: left;\">|</div>")
		("div-float-right"	. "<div style=\"float: right;\">|</div>")
		("div-columns"	. "<div style=\"columns: 2;\">\n|</div>")
		("div-columns-p"	. "<div style=\"columns: 2;\">\n<p style=\"margin-top: 0;\">\n|</p>\n</div>")
		("div-position"	. "<div style=\"position: |;\"></div>")
		("div-position-relative"	. "<div style=\"position: relative;\">|</div>")
		("div-position-absolute"	. "<div style=\"position: absolute;\">|</div>")
		("div-position-fixed"	. "<div style=\"position: fixed;\">|</div>")
		("div-position-sticky"	. "<div style=\"position: sticky;\">|</div>")
		("hr"		. "<hr/>")
		("hr-clear-float"	. "<hr style=\"clear: both; height: 0;\"/>")
		("details-summary"	. "<details>\n<summary>|</summary>\n</details>")
		("blockquote"	. "<blockquote>\n|</blockquote>")
		("pre"		. "<pre>\n|</pre>")
		("ol"		. "<ol>\n<li>|</li>\n<li></li>\n</ol>")
		("ul"		. "<ul>\n<li>|</li>\n<li></li>\n</ul>")
		("li"		. "<li>|</li>")
		("dl"		. "<dl>\n<dt>|</dt><dd\t></dd>\n<dt></dt><dd\t></dd>\n</dl>")
		("dt"		. "<dt>|</dt>")
		("dd"		. "<dd>|</dd>")
		("figure"	. "<figure>\n\n<figcaption>|</figcaption>\n</figure>")
		("figcaption"	. "<figcaption>|</figcaption>")
		("table"	. "<table>\n<caption>|</caption>\n</table>")
		("caption"	. "<caption>|</caption>")
		("thead"	. "<thead>\n<tr><th\t>|</th><th\t></th></tr>\n</thead>")
		("tbody"	. "<tbody>\n<tr><td\t>|</td><td\t></td></tr>\n</tbody>")
		("tfoot"	. "<tfoot>\n<tr><td\t>|</td><td\t></td></tr>\n</tfoot>")
		("colgroup/"	. "<colgroup |/>")
		("colgroup"	. "<colgroup>|</colgroup>")
		("col"		. "<col>|</col>")
		("tr"		. "<tr>|</tr>")
		("th"		. "<th>|</th>")
		("td"		. "<td>|</td>")
		("address"	. "<address>|</address>")
		("a"		. "<a>|</a>")
		("a-href"	. "<a href=\"|\"></a>")
		("a-href#"	. "<a href=\"#|\"></a>")
		("img"		. "<img src=\"|\"/>")
		("svg"		. "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"\" height=\"\" viewBox=\"\">\n|\n</svg>")
		("span"		. "<span>|</span>")
		("span-style"	. "<span style=\"|\"></span>")
		("code"		. "<code>|</code>")
		("u"		. "<span style=\"text-decoration: underline;\">|</span>")
		("strike"	. "<span style=\"text-decoration: line-through;\">|</span>")
		("s"		. "<s>|</s>")
		("ins"		. "<ins>|</ins>")
		("del"		. "<del>|</del>")
		("strong"	. "<strong>|</strong>")
		("tt"		. "<span style=\"font-family: monospace;\">|</span>")
		("b"		. "<span style=\"font-weight: bold;\">|</span>")
		("i"		. "<span style=\"font-style: italic;\">|</span>")
		("oblique"	. "<span style=\"font-style: oblique 20deg 45deg;\">|</span>")
		("big"		. "<span style=\"font-size: larger;\">|</span>")
		("small"	. "<small>|</small>")
		("font"		. "<span style=\"font-family: |;\"></span>")
		("left"		. "<div style=\"text-align: left;\">|</div>")
		("center"	. "<div style=\"text-align: center;\">|</div>")
		("right"	. "<div style=\"text-align: right;\">|</div>")
		("justify"	. "<div style=\"text-align: justify;\">|</div>")
		("em"		. "<em>|</em>")
		("site"		. "<site>|</site>")
		("q"		. "<q>|</q>")
		("dfn"		. "<dfn>|</dfn>")
		("dfn-title"	. "<dfn title=\"|\"></dfn>")
		("dfn-abbr"	. "<dfn><abbr>|</abbr></dfn>")
		("dfn-abbr-title"	. "<dfn><abbr title=\"|\"></abbr></dfn>")
		("abbr"		. "<abbr>|</abbr>")
		("abbr-title"	. "<abbr title=\"|\"></abbr>")
		("time"		. "<time>|</time>")
		("time-datetime"	. "<time datetime=\"|\"></time>")
		("var"		. "<var>|</var>")
		("samp"		. "<samp>|</samp>")
		("kbd"		. "<kbd>|</kbd>")
		("samp-kbd"	. "<samp><kbd>|</kbd></samp>")
		("kbd-samp"	. "<kbd><samp>|</samp></kbd>")
		("sub"		. "<sub>|</sub>")
		("sup"		. "<sup>|</sup>")
		("mark"		. "<mark>|</mark>")
		("bdo"		. "<bdo>|</bdo>")
		("bdo-dir"	. "<bdo dir=\"|\"></bdo>")
		("bdo-dir-rtl"	. "<bdo dir=\"rtl\">|</bdo>")
		("bdi"		. "<bdi>|</bdi>")
		("br"		. "<br/>")
		("wbr"		. "<wbr/>")
		("ruby"		. "<ruby>|</ruby>")
		("ruby-rt"	. "<ruby>|<rt></rt></ruby>")
		("ruby-rp"	. "<ruby>|<rp>(</rp><rt></rt><rp>)</rp></ruby>")
		("rt"		. "<rt>|</rt>")
		("rp"		. "<rp>(</rp><rt>|</rt><rp>)</rp>")
		("data"		. "<data>|</data>")
		("data-value"	. "<data value=\"|\"></data>")
		;(""	. "")
		("form-legend"	. "<form>\n<fieldset>\n<legend>|</legend>\n</fieldset>\n</form>")
		("form-fieldset"	. "<form>\n<fieldset>\n|</fieldset>\n</form>")
		("label"	. "<label>|</label>")
		("button"	. "<button\t>|</button>")
		("input-type"	. "<input type=\"|\"\t/>")
		("input-submit"	. "<input type=\"submit\"\t/>")
		("input-reset"	. "<input type=\"reset\"\t/>")
		("input-hidden"	. "<input type=\"hidden\"\t/>")
		("input-button"	. "<input type=\"button\"\t/>")
		("input-radio"	. "<input type=\"radio\"\t/>")
		("input-checkbox"	. "<input type=\"check\"\t/>")
		("input-text"	. "<input type=\"text\"\t/>")
		("input-search"	. "<input type=\"search\"\t/>")
		("input-tel"	. "<input type=\"tel\"\t/>")
		("input-url"	. "<input type=\"url\"\t/>")
		("input-email"	. "<input type=\"email\"\t/>")
		("input-password"	. "<input type=\"password\"\t/>")
		("input-month"	. "<input type=\"month\"\t/>")
		("input-week"	. "<input type=\"week\"\t/>")
		("input-time"	. "<input type=\"time\"\t/>")
		("input-datetime-local"	. "<input type=\"datetime-local\"\t/>")
		("input-number"	. "<input type=\"number\"\t/>")
		("input-range"	. "<input type=\"range\"\t/>")
		("input-color"	. "<input type=\"color\"\t/>")
		("input-file"	. "<input type=\"file\"\t/>")
		("input-image"	. "<input type=\"image\"\t/>")
		("select"	. "<select>\n<option\t>|</option>\n<option\t></option>\n</select>")
		("select-group"	. "<select>\n<optgroup><option\t>|</option>\n<option\t></option>\n</optgroup></select>")
		("textarea"	. "<textarea>|</textarea>")
		("progress"	. "<progress>|</progress>")
		("meter"	. "<meter>|</meter>")
		("menu"		. "<menu>|</menu>")
		("output"	. "<output>|</output>")
		("dialog"	. "<dialog>|</dialog>")
		;("command"	. "<command>|</command>")
		;
		("iframe"	. "<iframe|></iframe>")
		("embed"	. "<embed|></embed>")
		("embed-src"	. "<embed|></embed>")
		("object"	. "<object|></object>")
		("param"	. "<param|/>")
		("canvas"	. "<canvas|></canvas>")
		("video"	. "<video|></video>")
		("video-src"	. "<video|></video>")
		("audio"	. "<audio|></audio>")
		("audio-src"	. "<audio|></audio>")
		("picture"	. "<picture>|</picture>")
		("source"	. "<source|/>")
		("track"	. "<track|/>")
		("map"		. "<map>|</map>")
		("area"		. "<area|></area>")
		;
		("@import-url"	. "@import url(\"|\");")
		("@media-screen"	. "@media screen {\n|\n}")
		("@media-print"	. "@media print {\n|\n}")
		("@media-speech"	. "@media speech {\n|\n}")
		)))
	)

スニペットの追加はタブによる補完が効くので、うろ覚えでも選べば進められるのが効率的です。上では HTML5, HTML Living standard と廃止されたタグに配慮したスニペット群を揃えてみました。

句読点の変換「。、」「.,」「. , 」

日本語の句読点「。、」を全角の「.,」に replace-string したり query-replace する関数や、全角の「.,。、」を半角の「. , 。 、 」に replace-string したり query-replace する関数です。下の方に残っていますが、古に記載したものをリベンジしました。

以下のように ~/.emacs に書いておけばいいと思います。

(defun replace-kv-region (l)
  (save-excursion
    (save-restriction
      (narrow-to-region b e)
      (format-replace-strings l)
      ))
  )
;
(defun query-replace-strings (a)
  (dolist (i a)
    (goto-char b)
    (query-replace (car i) (cdr i))
    )
)
(defun query-replace-kv-region (l)
  (save-excursion
    (save-restriction
      (narrow-to-region b e)
      (query-replace-strings l)
      ))
  )
;
(defconst kutoten-zenpunct-kv '(("。" . ".") ("、" . ",")))
(defconst zenpunct-kutoten-kv '(("." . "。") ("," . "、")))
(defconst zenpunct-hanpunct-kv '(("." . ". ") ("," . ", ") ("。" . "。 ") ("、" . "、 ")))
(defconst hanpunct-zenpunct-kv '((". " . ".") (", " . ",") ("。 " . "。") ("、 " . "、")))
;
(defun replace-kutoten-zenpunct-region (b e)
  (interactive "r")
  (replace-kv-region kutoten-zenpunct-kv))
(defun replace-zenpunct-kutoten-region (b e)
  (interactive "r")
  (replace-kv-region zenpunct-kutoten-kv))
(defun replace-zenpunct-hanpunct-region (b e)
  (interactive "r")
  (replace-kv-region zenpunct-hanpunct-kv))
(defun replace-hanpunct-zenpunct-region (b e)
  (interactive "r")
  (replace-kv-region hanpunct-zenpunct-kv))
;
(defun query-replace-kutoten-zenpunct-region (b e)
  (interactive "r")
  (query-replace-kv-region kutoten-zenpunct-kv))
(defun query-replace-zenpunct-kutoten-region (b e)
  (interactive "r")
  (query-replace-kv-region zenpunct-kutoten-kv))
(defun query-replace-zenpunct-hanpunct-region (b e)
  (interactive "r")
  (query-replace-kv-region zenpunct-hanpunct-kv))
(defun query-replace-hanpunct-zenpunct-region (b e)
  (interactive "r")
  (query-replace-kv-region hanpunct-zenpunct-kv))
;
(global-set-key "\C-x\C-m/" 'replace-kutoten-zenpunct-region) 
(global-set-key "\C-x\C-m?" 'replace-zenpunct-kutoten-region) 
(global-set-key "\C-x\C-m." 'replace-zenpunct-hanpunct-region) 
(global-set-key "\C-x\C-m," 'replace-hanpunct-zenpunct-region) 
;
(global-set-key "\C-x\C-m\M-/" 'query-replace-kutoten-zenpunct-region) 
(global-set-key "\C-x\C-m\M-?" 'query-replace-zenpunct-kutoten-region) 
(global-set-key "\C-x\C-m\M-." 'query-replace-zenpunct-hanpunct-region) 
(global-set-key "\C-x\C-m\M-," 'query-replace-hanpunct-zenpunct-region) 

すると、以下のキーバインドで利用できます。

日本語文字コードの正規化

JIS X 0213 では全角のラテン文字や半角のカタカナの使用は推奨されていません。そのような変換をリージョンに対して行う関数やその逆関数、及び、キーバインディングを以下に記します。

(defconst normal-japanese-latin-kv '(
	("!" . "!")
	("”" . "\"")
	("#" . "#")
	("$" . "$")
	("%" . "%")
	("&" . "&")
	("(" . "(")
	(")" . ")")
	("*" . "*")
	("+" . "+")
	("," . ",")
	("−" . "-")
	("." . ".")
	("/" . "/")
	("0" . "0")
	("1" . "1")
	("2" . "2")
	("3" . "3")
	("4" . "4")
	("5" . "5")
	("6" . "6")
	("7" . "7")
	("8" . "8")
	("9" . "9")
	(":" . ":")
	(";" . ";")
	("<" . "<")
	("=" . "=")
	(">" . ">")
	("?" . "?")
	("@" . "@")
	("A" . "A")
	("B" . "B")
	("C" . "C")
	("D" . "D")
	("E" . "E")
	("F" . "F")
	("G" . "G")
	("H" . "H")
	("I" . "I")
	("J" . "J")
	("K" . "K")
	("L" . "L")
	("M" . "M")
	("N" . "N")
	("O" . "O")
	("P" . "P")
	("Q" . "Q")
	("R" . "R")
	("S" . "S")
	("T" . "T")
	("U" . "U")
	("V" . "V")
	("W" . "W")
	("X" . "X")
	("Z" . "Z")
	("[" . "[")
	("\" . "\\")
	("]" . "]")
	("^" . "^")
	("_" . "_")
	("`" . "`")
	("a" . "a")
	("b" . "b")
	("c" . "c")
	("d" . "d")
	("e" . "e")
	("f" . "f")
	("g" . "g")
	("h" . "h")
	("i" . "i")
	("j" . "j")
	("k" . "k")
	("l" . "l")
	("m" . "m")
	("n" . "n")
	("o" . "o")
	("p" . "p")
	("q" . "q")
	("r" . "r")
	("s" . "s")
	("t" . "t")
	("u" . "u")
	("v" . "v")
	("w" . "w")
	("x" . "x")
	("y" . "y")
	("z" . "z")
	("{" . "{")
	("|" . "|")
	("¦" . "¦")
	("}" . "}")
	("〜" . "~")
	("¬" . "¬")
	(" ̄" . "¯")
					)
)
(defconst normal-japanese-katakana-kv '(
	("¥" . "¥")
	("。" . "。")
	("「" . "「")
	("」" . "」")
	("、" . "、")
	("・" . "・")
	("ガ" . "ガ")
	("ギ" . "ギ")
	("グ" . "グ")
	("ゲ" . "ゲ")
	("ゴ" . "ゴ")
	("ザ" . "ザ")
	("ジ" . "ジ")
	("ズ" . "ズ")
	("ゼ" . "ゼ")
	("ゾ" . "ゾ")
	("ダ" . "ダ")
	("ヂ" . "ヂ")
	("ヅ" . "ヅ")
	("デ" . "デ")
	("ド" . "ド")
	("バ" . "バ")
	("ビ" . "ビ")
	("ブ" . "ブ")
	("ベ" . "ベ")
	("ボ" . "ボ")
	("パ" . "パ")
	("ピ" . "ピ")
	("プ" . "プ")
	("ペ" . "ペ")
	("ポ" . "ポ")
	("ヴ" . "ヴ")
	("ヲ" . "ヲ")
	("ァ" . "ァ")
	("ィ" . "ィ")
	("ゥ" . "ゥ")
	("ェ" . "ェ")
	("ォ" . "ォ")
	("ャ" . "ャ")
	("ュ" . "ュ")
	("ョ" . "ョ")
	("ッ" . "ッ")
	("ー" . "ー")
	("ア" . "ア")
	("イ" . "イ")
	("ウ" . "ウ")
	("エ" . "エ")
	("オ" . "オ")
	("カ" . "カ")
	("キ" . "キ")
	("ク" . "ク")
	("ケ" . "ケ")
	("コ" . "コ")
	("サ" . "サ")
	("シ" . "シ")
	("ス" . "ス")
	("セ" . "セ")
	("ソ" . "ソ")
	("タ" . "タ")
	("チ" . "チ")
	("ツ" . "ツ")
	("テ" . "テ")
	("ト" . "ト")
	("ナ" . "ナ")
	("ニ" . "ニ")
	("ヌ" . "ヌ")
	("ネ" . "ネ")
	("ノ" . "ノ")
	("ハ" . "ハ")
	("ヒ" . "ヒ")
	("フ" . "フ")
	("ヘ" . "ヘ")
	("ホ" . "ホ")
	("マ" . "マ")
	("ミ" . "ミ")
	("ム" . "ム")
	("メ" . "メ")
	("モ" . "モ")
	("ヤ" . "ヤ")
	("ユ" . "ユ")
	("ヨ" . "ヨ")
	("ラ" . "ラ")
	("リ" . "リ")
	("ル" . "ル")
	("レ" . "レ")
	("ロ" . "ロ")
	("ワ" . "ワ")
	("ン" . "ン")
	("゙" . "゛")
	("゚" . "゜")
				  ))
(defconst abnormal-japanese-latin-kv '(
	("!" . "!")
	("\"" . "”")
	("#" . "#")
	("$" . "$")
	("%" . "%")
	("&" . "&")
	("(" . "(")
	(" . ")")")
	("*" . "*")
	("+" . "+")
	("," . ",")
	("-" . "−")
	("." . ".")
	("/" . "/")
	("0" . "0")
	("1" . "1")
	("2" . "2")
	("3" . "3")
	("4" . "4")
	("5" . "5")
	("6" . "6")
	("7" . "7")
	("8" . "8")
	("9" . "9")
	(":" . ":")
	(";" . ";")
	("<" . "<")
	("=" . "=")
	(">" . ">")
	("?" . "?")
	("@" . "@")
	("A" . "A")
	("B" . "B")
	("C" . "C")
	("D" . "D")
	("E" . "E")
	("F" . "F")
	("G" . "G")
	("H" . "H")
	("I" . "I")
	("J" . "J")
	("K" . "K")
	("L" . "L")
	("M" . "M")
	("N" . "N")
	("O" . "O")
	("P" . "P")
	("Q" . "Q")
	("R" . "R")
	("S" . "S")
	("T" . "T")
	("U" . "U")
	("V" . "V")
	("W" . "W")
	("X" . "X")
	("Z" . "Z")
	("[" . "[")
	("\\" . "\")
	("]" . "]")
	("^" . "^")
	("_" . "_")
	("`" . "`")
	("a" . "a")
	("b" . "b")
	("c" . "c")
	("d" . "d")
	("e" . "e")
	("f" . "f")
	("g" . "g")
	("h" . "h")
	("i" . "i")
	("j" . "j")
	("k" . "k")
	("l" . "l")
	("m" . "m")
	("n" . "n")
	("o" . "o")
	("p" . "p")
	("q" . "q")
	("r" . "r")
	("s" . "s")
	("t" . "t")
	("u" . "u")
	("v" . "v")
	("w" . "w")
	("x" . "x")
	("y" . "y")
	("z" . "z")
	("{" . "{")
	("|" . "|")
	("¦" . "¦")
	("}" . "}")
	("~" . "〜")
	("¬" . "¬")
	("¯" . " ̄")
					  )
)
(defconst abnormal-japanese-katakana-kv '(
	("¥" . "¥")
	("。" . "。")
	("「" . "「")
	("」" . "」")
	("、" . "、")
	("・" . "・")
	("ガ" . "ガ")
	("ギ" . "ギ")
	("グ" . "グ")
	("ゲ" . "ゲ")
	("ゴ" . "ゴ")
	("ザ" . "ザ")
	("ジ" . "ジ")
	("ズ" . "ズ")
	("ゼ" . "ゼ")
	("ゾ" . "ゾ")
	("ダ" . "ダ")
	("ヂ" . "ヂ")
	("ヅ" . "ヅ")
	("デ" . "デ")
	("ド" . "ド")
	("バ" . "バ")
	("ビ" . "ビ")
	("ブ" . "ブ")
	("ベ" . "ベ")
	("ボ" . "ボ")
	("パ" . "パ")
	("ピ" . "ピ")
	("プ" . "プ")
	("ペ" . "ペ")
	("ポ" . "ポ")
	("ヴ" . "ヴ")
	("ヲ" . "ヲ")
	("ァ" . "ァ")
	("ィ" . "ィ")
	("ゥ" . "ゥ")
	("ェ" . "ェ")
	("ォ" . "ォ")
	("ャ" . "ャ")
	("ュ" . "ュ")
	("ョ" . "ョ")
	("ッ" . "ッ")
	("ー" . "ー")
	("ア" . "ア")
	("イ" . "イ")
	("ウ" . "ウ")
	("エ" . "エ")
	("オ" . "オ")
	("カ" . "カ")
	("キ" . "キ")
	("ク" . "ク")
	("ケ" . "ケ")
	("コ" . "コ")
	("サ" . "サ")
	("シ" . "シ")
	("ス" . "ス")
	("セ" . "セ")
	("ソ" . "ソ")
	("タ" . "タ")
	("チ" . "チ")
	("ツ" . "ツ")
	("テ" . "テ")
	("ト" . "ト")
	("ナ" . "ナ")
	("ニ" . "ニ")
	("ヌ" . "ヌ")
	("ネ" . "ネ")
	("ノ" . "ノ")
	("ハ" . "ハ")
	("ヒ" . "ヒ")
	("フ" . "フ")
	("ヘ" . "ヘ")
	("ホ" . "ホ")
	("マ" . "マ")
	("ミ" . "ミ")
	("ム" . "ム")
	("メ" . "メ")
	("モ" . "モ")
	("ヤ" . "ヤ")
	("ユ" . "ユ")
	("ヨ" . "ヨ")
	("ラ" . "ラ")
	("リ" . "リ")
	("ル" . "ル")
	("レ" . "レ")
	("ロ" . "ロ")
	("ワ" . "ワ")
	("ン" . "ン")
	("゛" . "゙")
	("゜" . "゚")
				)
)
;
(defun replace-normal-japanese-latin-region (b e)
  (interactive "r")
  (replace-kv-region normal-japanese-latin-kv))
(defun replace-abnormal-japanese-latin-region (b e)
  (interactive "r")
  (replace-kv-region abnormal-japanese-latin-kv))
(defun replace-normal-japanese-katakana-region (b e)
  (interactive "r")
  (replace-kv-region normal-japanese-katakana-kv))
(defun replace-abnormal-japanese-katakana-region (b e)
  (interactive "r")
  (replace-kv-region abnormal-japanese-katakana-kv))
;
(defun query-replace-normal-japanese-latin-region (b e)
  (interactive "r")
  (query-replace-kv-region normal-japanese-latin-kv))
(defun query-replace-abnormal-japanese-latin-region (b e)
  (interactive "r")
  (query-replace-kv-region abnormal-japanese-latin-kv))
(defun query-replace-normal-japanese-katakana-region (b e)
  (interactive "r")
  (query-replace-kv-region normal-japanese-katakana-kv))
(defun query-replace-abnormal-japanese-katakana-region (b e)
  (interactive "r")
  (query-replace-kv-region abnormal-japanese-katakana-kv))
;
(global-set-key "\C-x\C-m;" 'replace-normal-japanese-latin-region) 
(global-set-key "\C-x\C-m:" 'replace-abnormal-japanese-latin-region) 
(global-set-key "\C-x\C-m\\" 'replace-normal-japanese-katakana-region) 
(global-set-key "\C-x\C-m|" 'replace-abnormal-japanese-katakana-region) 
;
(global-set-key "\C-x\C-m\M-;" 'query-replace-normal-japanese-latin-region) 
(global-set-key "\C-x\C-m\M-:" 'query-replace-abnormal-japanese-latin-region) 
(global-set-key "\C-x\C-m\M-\\" 'query-replace-normal-japanese-katakana-region) 
(global-set-key "\C-x\C-m\M-|" 'query-replace-abnormal-japanese-katakana-region) 

すると、以下のキーバインドで利用できます。

半角・全角、ひらがな・カタカナ変換

前節と似ていますが、Emacs にはリージョンの半角・全角、ひらがな・カタカナ変換を行う関数が標準的に用意されています。以下のようにキーバインディングすると、ある種の文章には大変便利です。

(global-set-key (kbd "C-x C-m C-;") 'japanese-hankaku-region) 
(global-set-key (kbd "C-x C-m C-l") 'japanese-zenkaku-region) 
(global-set-key (kbd "C-x C-m C-j") 'japanese-hiragana-region) 
(global-set-key (kbd "C-x C-m C-k") 'japanese-katakana-region) 

ps-print.el の設定

以下の内容は、非常に古いもので今は使っていません。

Mule が Emacs に統合され、coco や any2ps, m2ps がなくなっちゃった、と思ってたら、ps-print.elが Mule 拡張されてて以前の any2ps の代替機能になっているように思えます。その上、設定次第では、BDFによるビットマップフォントと PostScript builtin フォントを共存できるので、せっかくだし、gs-cjk の CJK フォントを使うように設定してみました。`C-u M-x ps-print-buffer` で PostScript ファイルを生成します。

何やら冗長ですが、BDF のエントリは ps-mule.el のままで、builtin のエントリが設定及び動作確認した箇所です。その他も、適宜アウトラインフォントに置き換えていく予定。

jutl.el version 0.1

以下の内容は、非常に古いもので今は使っていません。また、jutl.el は上述のベターな代替を使っています。

日本語の句読点「。、」を全角の「.,」に replace-string したり、query-replaceする関数を作りました。なにぶん、Emacs-Lisp のプログラミング(ってほどのものでもないけど)は初めてなので (1999/5/12現在)、おかしなことをやっているかも知れません。御指摘下されば幸いです。

この jutl.el を Emacs-Lisp のロードパスに置いて、~/.emacs に以下のように書きます。

(load "jutl")
(global-set-key "\C-x\C-k/" 'jutl-replace-kutoten-period-comma)
(global-set-key "\C-x\C-k?" 'jutl-replace-period-comma-kutoten)
(global-set-key "\C-x\C-k\M-/" 'jutl-query-replace-kutoten-period-comma)
(global-set-key "\C-x\C-k\M-?" 'jutl-query-replace-period-comma-kutoten)

すると、以下のキーバインドで利用できます。

但し、Emacs-20 だとキーバインドのプレフィックスが "C-x C-m" の方が好ましいと思います.私は以下のように ~/.emacs に書いています.

(load "jutl")
(if (and (featurep 'mule) (string-match "SUETSUMUHANA" mule-version))
  (progn
    (global-set-key "\C-x\C-k/" 'jutl-replace-kutoten-period-comma)
    (global-set-key "\C-x\C-k?" 'jutl-replace-period-comma-kutoten)
    (global-set-key "\C-x\C-k\M-/" 'jutl-query-replace-kutoten-period-comma)
    (global-set-key "\C-x\C-k\M-?" 'jutl-query-replace-period-comma-kutoten)))
(if (and (featurep 'mule) (string-match "HANANOEN" mule-version))
  (progn
    (global-set-key "\C-x\C-m/" 'jutl-replace-kutoten-period-comma)
    (global-set-key "\C-x\C-m?" 'jutl-replace-period-comma-kutoten)
    (global-set-key "\C-x\C-m\M-/" 'jutl-query-replace-kutoten-period-comma)
    (global-set-key "\C-x\C-m\M-?" 'jutl-query-replace-period-comma-kutoten)))

作り方が悪いのか、アンドゥを2回やらないと元に戻りません。テキストが長いとアンドゥで元に戻らないこともあるようです。今後の課題です。あと、漢字コードの問題もあると思います。これも今後の課題ですが、私は euc-jp しか使わないので取り組むかどうか未定。(昨今は流石に utf-8 を使っています。)

xcal.el, xcal-19.el へのパッチ

以下の内容は、非常に古いもので今は使っていません。

Emacs/Mule 用のカレンダーの xcal.tar.gz の以下の点を修正しました。

いろいろと課題(例えば、成人の日・体育の日問題)は残されていますので暫定的なパッチとして公開してます。


このサイトについてのご意見ご要望は taiji@aihara.co.jp までお願いします。

Copyright (C) 1999-2001, 2013, 2021 Taiji Yamada, All rights reserved.