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 で自動作成されるファイル(バックアップ、自動保存、ロック)の設定

Emacs ではファイルを編集すると、バックアップファイルという ~(チルダ)の付いたファイルができてしまい、これが結構うっとうしかったりします。
今回はこのバックアップファイルなどの Emacs が自動で作成するファイル、およびその設定について説明します。

Emacs が自動で作成するファイルの種類

Emacs がファイルの編集時に自動で作成するファイルはバックアップファイルを含めて大きく分けて 3 種類(細かく言うと 4 種類)あります。

種別 自動削除 用途
バックアップファイル foo.txt~ しない 編集前のファイルのバックアップ
自動保存ファイル #foo.txt# する 作業中のファイルの自動保存。 Emacs が不正終了した場合に使用
自動保存リストファイル .saves-xxx する 自動保存ファイルのリスト
ロックファイル .#foo.txt する 同時に修正しないためのロックに使用


これらのファイルは設定によって、作らないようにしたり、 作成先を変更したりできます。 お勧めは次のようにする感じです。
  • バックアップファイルは一カ所にまとめて作成
  • 自動保存ファイルは作成
  • 自動保存リスト、ロックファイルは作成しない
以降から 3 つのファイルについてそれぞれ解説していきます。

バックアップファイル (foo.txt~)

バックアップ(backup)ファイルはファイルをオープンする際、オープン時(編集前)のファイルをバックアップとして残します。 これは間違って修正や削除した時に使えます。

Emacs はかなり古くからあります。最近のソフトウェア開発ではバージョン管理システムを使うのが当たり前になってきているので、 いらないといえばいらないです。 うっとうしから作らないということにするというのも一つの手です。


作成しない場合には init.el に以下のように記述します。
 (setq make-backup-files t) 

ただ、チェックイン(コミット)はタイミングがあり、残しておきたいこともあります。 また、すべてのファイルをバージョン管理しているわけでもないです。
バックアップファイルはデフォルトだと編集対象と同じディレクトリーに作成します。 そのため、あちこちにできて、うっとうしくなります。 作成先を指定してまとめておくとそれほど邪魔ではありません。

