Emacs における C, C++ 系モードのインデント設定

C, C++ などのコードを Emacs で書いていて、 「インデントを自動でやってくれるのはいいけど、 自分が望んでいるものと違う」 ということはないでしょうか?
C, C++ を始め、 Java 、 JavaScript 、 C# などのモードは cc-mode を元に作られています。 この cc-mode ではインデントを細やかに設定できる分、やり方が少しわかりづらいです。
今回はこの C, C++ 言語系のモードでのインデントの設定方法について説明したいと思います。

また、インデントの設定が適切にできていれば、 {, ; などのキーを入力した時に自動で改行、インデントしてくれるという便利な機能も使えます。

設定方法とバッファーローカル変数

最初に cc-mode 関連の設定を行う方法について説明します。 Emacs で設定を行う場合には 2 通りの方法があります。

カスタマイズ

cc-mode 関連の設定項目はカスタマイズでは C グループに属するので、次の手順で設定します。
  1. M-x customize-group [RET] c で C group のカスタマイズ画面を開く
  2. 設定したい項目を変更
  3. 設定([Set ..])、保存([Sava ..])

設定ファイルの記述とバッファーローカル

カスタマイズを使わない場合は設定ファイルに記述するのですが、 ここで注意点があります。
それは設定する変数がバッファーローカルかどうかという点です。 通常、変数に設定した値は emacs 全体で共通に使われますが、 バッファーローカルな変数はバッファーごとに固有の値を持ちます。
次章で紹介する機能の ON/OFF 的な設定値は通常の変数ですが、 インデントの設定値の多くはバッファーローカルな変数となっています。

バッファーローカルな変数を設定ファイルで設定する場合には、モードのホックを使って バッファーを開いた時に設定する必要があります。
;; init.el だけに設定されてしまう
(setq c-basic-offset 4)

;; ホックを使った設定
(defun my-c-c++-mode-init ()
  (setq c-basic-offset 4)
  )
(add-hook 'c-mode-hook 'my-c-c++-mode-init)
(add-hook 'c++-mode-hook 'my-c-c++-mode-init)
面倒かもしれませんが、インデント量のような値はモードごとに変えたいため、 このようになっています。


また、カスタマイズで設定した値はバッファーローカルにならないということも注意する必要があります。
これはバッファーローカルな変数でも全てのモードで共通でも構わないという時には楽ですが、 逆にモードで個別に設定したいという場合にはカスタマイズからは設定できないようになっています。


この記事では基本的にカスタマイズ、設定ファイルの両方を説明していますが、 設定する場合は次のような方針で行って下さい。
  • バッファーローカルではない変数(機能の ON/OFF など)
    • カスタマイズ、設定ファイルのどちらでも可
  • バッファーローカル(インデント関連の設定など)
    • 共通した値を使用 → カスタマイズ
    • モードごとに設定 → 設定ファイル
ただし、設定ファイルからであればどの変数でもバッファーローカルにすることは可能です。
(defun my-c-c++-mode-init ()
  ;; 変数をバッファーローカルに
  (make-local-variable 'c-tab-always-indent)
  (setq c-tab-always-indent nil)
  )

インデントの設定を使う Emacs の機能

インデントのスタイルを使う機能を大きく分けると 2 つです。
  1. オフセット(インデント量)を使う機能
  2. 自動改行、インデント

オフセット(インデント量)を使う機能

[Tab] によるインデント、 C-M-\ のインデント整形、 C-j の改行 + インデントなどオフセット(インデント量)を使う機能です。 オフセットはコーディングする上で最低限していないといけない設定でしょう。

[Tab] キーの挙動の変更

[Tab] キーでインデントですが、これは C Tab Always Indent(c-tab-always-indent) の設定を変えると、 挙動を変えることができます。

動作
t 常にインデント
nil 左端(文字の前)ではインデント、それ以外はタブの挿入
t, nil 以外 コメント、文字列などではタブ、それ以外はインデント

この値が t の場合、 Tab キーを押しても インデントをあわせるだけで、タブは挿入できません。 t, nil 以外( 1 など)の場合もコメントなど特定の領域以外はタブを挿入できません。
それらの設定でタブを挿入したい場合には C-q [Tab]などを使います。

c-tab-always-indent はバッファーローカルではないため、カスタマイズ、設定ファイルのどちらでも設定しても同じです。

カスタマイズ :
emacs_indent_tab_always_indent.png

設定ファイル :
(setq c-tab-always-indent t)

自動改行、インデント

{, ; などのキーを入力すると自動で改行、インデントをしてくれる機能です。 カスタマイズで設定するか、設定ファイルに以下を追記すると有効になります。
(setq c-auto-newline t)
これが有効になっているとモード行のモードを表すところに "/la" が付きます。 正確には "/a" の自動改行と "/l" の electric-state (インデント)は別なのですが、 ほぼセットだと思って下さい。
このモードで改行やインデントをさせずに { などを入力したい場合は C-q { といったように入力します。 特に : はネームスペース等でも使うので、"::"(コロン 2 つ)を入力する C-c : も用意されています。

この機能は { 等で改行するので、スタイルは改行位置などもちゃんと設定する必要があります。 自動改行を有効にしなければ、オフセット量だけでも十分ですが、 コーディングが非常に楽になる機能なので、ぜひ使ってみてください。

空白を一度に削除

ついでなので、 hungry-delete の機能も紹介します。
これは [Back Space] などで空白を削除すると 空白以外が出てくるところまで一度に削除してくれます。

以下の記述を追記していると有効になります。
(setq c-hungry-delete-key t)
有効になっているとモード行に "/h" が付きます。

スタイルの設定

インデントの設定では、まずベースとするスタイルを指定します。

スタイルの種類

選択可能なスタイルを次の表にあげます。 ただし、バージョンによって変わるかも知れないので、 正確には C-h v c-style-alist で確認して下さい。

スタイル 説明
gnu GNU スタイル
k&r C の古典 『 K&R 』のスタイル。
標準の ANSI C と文法自体少し違うので、最近ではほとんど使われてない。 本自体も今の版はこのスタイルではない。
bsd BSD/Allman スタイル。
Visual Studio のスタイルはこれがベース。
whitesmith 古くからある商用コンパイラー Whitesmiths のスタイル
stroustrup C++の作者であるストロヴストルップ『プログラミング言語C++』のスタイル
ellemtel 『Programming in C++, Rules and Recommendations』で規定されているスタイル
linux Linux カーネルのコードで使われているスタイル
java java-mode で使われる Java のコーディングスタイル
awk awk-mode で使われる AWK のコーディングスタイル。
python Python モードのスタイルではなく、 Python の C 拡張モジュールを書く際のスタイル
user ユーザー定義用の特殊なスタイル。(後述)

ここで挙げたもののうち、主要なものは Wikipedia に説明があります。

スタイルの設定方法

スタイルの設定はカスタマイズを使った方法で説明します。


C グループの C Default Style でモードごとのスタイルを設定します。 これはモードごとに対応するスタイルを設定する変数ですので、バッファーローカルではありません。
emacs_indent_style.png

C#、 JavaScript など後からパッケージで追加するようなモードは出てませんが、 各 lisp ファイル内で定義されているはずですので、ここで設定する必要はありません。


各モードに指定するスタイル名は前節のものを指定します。 インデントなど指定したスタイルで問題がなければ、それで設定は完了です。
そうでなければ、個別に設定していく必要があります。 例えば、 Visual Studio 風のスタイルにしたい場合、 "bsd" が近いのですが、他の設定もしないと綺麗に一致はしません。

基本オフセット量の設定

基本オフセットというのは、 1 段インデントをする際のサイズです。

カスタマイズの場合、C Basic Offset のパラメーターで設定します。
emacs_indent_basic_offset.png


c-basic-offset はバッファーローカルな変数ですが、カスタマイズで設定した場合には、 cc-mode を元にした全てのモードで同じ値が使用されます。
モード別で指定するためには設定ファイルでロード時に設定にします。
(defun my-c-c++-mode-init ()
  (setq c-basic-offset 4)
  )

(add-hook 'c-mode-hook 'my-c-c++-mode-init)
(add-hook 'c++-mode-hook 'my-c-c++-mode-init)

タブ幅

先ほどの基本オフセットというのはタブのサイズとは別ものです。 必ずしもタブ一つがインデントの一段というわけではありません。
タブ幅が 8 、 基本オフセットも 8 であれば 1 段でタブ1つですが、 タブ幅が 8 、 基本オフセットが 4 ならば 2 段でタブ 1 つとなります。

タブ幅を変更したいという場合は以前の記事を見て下さい。 なお、タブ幅(tab-width)もバッファーローカル変数です。

タブの代わりに空白

タブとインデントの関連でもう一つ補足しておきます。
indent-tabs-mode の値に nil を設定するとインデントの際にタブを使わずに、 空白(スペース)のみ使用するようにできます。 たまに 「タブは使うな」 といったコーディングルールがあったりするので、そういった場合に設定します。

カスタマイズでも設定できるのですが、 全モードで使われると影響が大きいので、 設定ファイルで設定した方がいいでしょう。
(defun my-c-c++-mode-init ()
  (setq indent-tabs-mode nil)
  )

;; 略 

インデント量の設定

インデントの状況別のオフセット量は C Offsets Alist(c-offsets-alist)で設定します。

emacs_indent_offsets.png

オフセット値

オフセットとして設定する値によく使うのは 3 つです。
意味
0 インデントなし
+ 1 段インデント
- 1 段インデントを戻す

この +, - で増減する単位が先ほどの c-basic-offset のサイズです。

これ以外にも数値、記号、関数など色々使えます。 その他の値については C-h v [RET] c-offsets-alist で確認して下さい。

Syntax

オフセット値は状況ごとに設定できるようになっています。 そのうちの幾つかを紹介します。
if, while ブロック
制御文のブロックです。スタイルごとに違いがでやすいところだと思います。
emacs_indent_offset_if.png
switch ブロック
制御文の中でも switch 文には case ラベルの設定もあります。
emacs_indent_offset_switch.png
クラス内関数
関数の定義のブロックは defun-open なのですが、 クラス内のインライン定義の場合は inline-open になります。
emacs_indent_offset_inline.png
上記以外の項目についても、以下のサイトに説明があります。

スタイルの構成

ここで、スタイルの中身について説明します。

スタイルは継承することができ、 構成は継承元のスタイル名と 変数-値 ペアのリストからなっています。
`("bsd" ;; <- 継承元スタイル
  ;; (変数 . 値) のリスト
  (c-basic-offset . 4)
  (tab-width . 4)
  (c-offsets-alist . ((inline-open . 0)
                      (substatement-open . 0)
                      (case-label . 0)))
  (c-hanging-braces-alist . ((inline-open         before after)
                             (block-open          before after)
                             (substatement-open   before after)))
  (c-cleanup-list . (defun-close-semi
                      list-close-comma
                      scope-operator
                      compact-empty-funcall)))
変数-値のリストを継承元から設定していき、同じ変数の場合は対象のスタイルの値で上書きされます。
例えば、 次節の c-hanging-braces-alist などは継承元で設定されていても、 それは全く使われず、今のスタイルのリストが使用されます。

ただし、 c-offsets-alist は特別でリストの中身も継承されます。
defun-open の値が継承元で設定されていて、今のスタイルで設定されていないとすると、 継承元の値が使われます。


個々のスタイルでどのような値が設定されていかについても C-h v c-style-alist で見ることができます。

user スタイル

c-offsets-alist にはもう一つ特別な点があり、 カスタマイズで設定した値は user スタイルの値として設定されます。

user スタイルはすべてのスタイルの継承元です。
そのため、カスタマイズで設定された値がすべてのモードにそのまま適用されることはありませんが、 設定値はスタイルが優先されます。 スタイルの設定から漏れているものをここで設定する感じです。


なお、設定ファイルからであれば、ロード時に値を変更することもできます。
(defun my-c-c++-mode-init ()
  (setq c-offsets-alist '((statement-case-open . +)
                          (case-label . 0)))
  )
また、自作のスタイルを作成することもできます。 自作のスタイルのサンプルはこの記事の最後にあげていますので、 そちらをご覧ください。

自動改行、インデントのための設定

機能で紹介した自動改行、インデントを使う場合、 改行位置などの設定も必要となります。

改行位置

{ などのキーを押した時に改行を入れるかどうかを指定するため 3 つの変数があります。
キー 変数名
{ } (ブレース) c-hanging-braces-alist
: (コロン) c-hanging-colons-alist
, ; (カンマ、セミコロン) c-hanging-semi&comma-criteria

emacs_indent_hanging.png


これらは対象ごとに before, after を指定したり、複雑な場合は関数で指定します。
substatement-open を例にすると次のようになります。
after
if (a == 0) {
    foo();
}
befor
if (a == 0) 
{   foo();
    bar(); }
befor after
if (a == 0) 
{
    foo();
}
設定する対象の名前は c-offsets-alist の対象の名前とほとんど同じなので、 そちらの説明をご覧下さい。


3 つの変数はどれもバッファーローカルなので、設定ファイルの場合はロード時に設定するようにします。
(defun my-c-c++-mode-init ()
  (setq c-hanging-braces-alist '((class-open before after)
                                 (class-close before)))
  )

改行位置(C#)

C# モード (csharp-mode) の場合、 { を押してインデントが上手くいかないことがあります。
これはインデントの設定があっていないのではなく、 csharp-mode では { のキー割り当てを拡張したコマンドにしていて、 それが上手く動いていないためです。
手っ取り早く治す場合、 { の割り当てを他のモードと同じ c-electric-brace にすると治ります。
(defun my-csharp-mode-init ()
  (local-set-key "{" 'c-electric-brace)
  )
(add-hook 'csharp-mode-hook 'my-csharp-mode-init)

Clean up

c-cleanup-list は "} else {" のようにつなげるかどうかや "foo ()" のように関数の前の空白を入れるかどうかなどの設定です。 これを設定していると自動インデントの際に空白、改行を削除(追加)してくれます。
emacs_indent_cleanup.png

Clean up の説明は、英語ですが Emacs のマニュアルがサンプル付きで分かりやすいです。 こちらの変数もバッファーローカルです。
(defun my-c-c++-mode-init ()
  (setq c-cleanup-list '(scope-operator
                         compact-empty-funcall))
  )

カスタムスタイル

デフォルトで用意されたスタイルに合わない場合、個別に設定していきます。 これを自分でスタイルを作ってまとめて設定することも可能です。
開発しているプロジェクトのコーディングスタイルがある場合は、 「カスタムスタイルを用意して、メンバーにそれを使ってもらう」 といった際に使えると思います。

サンプルを兼ねて、使いそうなカスタムスタイルを 2 つ挙げたいと思います。

Google コーディングスタイル

Google は C++ のコーディングガイドを公開しており、 そこの「書式」の章でインデントのスタイルも規定しています。 emacs_indent_google.png

そこでは Emacs 用の設定ファイル(google-c-style.el)も公開されています。 使いたい場合はリンクを [名前を付けてリンク先を保存] でダウンロードして下さい。

取得した lisp ファイルは load-path の通ったフォルダーに置き、 ~/.emacs.d/init.el に以下の記述を行います。
(defun my-c-c++-mode-init ()
  (require 'google-c-style)
  (google-set-c-style)
  ;; (google-make-newline-indent)
  )

(add-hook 'c-mode-hook 'my-c-c++-mode-init)
(add-hook 'c++-mode-hook 'my-c-c++-mode-init)
因みに google-make-newline-indent を記述すると [Enter] キーで改行とインデントを一度に行うようになります。
ただ、改行するときに C-j を押せばいいだけなので、 設定する必要はないと思います。

Visual Studio のスタイル

Windows で開発していると、自分以外のプロジェクトメンバーが Visual Studio を使っているという驚きの状況に陥ることがあります。 どうやら IDE でコード書いている人がいるというウワサは本当みたいです。

仕方がないので、私はインデントを Visual Studio 風に設定しています。
しかし、スタイルを "bsd" しても、他の設定もしないと一致しません。 そこで、 Google スタイルのようにまとめて設定するファイルを作成してみました。 リンク先をダウンロード([名前を付けてリンク先を保存])して、 パスの通ったフォルダーにおいて、以下の記述を ~/.emacs.d/init.el に記述して下さい。
(autoload 'vs-set-c-style "vs-set-c-style")
(add-hook 'c-mode-hook 'vs-set-c-style)
(add-hook 'c++-mode-hook 'vs-set-c-style)


スポンサーサイト



 

Emacs におけるスクロールの挙動とその設定

Emacs ではデフォルトのままだとスクロールする時、ガクガクと動く感じがします。 その調整も含めて、今回は Emacs でのスクロールの挙動とその変更方法について説明します。

カーソル移動によるスクロール

なぜ、ガクガクとスクロールする感じになるかというと、 Emacs では画面端になって、スクロールする際に、 画面中央にカーソルがくるようにするためです。

emacs_scroll_step.png

これはこれで、なるべく画面の中央で編集ができるため、良い点もあります。 ただ、 Word など他のアプリと挙動が違うので、ちょっと気持ち悪く感じます。

ステップ量

中央に移動する挙動を変えるには scroll-conservatively の値を変更します。
この値のデフォルトは 0 であり、これを 1 にすると、 スクロールは 1 行となり、自然な感じになります。
(setq scroll-conservatively 1)
ちなみに、scroll-step の変数でも同じように変わりますが、 scroll-conservatively の方が新しく用意されたもので、大きな値などにも対応しており、よりよいです。

マージン

一行ずつスクロールするようになると、書き続けるうちに画面の下の方ばかりで編集することになることがあります。 見づらいですが、そういうものといえばそういうものですし、 C-l で中央にカーソルを持ってくることもできます。


ただ、 Emacs にはスクロールのマージンを指定する機能もあり、 これを設定すると画面の端に到達する前に画面をスクロールできるようになります。
(setq scroll-margin 5)
emacs_scroll_margin.png

1 画面のスクロール

1 画面のスクロールというのは C-vM-v によるページダウン、ページアップのことです。

重複行数

ページをスクロールする際、移動をわかりやすくするため、ちょっと重複するようになっています。 特にターミナルで動作させている時など、この重複は大事です。

この値は next-screen-context-lines で設定し、デフォルトは 2 です。
(setq next-screen-context-lines 5)
emacs_scroll_duple.png

カーソル位置の保持

scroll-preserve-screen-position の変数に t を設定すると ページスクロール時に画面上におけるカーソルの位置をなるべく変えないようにします。
(setq scroll-preserve-screen-position t)
emacs_scroll_conpos.png

他のアプリなどでは保持することが多いので、 どちらかというと設定しておいた方が自然かなという気がします。

マウスホイール

最近では Emacs でもデフォルトでマウスのホイールによるスクロールができるようになっています。
ただ、他のアプリではホイールでスクロールするとカーソルは移動せずにスクロールするものですが、 Emacs のスクロールはカーソルありきの移動です。 どちらが良い悪いとも言えませんが、同じような感じにすることはできません。 そのかわりといっては何ですが、 Emacs ではターミナルでさえ、ホイールスクロールが使えるようになっています。


ホイールスクロールに関しては、設定する必要はあまりありませんが、 Emacs では ShiftCtrl を押しながら、 ホイールした時のスクロール量の調整などもできるようになっています。
 ;; マウスホイールによるスクロール時の行数
 ;;   Shift 少なめ、 Ctrl 多めに移動
 (setq mouse-wheel-scroll-amount
       '(5                              ; 通常   (デフォルト 5)
        ((shift) . 1)                   ; Shift  (デフォルト 1)
        ((control) . 40)                ; Ctrl   (デフォルト nil = 無効)
        ))

設定用コード

init.el ファイルの記述用に設定をまとめてみました。
 ;; スクロールした際のカーソルの移動行数
 (setq scroll-conservatively 1)
 
 ;; スクロール開始のマージンの行数
 (setq scroll-margin 10)
 
 
 ;; 1 画面スクロール時に重複させる行数
 (setq next-screen-context-lines 10)
 
 ;; 1 画面スクロール時にカーソルの画面上の位置をなるべく変えない
 (setq scroll-preserve-screen-position t)
 
 
 ;; マウスホイールによるスクロール時の行数
 ;;   Shift 少なめ、 Ctrl 多めに移動
 (setq mouse-wheel-scroll-amount
       '(5                              ; 通常
        ((shift) . 1)                   ; Shift
        ((control) . 40)                ; Ctrl
        ))
 

条件分岐 - 環境設定のための Emacs Lisp 入門

Emacs Lisp 入門の第 8 回です。
設定に絞った Emacs Lisp の入門なので、制御構造は必要ないかと思い、前回で終了していました。 しかし、 OS など環境の違う場合に同じ設定ファイルを使おうとすると、条件分岐は必要になってきます。 そこで、今回、 elisp での条件分岐について追加しました。

条件分岐の式

条件分岐の式の基本は if です。
 (if 条件式
     真の式
   偽の式1
   偽の式2
    :)
条件式は真ならば式の 2 番目の引数として渡した式が評価され、 偽ならば 3 番目以降が順に評価されます。


ただし、 if は偽の時は複数書けるのですが、真で評価する式には 1 つしか書けません。 こういった場合、 progn で複数書けます。
 (if 条件式
     (progn 
       式1
       式2
       :))
ただ、ちょっと書くのが面倒なので、真の時だけ渡した式を順に評価する when も用意されています。
 (when 条件式
   式1
   式2
   :)
また、逆に偽の時に実行する unless もあります。

条件式

条件分岐に使う条件式では nil の場合に偽、 t など nil 以外の場合に真として判定されます。
nil 以外ですので、 数値の 0、 空文字などでも 真となります。
 (if nil "true" "false") ;; "false"
 (if t "true" "false")   ;; "true"
 (if 0 "true" "false")   ;; "true"
 (if "" "true" "false")  ;; "true"
空リスト '() が真か偽かは Lisp の処理系によって違うのですが、 elisp では空リストは nil です。
例えば、 変数に 空リスト '() を格納したとしても、その変数には nil が格納されることになります。
 (if '() "true" "false")  ;; "false"
 
 (setq foo '())
 foo ;; nil

一致判定

一致判定には eq を使います。
設定には基本的に eq を覚えておけば十分ですが、 似たような関数として、 equal というのもあり、こちらの方がゆるい一致判定といえます。

関数 機能
eq シンボル、整数値が一致。
equal 2 つの値が一致

 (eq 'foo 'foo)      ;; t
 (eq 1 1)            ;; t
 (eq "foo" "foo")    ;; nil
 (equal "foo" "foo") ;; t

論理式

elisp にも論理式があります。 設定に関して言えば、 not ぐらいを覚えておくぐらいでいいかと思います。

関数 意味 説明
not 否定 真、偽の反転
and 論理積 すべて真の時、真
or 論理和 どれか一つ真の時、真

 (not t)    ;; nil
 (not nil)  ;; t
 
 (and nil t) ;; nil
 (or  nil t) ;; t

設定でよく使う条件式

実際に設定でよく使う条件式を紹介します。

機能 切り替え
system-type OS の判定 OS
window-system Window システムの判定 ターミナルかどうか
file-exists-p ファイルの存在チェック ファイル、ライブラリーの有無
require, load ロードの成功、失敗
fboundp 関数が定義済みかどうかのチェック バージョン

OS

設定ファイルの共通化の基本としては OS で処理を変えることだと思います。
OS を表すシンボルが system-type の変数に格納されており、 これで OS を判断します。

格納されている主なシンボルを以下の表にあげます。 詳しくは C-h v system-type で変数の内容を確認するようにしてください。

シンボル タイプ
gnu/linux GNU/Linux
gnu/kfreebsd Free BSD
darwin Mac OS X
windows-nt Windows
cygwin Windows(Cygwin 版)


なお、 Windows 7 などでも Cygwin でビルドした Emacs でなければ、 windows-nt になります。
また、 シンボル名の '/' の文字はただの文字として扱われています。 elisp は前置法なので、 +, - などわりといろんな記号が変数(シンボル)名に使用できます。
 ;; Windows の場合、 IME の変換でエラーがでないようにする
 (when (eq system-type 'windows-nt)
   (global-set-key [M-kanji] 'ignore)
   (global-set-key [kanji] 'ignore)
   )

ターミナル

window-system の変数には実行時の Window システムが 'x', 'w32' などのシンボルで格納されています。 Window システムというのは、 Unix における X Window System など GUI を実現しているシステムです。 これで、 OS の判定ができなくもないですが、 system-type を使う方が普通です。
では、 window-system を何に使うかというと、ターミナルかどうか判定に使います。 ターミナルではキーコードなどの問題で切り替えが必要なことがあります。
Window システムが使われていないということで、ターミナルでは window-systemnil となっています。
 ;; ターミナルの場合(window-system が nil)、
 ;; <backspace> が C-h になるため、 C-h で一文字削除に設定
 (unless window-system
   (global-set-key "\C-h" 'delete-backward-char)             ;; 全般
   (define-key isearch-mode-map "\C-h" 'isearch-delete-char) ;; インクリメンタルサーチ用
   (add-hook 'c-mode-common-hook
            '(lambda ()
               (local-set-key "\C-h" 'c-electric-delete)))  ;; C 言語系モード
   )

ファイル、ライブラリーの有無

設定ファイルのロード中にエラーが発生すると途中で止まってしまいます。

file-exists-p の関数を使うと、ファイルの有無がチェックできるので、 ファイルがあるときだけロードするということができます。
 (setq custom-file "~/.emacs.d/custom_setttings.el")
 (if (file-exists-p custom-file)
     (load custom-file))
ただ、以前ファイルのロードのところで説明した load第 2 引数に t を指定すると、 「ロード対象のファイルが存在しない」という問題に関しては、エラーを発生しなくなります。
そのため、前述のコードは次のように書けます。
 (setq custom-file "~/.emacs.d/custom_setttings.el")
 (load custom-file t)
load と同様に require第 3 引数に t を指定 すると エラーが発生しなくなります。
これらはエラーは発生しなくても、ロードに成功すれば t 、 失敗すれば nil を返します。 これを利用して、 ロードし、成功した場合だけ実行する処理 が書けます。
 (when (require 'auto-complete-config nil t)
   (ac-config-default))

バージョン

共通して設定ファイルを使用する場合、すべての Emacs が同じバージョンとは限りません。 その対策として、バージョンの番号によって処理を切り替えてもよいのですが、 使いたい関数が定義されているかチェックしてから実行した方が確実です。
fboundp を使うと、関数が定義されているか をチェックすることができます。
 (if (fboundp 'normal-top-level-add-subdirs-to-load-path)
     (normal-top-level-add-subdirs-to-load-path))
以前、変数の解説で、一つのシンボルには 関数と変数が格納(結合)できる と説明しました。
fboundp は関数用ですが、 変数が定義されているかどうかをチェックする boundp という 関数もあります。 ただ、変数の場合は未定義の変数に値を設定したとしても、エラーではないので、 あまり設定では使用しません。



 
このページをシェア
アクセスカウンター
アクセスランキング
[ジャンルランキング]
コンピュータ
31位
アクセスランキングを見る>>

[サブジャンルランキング]
プログラミング
5位
アクセスランキングを見る>>
カレンダー(アーカイブ)
プルダウン 降順 昇順 年別

08月 | 2023年09月 | 10月
- - - - - 1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30


はてな新着記事
はてな人気記事
ブロとも申請フォーム
プロフィール

yohshiy

Author:yohshiy
職業プログラマー。
仕事は主に C++ ですが、軽い言語マニアなので、色々使っています。

はてブ:yohshiy のブックマーク
Twitter:@yohshiy

サイト紹介
プログラミング好きのブログです。プログラミング関連の話題や公開ソフトの開発記などを雑多に書いてます。ただ、たまに英語やネット系の話になることも。