2009-07 / 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31

2009-07-05 (日)

Emacs講座 -第6回- load-path [Emacs講座]

目次 / 第1回 第2回 第3回 第4回 第5回 第6回 第7回 第8回 第9回

本項は、ネット上から *.el をダウンロードして、いろいろ試したくなっ
てきたあたりで読むと良いと思います。load-path の仕組みを理解しましょう。

load-path とは何か?


UNIX や Windows 等に存在する「環境変数 PATH」の Emacs 版です。

例えば ls を実行すると、「環境変数 PATH」に登録された最初のディレク
トリから ls が検索され、最初にヒットした ls が使われますよね?
また、どのディレクトリにも ls が存在しなければ、

command not found: ls

などといったエラーが発生します。

Emacs では例えば ~/.emacs に以下のようなコードを書くと load-path が
参照されます。

(require 'hoge)


load-path は Emacs Lisp の変数です。どんな値が入っているのかは第3回
の方法で調べられます。

load-path には複数のディレクトリが登録されているはずです。

まず先頭のディレクトリについて、以下の順で検査が行われます。第2回
.emacs と同じですね。

1. hoge.elc が存在するか?
2. hoge.el が存在するか?
3. hoge が存在するか?


1, 2, 3 のどれにも当てはまらなければ、次のディレクトリが検査されます。
全てのディレクトリで当てはまらなければ、以下のエラーが発生します。

Cannot open load file: hoge


load-path を構成するディレクトリ


デフォルトの設定では、以下の順番に構成されているはずです。

1. <PREFIX>/share/emacs/<EMACS-VERSION>/site-lisp 以下全てのディレクトリ
2. <PREFIX>/share/emacs/site-lisp 以下全てのディレクトリ
3. <PREFIX>/share/emacs/<EMACS-VERSION>/lisp 以下全てのディレクトリ


Emacs-22.3 を /usr/local 以下にインストールした場合は、このようにな
ります。

1. /usr/local/share/emacs/22.3/site-lisp 以下全てのディレクトリ
2. /usr/local/share/emacs/site-lisp 以下全てのディレクトリ
3. /usr/local/share/emacs/22.3/lisp 以下全てのディレクトリ


1 は当該バージョンの Emacs だけに参照させたい *.el を置くディレクト
リです。デフォルトでは subdirs.el というファイルだけが置かれています。
(subdirs.el は後で説明するので、覚えておいて下さい。)

2 は全てのバージョンの Emacs から参照させたい *.el を置くディレクト
リです。ここにも、デフォルトでは subdirs.el というファイルだけが置
かれています。

3 は当該バージョンの Emacs に付属する、全ての *.el が置かれているデ
ィレクトリです。

load-path が構築される仕組み


<PREFIX>/share/emacs/site-lisp 以下に適当な名前のディレクトリを作っ
て、Emacs を再起動してみて下さい。追加したディレクトリが load-path
に追加されていますよね。なぜでしょう?

Emacs は起動時に以下の 3 つの subdirs.el を評価します。

1. <PREFIX>/share/emacs/<EMACS-VERSION>/site-lisp/subdirs.el
2. <PREFIX>/share/emacs/site-lisp/subdirs.el
3. <PREFIX>/share/emacs/<EMACS-VERSION>/lisp/subdirs.el


12 の subdirs.el の内容は同じで、以下のように記載されているはず
です。

(if (fboundp 'normal-top-level-add-subdirs-to-load-path)
    (normal-top-level-add-subdirs-to-load-path))


この Emacs Lisp 式の意味は
「normal-top-level-add-subdirs-to-load-path という関数が存在すれば、
normal-top-level-add-subdirs-to-load-path を実行する」になります。

normal-top-level-add-subdirs-to-load-path() はディレクトリを再帰的
に探索し、見つかったディレクトリを load-path に追加する関数です。た
だし、以下のディレクトリは load-path に追加しません。

"." で始まるディレクトリ
"RCS" "CVS" "rcs" "cvs" という名前のディレクトリ
".nosearch" というファイルが存在するディレクトリ


3 の subdirs.el には Emacs-22.3 の場合、以下のように記載されている
はずです。

(normal-top-level-add-to-load-path
 '("url" "textmodes" "progmodes" "play" "obsolete" "net" "mh-e" "mail" "language"
   "international" "gnus" "eshell" "erc" "emulation" "emacs-lisp" "calendar" "calc"))


まあ、だいたい意味は分かりますよね。(説明するのが面倒になってきまし
た..。^^;)

load-path にユーザ指定のディレクトリを追加する方法


root 権限を持っていない等の理由から、前述の site-lisp 以下に *.el
をコピーできない場合もあるでしょう。その場合は、load-path にディレ
クトリを追加します。

例えば、"~/share/elisp" を追加したい場合は以下を ~/.emacs に設定し
て下さい。

(add-to-list 'load-path "~/share/elisp")


この例では load-path の先頭に "~/share/elisp" が追加されます。

ユーザ指定のディレクトリ以下全てを load-path に追加する方法


上の方法だと、~/share/elisp 以下にディレクトリを追加するたびに
add-to-list() を追加する必要があり、少々面倒です。そこで前述の
normal-top-level-add-subdirs-to-load-path を利用します。

先にコードを晒します。

(defconst my-elisp-directory "~/share/elisp" "The directory for my elisp file.")

(dolist (dir (let ((dir (expand-file-name my-elisp-directory)))
               (list dir (format "%s%d" dir emacs-major-version))))
  (when (and (stringp dir) (file-directory-p dir))
    (let ((default-directory dir))
      (add-to-list 'load-path default-directory)
      (normal-top-level-add-subdirs-to-load-path))))


このコードを ~/.emacs に設定すると、load-path の先頭に以下の順番で
追加されます。

1. "~/share/elisp<emacs-major-version>" 以下全てのディレクトリ
2. "~/share/elisp" 以下全てのディレクトリ


使用している Emacs のバージョンが 22.3 の場合、
<emacs-major-version> は 22 になります。
変数 my-elisp-directory は適宜変更して下さい。

require 以外の *.el 読み込み方法


require は、ファイル中に (provide 'hoge) などと書かれている *.el を
読み込む関数です。そうすることで、require 済みかを以下の方法で判別
できます。

(if (featurep 'hoge)
    ...)


また、(require 'hoge) は何度実行しても、hoge.el は一度しか読み込ま
れません。

require と似たものに load があります。featurep() による検査は行えま
せん。load すると、安直に hoge.el が load されます。

(load "hoge")



少し特殊なものに autoload があります。この式が評価された時点では
hoge.el は読み込まれません。hogehoge という関数が実行された直後に
hoge.el が読み込まれ、その後 hogehoge() が実行されます。

(autoload 'hogehoge "hoge" nil t)



他、load-file という関数もあります。M-x load-file を実行し、読み込
みたいファイルを指定すると、そのファイルが load されます。つまり、
load-path とは直接関係ありません。

関連する関数


load-path に関連する関数をご紹介します。それぞれ M-x で呼び出せます。

locate-library
  指定した *.el の場所をフルパスで出力。

list-load-path-shadows
  *.el の名前が同じであるため、load されない *.el を表示。

第6回終わり。

目次 / 第1回 第2回 第3回 第4回 第5回 第6回 第7回 第8回 第9回

2009-07 / 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31

最終更新時間: 2017-12-06 23:28

検索


最近の話題
- 2017-11-28
  『Real World HTTP』を読んだ
- 2017-11-18
  iPhone X 64GB SIM フリー版を買って一週間経った
- 2017-11-16
  golang.tokyo #10 x WomenWhoGoTokyo に行ってきた #golangtokyo
- 2017-11-12
  『PromiseとAsync-Awaitまとめ(Emacsで)』という LT をした
- 2017-11-10
  RSpec 3.5 から shared_context の使い方が少し変わっていた
  S3 の public バケットで特定パス以下を IP アドレス制限する
- 2017-11-01
  『オブジェクト指向設計実践ガイド』読書会での感想メモ
- 2017-10-30
  『スターティングGo言語』を読んだ
最近追記された記事
- 2017-01-10-1 (4日前)
- 2017-04-08-1 (24日前)
- 2017-06-02-1 (158日前)
- 2017-04-29-1 (220日前)
- 2017-04-13-1 (234日前)
- 2017-04-13-1 (236日前)
- 2017-03-02-1 (278日前)
- 2017-02-25-1 (283日前)
- 2017-02-21-1 (287日前)
- 2015-06-07-1 (293日前)
カテゴリ
- Anthy (3)
- Apache (11)
- Apple (1)
- ATOK (4)
- au (3)
- AWS (20)
- Bazaar (1)
- Berkshelf (2)
- BigQuery (1)
- BitBar (3)
- Book (91)
- Boxen (2)
- Bugsnag (1)
- capistrano (4)
- chalow (56)
- ChatWork (1)
- Chef (17)
- Chrome (3)
- Chromecast (1)
- CircleCI (10)
- clang (26)
- Comics (2)
- Cooking (10)
- cvs (15)
- cygwin (12)
- D3.js (1)
- Debian (55)
- Docker (3)
- E-mail (8)
- elasticsearch (4)
- Emacs (222)
- Emacs講座 (10)
- English (4)
- feedforce (7)
- fetchmail (3)
- Firefox (20)
- Fluentd (4)
- ftp (1)
- Game (20)
- GCP (1)
- Gem (5)
- Git (9)
- GitHub (19)
- golang (9)
- Google (1)
- gpg (4)
- GrowthForecast (7)
- Health (3)
- Heroku (9)
- Homebrew (10)
- HTML (6)
- iBook (1)
- iPhone (16)
- IRC (1)
- Jenkins (8)
- JS (1)
- Karabiner (1)
- KeySnail (3)
- Kibana (1)
- Kindle (1)
- Kubernetes (2)
- Langrich (7)
- LDAP (6)
- Life (19)
- Linux (6)
- Mackerel (1)
- Mew (18)
- MongoDB (1)
- Mozilla (19)
- Music (1)
- MySQL (1)
- NAS (4)
- nginx (6)
- NHK (1)
- Node (1)
- ntp (4)
- OOP (2)
- OpenID (2)
- openssl (1)
- Opera (2)
- OSX (41)
- Perl (14)
- PHP (19)
- PostgreSQL (1)
- procmail (4)
- Programing (3)
- Puppet (1)
- Python (2)
- Rails (12)
- Rake (2)
- RaspberryPi (1)
- RedHat (29)
- Redmine (3)
- RSpec (2)
- Ruby (50)
- samba (3)
- screen (7)
- sed (5)
- serverspec (6)
- sh (8)
- Slack (2)
- Solaris9 (22)
- Spring (2)
- ssh (4)
- StatusNet (21)
- svn (12)
- Swift (1)
- Tablet (1)
- tdiary (3)
- Twitter (14)
- Twmode (6)
- Ubuntu (5)
- UNIX (102)
- vagrant (8)
- Video (21)
- vim (1)
- Wercker (9)
- Windows (29)
- Wine (3)
- XML (11)
- XP (1)
- zsh (25)
- インストールメモ (33)
- クイックシェイプ (12)
- ネタ (15)
- 勉強会 (16)
- 携帯 (6)
- 正規表現 (4)
過去ログ
2017 : 01 02 03 04 05 06 07 08 09 10 11 12
2016 : 01 02 03 04 05 06 07 08 09 10 11 12
2015 : 01 02 03 04 05 06 07 08 09 10 11 12
2014 : 01 02 03 04 05 06 07 08 09 10 11 12
2013 : 01 02 03 04 05 06 07 08 09 10 11 12
2012 : 01 02 03 04 05 06 07 08 09 10 11 12
2011 : 01 02 03 04 05 06 07 08 09 10 11 12
2010 : 01 02 03 04 05 06 07 08 09 10 11 12
2009 : 01 02 03 04 05 06 07 08 09 10 11 12
2008 : 01 02 03 04 05 06 07 08 09 10 11 12
2007 : 01 02 03 04 05 06 07 08 09 10 11 12
2006 : 01 02 03 04 05 06 07 08 09 10 11 12
2005 : 01 02 03 04 05 06 07 08 09 10 11 12
2004 : 01 02 03 04 05 06 07 08 09 10 11 12
2003 : 01 02 03 04 05 06 07 08 09 10 11 12
2002 : 01 02 03 04 05 06 07 08 09 10 11 12
2001 : 01 02 03 04 05 06 07 08 09 10 11 12
Google+