作成先を変更する場合、 (対象ファイルの正規表現 . 作成先ディレクトリー) のペアー(コンスセル)を要素とするリスト(backup-directory-alist)で指定します。 デフォルトは nil(空) でリストの対象ファイルに引っかからない場合は元のファイルと同じところに作成します。
以下の例では すべて(".*")のファイルを対象に "~/.ehist" ディレクトリーに作成します。
 (setq backup-directory-alist '((".*" . "~/.ehist")))

移動して邪魔にならなくなったなら、一つ前だけでなく、もっとおいておきたいということもあります。番号をつけて複数前のまで残しておく なんてこともできます。
番号を付けて残す場合は、もちろん過去の全部残すってわけにはいかないので、範囲を指定します。
 ;; 番号付けによる複数保存
 (setq version-control     t)  ;; 実行の有無
 (setq kept-new-versions   5)  ;; 最新の保持数
 (setq kept-old-versions   1)  ;; 最古の保持数
 (setq delete-old-versions t)  ;; 範囲外を削除
kept-new-versions は過去の 5 個分残すという意味です。 kept-old-versions の方はちょっとわかりづらいですが、残し始めからの数です。 これが 1 であれば、最初(オリジナル)の分は残すってことになります。

自動保存

自動保存(auto-save)ファイルは編集中のファイルを保存したファイルで、 自動保存リスト(auto-save-list)ファイル はその自動保存しているファイルのリストを記述したファイルです。 これらは 正常に終了すると削除されますが、Emacs がエラーで落ちたりするとファイルが残ります。


Word などでも途中で落ちて、起動しなおすと編集中だったものが 「修復されたファイル」として出てきます。

Emacs の場合、異常終了した後、編集中だったファイルを開くと自動保存ファイルが残っていることを教えてくれます。 そこで M-x recover-this-file を実行して、自動保存された状態に戻すことができます。

ただ、それだと再度オープンした時にしかわかりません。 落ちた後、残っている自動保存ファイルを調べるには、自動保存リストファイルの中身を見ます。 recover-file というコマンドもあり、これはファイルを指定しての復帰です。
自動保存リストファイル自体は M-x recover-session でリストファイルのリストを表示することができます。

自動保存ファイル (#foo.txt#)

自動保存ファイルはバッファーを正常に閉じれば消えますし、復帰で助かることもあるので、 デフォルトのまま作るようにてしておいて問題ないと思います。


ちなみに自動保存をしない場合は次のようにします。
 (setq auto-save-default nil)

作成先を変更する場合、 (対象ファイルの正規表現 作成ファイルのパス t) のリストのリスト(auto-save-file-name-transforms)で指定します。
リストの 2 番目の要素はバックファイルのように作成先のディレクトリーでもいいですし、 正規表現のマッチング結果を使ったファイル名にすることもできます。 3 番目の t は名前の付け方を変えるオプションですが、 t で問題ないです。

リストの正規表現にマッチするものがない場合は元のファイルと同じところに出来ます。
デフォルトでは、一つだけリストに入っています。 これはリモートファイル( /ftp:xxx など)の場合に自動保存ファイルの作成先をローカルの一時ディレクトリー(temporary-file-directory)にするものです。
 '(("\\`/[^/]*:\\([^/]*/\\)*\\([^/]*\\)\\'" "一時ディレクトリー/\\2" t))
以下はすべてのファイル(".*")に対して "~/tmp" 以下に作成する例です。
 (setq auto-save-file-name-transforms   '((".*" "~/tmp/" t)))

この自動保存はデフォルトでは 30 秒たつか、 300 回入力操作を行うと実行されます。 ただ、デフォルトのままだとちょっと間隔が長いです。
自動保存の間隔を調整することもできます。
 ;; 保存の間隔
 (setq auto-save-timeout 10)     ;; 秒   (デフォルト : 30)
 (setq auto-save-interval 100)   ;; 打鍵 (デフォルト : 300)

自動保存リストファイル (~/.emacs.d/auto-save-list/.saves-xxxx)

こちらも正常に終了すれば消えるのですが、残っていたとしてもわざわざみて調べたりはあまりしないと思うので、 作る必要はないです。


作成しない場合は次のように記述します。
 (setq auto-save-list-file-prefix nil)
デフォルトではリストファイルは "~/.emacs.d/auto-save-list" のディレクトリーに作成されます。
以下は 作成先を変更する場合の例です。
 (setq auto-save-list-file-prefix "~/tmp/.saves-")
中止、作成先の変更ともに auto-save-list-file-prefix の変数を使います。
これはリストファイルの名前の前につける文字列で、これのパスの部分で作成先を変更し、 nil ならば作らないというようになります。 デフォルトは、この値が "~/.emacs.d/auto-save-list/.saves-" となっています。

ロックファイル (.#foo.txt)

ロック(lock)ファイル同じファイルを同時に編集しないためのロックとして作成されます。 こちらも正常に終了すると削除されます。
Emacs はもともと Unix 向けに作られたもので、 Unix は PC と違い、ネットを介して、あちこちからログインして使うことが想定されています。 ロックファイルはユーザーが同じファイルを編集していないかのチェックに使われます。

このロックファイルは ".#編集ファイル" の形式で編集ファイルと同じディレクトリーに作成されます。 実際はユーザー名やプロセス ID を組み合わせた長い名前のファイルを作成し、 そのシンボリックリンクとなっています。
自動で削除されるため作っておいても別にいいのですが、一人で使う PC などでは無駄なので、作成しないようにした方がいいでしょう。


作成しない場合は次のように記述します。 なお、作成先の変更はできないみたいです。
 (setq create-lockfiles nil)

特定のディレクトリーだけ作成しない

自動作成は行うけど、特定のディレクトリーにあるファイルに対しては作成したくないという時もあります。
例えば、 Google ドライブや DropBox のようなファイル共有サービスを使う場合、 その対象のディレクトリーは、サービス側で保存の度に履歴をとっているので、バックアップする必要がありません。


しかし、残念ながら Emacs では特定のディレクトリーだけ除くという機能は用意してくれてないみたいです。 というわけで自分で書いてみました。
 (defvar my-inhibit-auto-file-directory-list
   (list
    "~/DropBox"
    (concat (getenv "USERPROFILE") "/Google ドライブ")
    )
   "自動作成(バックアップ、自動保存、ロック)を禁止するディレクトリーのリスト")
   
 (add-hook 'find-file-hook
          '(lambda ()
             (when (listp my-inhibit-auto-file-directory-list)
               (let ((inhibit-ptn (concat "^\\(" (mapconcat '(lambda (str) (regexp-quote (expand-file-name str)))
                                                            my-inhibit-auto-file-directory-list "\\|") "\\)")))
                 (when (string-match inhibit-ptn buffer-file-name)
                   (setq backup-inhibited t) ;; バックアップ禁止
                   (auto-save-mode nil)      ;; 自動保存しない
                   (make-local-variable 'create-lockfiles) ;; ロックファイルを作成しない
                   (setq create-lockfiles nil)
                   )))))
my-inhibit-auto-file-directory-list のリストの要素にすると、そのディレクトリー以下(サブディレクトリーも含む)のファイルに対しては自動作成しないようになります。
自動作成ファイルは 3 つとも作らないようなっています。 変えたい場合は対象のところをコメントアウトしてください。


 

Node.js API (path) - ファイルパスの文字列操作

Node.js では 標準モジュール の一つである Path モジュールでファイルパスの文字列の解析、操作などの機能が提供されています。 今回はその Path モジュールを使ったファイルパス関連の操作について紹介します。

Path モジュールは 'path' を require して使用します。
 var path = require('path');
なお、Path モジュールではファイルパスの文字列処理のみで、ファイル自体のコピー、移動といった処理は fs (File System)モジュールになります。

ファイルパスの解析

ファイルパスを元に各部分を取得する関数が用意されています。
関数 対象
dirname ディレクトリーパス
basename ディレクトリーのパスを取り除いたファイル名。
拡張子抜きの場合は、第 2 引数に拡張子を指定する
extname 拡張子
 var pathstr = '/foo/bar/baz/asdf/quux.html';
 path.dirname(pathstr);    // /foo/bar/baz/asdf
 path.extname(pathstr);    // .html
 path.basename(pathstr);   // quux.html
 path.basename(pathstr, path.extname(pathstr));    // quux
まとめてやる場合は parse でオブジェクトを取得します。
 path.parse(pathstr);
 // { root: '/',
 //   dir: '/foo/bar/baz/asdf',
 //   base: 'quux.html',
 //   ext: '.html',
 //   name: 'quux' }
Windows の場合、 root は 「ドライブ名 + ":\"」 になります。
 path.parse('c:\\foo\\bar\\baz\\asdf\\quux.html');
 // { root: 'c:\\',
 //   dir: 'c:\\foo\\bar\\baz\\asdf',
 //   base: 'quux.html',
 //   ext: '.html',
 //   name: 'quux' }
逆の生成は format です。 生成には dir と base の要素しか使いません。
 console.log(path.format({
     dir : "/path/dir",
     base : "file.txt"
 }));
 // /path/dir/file.txt

相対パス、絶対パス

相対パスを絶対パスに変換する場合 resolve を使います。
 path.resolve('../foo.txt'); // /home/user/foo.txt
逆に絶対パスを相対パスに変換する場合は relative を使います。
このとき、第 1 引数が基準となるディレクトリーです。
 path.relative('/data/orandea/test/aaa', '/data/orandea/impl/bbb'); // ../../impl/bbb
ファイルパスが絶対パスか相対パスかの判定は isAbsolute です。
 path.isAbsolute('/foo/bar'); // true
 path.isAbsolute('../bar');   // false
 path.isAbsolute('c:\\Program Files'); // true

その他のファイルパス操作

ディレクトリーパスとファイル名の結合など、ファイルパスの結合には join を使用します。
 path.join('/foo/bar/baz/asdf/', 'quux.html'); // /foo/bar/baz/asdf/quux.html
path.join('/foo/bar/baz/asdf',  'quux.html'); // /foo/bar/baz/asdf/quux.html
複数まとめて結合することもできます。
 path.join('/foo', 'bar', 'baz/asdf', 'quux', '..'); // /foo/bar/baz/asdf/quux.html
normalize はパス中の '..'、 '.' を解決します。
ちなみに文字列上の解決のみですので、ちゃんと絶対パスに直したい場合は resolve の方を使います。
 path.normalize('./foo/bar/baz/../quz/.'); // foo/bar/quz
 path.resolve(  './foo/bar/baz/../quz/.'); // /home/user/programmers_notes/foo/bar/quz

Windows, POSIX(Unix)

Windows と Unix ではパス区切りなどが違います。それらは path オブジェクトのメンバーに格納されています。
メンバー名 対象 Windows Unix
sep パス区切り \ /
delimiter 複数パスの区切り ; :
 '/foo/bar/baz'.split(path.sep); // [ '', 'foo', 'bar', 'baz' ]
 
 process.env.PATH;      // C:\Windows\system32;C:\Windows; ...
 process.env.PATH.split(path.delimiter);
 // [ 'C:\\Windows\\system32',
 //   'C:\\Windows',
 //     :
Windows と Unix では処理方法、結果などが変わってきます。
Window 上で Unix(POSIX) のパス処理をしたい場合などには posix, win32 を使います。
 path.posix.sep; // /
 path.win32.sep; // \
 path.posix.join('/foo/bar/baz/asdf/', 'quux.html'); // /foo/bar/baz/asdf/quux.html
 path.win32.join('/foo/bar/baz/asdf/', 'quux.html'); // \foo\bar\baz\asdf\quux.html
通常、 path の関数を呼び出した場合、その環境に合わせて posix または win32 の関数が呼び出されています。

サンプルコード

記事で使用したサンプルコードは以下のリンクから取得(名前をつけて保存)できます。 これを node コマンドの引数に渡して実行します。
$ node path.js 
node コマンドの使い方について詳しくは以前の記事をご覧ください。

 
このページをシェア
アクセスカウンター
カレンダー(アーカイブ)
プルダウン 降順 昇順 年別

04月 | 2016年05月 | 06月
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 31 - - - -


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

yohshiy

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

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

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