Top | Wiki | Blog | Github  

目次

Configurations for GNU Emacs

はじめに

  • この文章は,org2dokuwiki.plを使って生成しています.
  • init.el 本体は,github に公開しています.
  • init.org から init.elinit.pdfinit.odtwiki を生成しています.
  • 一部の関数定義を utility.el に分離しています.
  • コピペだけで動かなかった場合は,ページ最下部のコメント欄にご意見をどうぞ.

基本設定

この設定群を利用するために設定です.一部の関数は記述しておかないと動かない可能性があります.

init.el のヘッダ

;; -*- lexical-binding: t -*-
;; Configurations for Emacs
;;                                         Takaaki ISHIKAWA  <takaxp@ieee.org>

init ファイルの読み込み時間計測

次の関数を init.el の最初に記載して,オプション付きで after-init-hook に乗っければ,initファイルの読み込み時間を計測できます(GUIのフレーム生成を含まない).これ以降に設定する emacs-init-time の派生関数と違い, after-init-hook で実行される処理の時間もわかります(ほかの処理も微妙に入るので,あくまで目安です).

(defconst before-load-init-time (current-time))
(defun my:load-init-time ()
  "Loading time of user init files including time for `after-init-hook'."
  (let ((time1 (float-time
                (time-subtract after-init-time before-load-init-time)))
        (time2 (float-time
                (time-subtract (current-time) before-load-init-time))))
    (message (concat "Loading init files: %.0f [msec], "
                     "of which %.f [msec] for `after-init-hook'.")
             (* 1000 time1) (* 1000 (- time2 time1)))))
(add-hook 'after-init-hook 'my:load-init-time t)

after-init-hook の値をチェックして,最後に配置されていることに留意します.以下は, after-init-hook の例です.

(session-initialize recentf-mode my:emacs-init-time my:load-init-time)

起動時間の計測

M-x emacs-init-time を実行すると,Emacsの起動にかかった時間が表示されます.個人的にはミリ秒表示が好きなので,手を加えます.元ネタはすぎゃーんメモからです.感謝.

(defun my:emacs-init-time ()
  (message "Emacs booting time: %.0f [msec] from `emacs-init-time'."
           (* 1000
              (float-time (time-subtract
                           after-init-time
                           before-init-time)))))
(add-hook 'after-init-hook 'my:emacs-init-time)

GCサイズの最適化

起動時に発生するガベージコレクトを防きます.起動後に使用しているメモリサイズを超えていれば良さ気. garbage-collection-messages を設定しておくと,ガベージコレクトが生じる時にメッセージが出るようになります.

(setq gc-cons-threshold 134217728) ;; 128MB
(setq garbage-collection-messages t)

[exec-path-from-shell] PATH設定をシェルから継承する

外部プログラムのサポートを得て動くパッケージは,設定の過程でプログラムが見つからないと怒られることがしばしばあります. exec-path-from-shell は,シェルに設定した PATH の情報を継承して exec-pathPATH を設定してくれます.私は起動時に環境を切り替えることがあるので使ってませんが,使われている方は多いようです.

(when (and (require 'exec-path-from-shell nil t)
           (memq window-system '(mac ns)))
  (exec-path-from-shell-initialize))

cl を使う

同時にバイトパイル時の警告を回避するために,いくつかのパッケージを eval-when-compile の中に記述します.

(eval-when-compile
  (require 'cl-lib)
  (require 'org)
  (require 'org-clock)
  (require 'org-mac-link))

[load-package-p] 設定の読み込みフラグを確認する

loading-packages 変数に,設定を無視するパッケージを記述しておくと, autoload-if-found 内でそれらを読み込まないようにします.読み込まなかったパッケージは,Messages バッファにそのことを報告します. autoload-if-found は本来の実装ではなく,loading-packages を参照するように手を加えています.

(defun load-package-p (file)
  (let ((enabled t))
    (when (boundp 'loading-packages)
      (dolist (package loading-packages)
        (let ((name (car package))
              (flag (cdr package)))
          (when (and (stringp name)
                     (equal file name)
                     (not flag))
            (setq enabled nil)
            (message "--- `%s' was NOT loaded explicitly" name)))))
    enabled))

リストで関数を渡す autoload-if-found を使う

eval-after-load とのペアでマクロ化したバージョンもあります(次章参照).ただ,生成されるバイトコードに問題がありそうなので,最近は autoload-if-foundwith-eval-after-load の組み合わせに戻しています.最初に when 判定をすることで,パッケージが未インストールの状態に各種設定をスキップするので安全です.

  (when (autoload-if-found
         '(f1 f2) ;; 関数リスト.要素の関数を呼ぶ時に,パッケージが読み込まれる
         "package-name" nil t) ;; 第4引数まで指定すると,M-x で補完対象になる.
 
    ;; (1) バイトコンパイル時に警告がでたら,対応するパッケージを記載
    (eval-when-compile
      (require 'package-name nil t))
 
    ;; (2) 遅延読み込みする設定群
    (with-eval-after-load "package-name"
      (setq v1 t)
      (setq v2 nil)
      (define-key package-name-map (kbd "q") 'f1))
 
    ;; (3) パッケージが存在すれば, Emacs 起動時に読み込む設定群
    (push '("\\.hoge$" . package-name-mode) auto-mode-alist)
    (add-hook 'after-init-hook 'f1)
    (global-set-key (kbd "r") 'f2))

次のカスタマイズされた autoload-if-found は引数にリストのみを受け付けます.

(defun autoload-if-found (functions file &optional docstring interactive type)
  "set autoload iff. FILE has found."
  (and (load-package-p file)
       (locate-library file)
       (progn
         (dolist (f functions)
           (autoload f file docstring interactive type))
         t)))

[eval-after-autoload-if-found] 複数関数を対象とする遅延読み込み

Twitterでぼやいていたら @cvmatさんが降臨して次のマクロを作ってくださいました.感謝感謝.

autoload-if-found で遅延読み込みすると,eval-after-load と組み合わせるので,どうしてもインデントが増えてしまうのが欠点です.

例えば,cycle-buffer を遅延読み込みしたい場合, setq で変数を書き換えするために随分とインデントが進んでいます.

# (eval-after-autoload-if-found '(f1 f2) “f”) ;; autoload に複数指定 # (eval-after-autoload-if-found '(f1 f2) “f” nil t) ;; interactive を使う時 # (when (eval-after-autoload-if-found '(f1 f2) “f” nil t nil '()) (add-hook..)

(when (autoload-if-found
       '(cycle-buffer cycle-buffer-backward) "cycle-buffer" nil t)
  (with-eval-after-load "cycle-buffer"
    (setq cycle-buffer-allow-visible t)
    (setq cycle-buffer-show-length 12)
    (setq cycle-buffer-show-format '(" [ %s ]" . " %s"))))

これをスッキリさせるために eval-after-autoload-func を使います.記述がシンプルになり,行数も桁数もスッキリです.

(eval-after-autoload-if-found
 '(cycle-buffer cycle-buffer-backward) ;; autoload で反応させる関数
 "cycle-buffer" nil t nil      ;; 反応させた関数のコールで読むパッケージ指定
 '(;; パッケージ読み込み後の設定
   (setq cycle-buffer-allow-visible t)
   (setq cycle-buffer-show-length 12)
   (setq cycle-buffer-show-format '(" <(%s)>" . " %s"))))

さらに戻り値を判定して,グローバルなキーアサインもできます.存在しないパッケージの関数呼び出しを明示的に防ぐために有効です. hook 系の登録も同様です.

(when (eval-after-autoload-if-found
       '(cycle-buffer cycle-buffer-backward) "cycle-buffer" nil t nil
       '((setq cycle-buffer-allow-visible t)
         (setq cycle-buffer-show-length 12)
         (setq cycle-buffer-show-format '(" <(%s)>" . " %s"))
         ;; パッケージのキーアサインはこちら
         ;; (define-key xxx-map (kbd "q") 'hoge)
         ))
  ;; グローバルはこちら
  (global-set-key (kbd "M-]") 'cycle-buffer)
  (global-set-key (kbd "M-[") 'cycle-buffer-backward)
  ;; パッケージに紐付いたフックはこちらへ
  ;; (add-hook 'xxx-hook 'hogehoge)
  ;;
  ;; ビルドインではないmodeの auto-mode-alist 設定も必要ならこちに記述
  ;; (push '("\\.hoge$" . hoge-mode) auto-mode-alist)
  )

なお,第四引数 (functions file docstring interactive) まで指定すれば, M-x の呼び出し候補に functions で指定した関数が補完表示されます.

関数版

関数版にリスト loading-packages を追加しました.このリストに事前に Lisp ファイル名を入れておくと,一切の設定をスキップするものです. eval-after-atoload-if-found を定義する前に次のような変数を設定しておきます.バイトコンパイルしていないファイルに書いておけば,パッケージのON/OFFを簡単に制御できます.

ただ問題点として,最後の引数に入れる関数がバイトコンパイル時に展開されないようで,出来上がったバイトコードが高速化に寄与しているのか不明です.簡易的な実験ではだいぶ差があるようで,最近は autoload-if-foundwith-eval-after-loadeval-when-compile の組み合わせで,設定を書いて,遅延ロードと高速読み込みを実現しています. loading-packagesautoload-if-found に組み込みました.

(setq loading-packages ;; 追加されていない場合は標準で読み込む
      '(("web-mode" . nil) ;; 読み込まない
        ("org" . t))) ;; 読み込む

https://gist.github.com/3513287

;; https://github.com/zk-phi/setup
;; (when (require 'setup nil t)
;;   (setup-initialize))
(defun eval-after-autoload-if-found
    (functions file &optional docstring interactive type after-body)
  "Set up autoload and eval-after-load for FUNCTIONS iff. FILE has found."
  (let ((enabled t)
        (package nil))
    (message "--- %s" file)
    (when (and (boundp 'loading-packages) loading-packages)
      (dolist (package loading-packages)
        (let ((name (car package))
              (flag (cdr package)))
          (when (and (stringp name) (equal file name))
            (unless flag
              (setq enabled nil)
              (message "--- A setting for `%s' was NOT loaded explicitly"
                       name))))))
    ;; if disabled then return nil.
    (when (and enabled (locate-library file))
      (mapc (lambda (func)
              (autoload func file docstring interactive type))
            (if (listp functions)
                functions
              (list functions)))
      (when after-body
        (eval-after-load file `(progn ,@after-body)))
      t)))

マクロ版

以下はマクロ版です.引数の渡し方が関数と少し違うので要注意です.

https://gist.github.com/3499459

(defmacro eval-after-autoload-if-found
    (functions file &optional docstring interactive type &rest after-body)
  "Set up autoload and eval-after-load for FUNCTIONS iff. FILE has found."
  `(let* ((functions ,functions)
          (docstring ,docstring)
          (interactive ,interactive)
          (type ,type)
          (file ,file))
     (when (locate-library file)
       (mapc (lambda (func)
               (autoload func file docstring interactive type))
             (if (listp functions)
                 functions
               (list functions)))
       ,@(when after-body
           `((eval-after-load file '(progn ,@after-body))))
       t)))

[library-p] load-path にライブラリがあるかを判定

パッケージが load-path に存在していて使える状態にあるかを調べます.もし存在しなければ,メッセージバッファに [NOT FOUND] を刻みます.

libraries には複数を指定でき,すべてが使える状態の場合のみ t が返ります.

"org" を渡したり, '("org" "helm") を渡したりできます.

(defun library-p (libraries)
  "Return `t' when every specified library can be located. "
  (let ((result t))
    (mapc (lambda (library)
            (unless (locate-library library)
              (message "--- NOT FOUND: %s" library)
              (setq result nil)))
          (if (listp libraries)
              libraries
            (list libraries)))
    result))

[passed-clock-p] 指定時刻が本日の未来の時刻かを判定

今日の時刻に限定して,指定時刻が過去の時間かどうかを判定します. run-at-time が想定通りに動かず,起動時に対象の関数が走ってしまうので,この判定が nil の時だけタイマー登録します. target を HH:MM の書式で与えます.現在時刻を与えた場合は,過ぎ去っていないので nil を返します.

(defun passed-clock-p (target)
  (let
      ((hour nil)
       (min nil)
       (current-hour nil)
       (current-min nil))
    (when (string-match "\\([0-2]?[0-9]\\):\\([0-5][0-9]\\)" target)
      (setq hour (substring target (match-beginning 1) (match-end 1)))
      (setq min (substring target (match-beginning 2) (match-end 2)))
      (setq current-hour (format-time-string "%H" (current-time)))
      (setq current-min (format-time-string "%M" (current-time)))
      (< (+ (* (string-to-number hour) 60)
            (string-to-number min))
         (+ (* (string-to-number current-hour) 60)
            (string-to-number current-min))))))

[input-focus-p] フォーカス判定

フォーカスが当たっているのかを判定するための関数です.

(defvar window-focus-p t)
(defun window-focus-p ()
  (if window-focus-p t nil))
(add-hook 'focus-in-hook #'(lambda () (setq window-focus-p t)))
(add-hook 'focus-out-hook #'(lambda () (setq window-focus-p nil)))

警告の抑制

起動時に警告が出てうっとうしい場合に使います.起動直後に呼ばれるように, .emacs の上の方に書いておくとよいと思います.

(setq byte-compile-warnings
      '(free-vars unresolved callargs redefine obsolete noruntime
                  cl-functions interactive-only make-local))
(setq ad-redefinition-action 'accept)

エラー表示の抑制

普段使いでは要らないので抑制します.

(setq debug-on-error nil)

C-x C-c で容易にEmacsを終了させないように質問する

y-or-n-p を指定するだけです.

(setq confirm-kill-emacs 'y-or-n-p)

以前は, C-x C-c を以下の関数に割り当てて,任意の質問文で入力を求めていました.

;;; Cite: http://flex.ee.uec.ac.jp/texi/emacs-jp/emacs-jp_12.html
;;; Cite: http://d.hatena.ne.jp/Ubuntu/20090417/1239934416
;; A simple solution is (setq confirm-kill-emacs 'y-or-n-p).
(defun confirm-save-buffers-kill-emacs (&optional arg)
  "Show yes or no when you try to kill Emacs"
  (interactive "P")
  (cond (arg (save-buffers-kill-emacs))
        (t
         (when (yes-or-no-p "Are you sure to quit Emacs now? ")
           (save-buffers-kill-emacs)))))

キーバインド

Show yes or no when you try to kill Emacs

(global-set-key (kbd "C-x C-c") 'confirm-save-buffers-kill-emacs)

Messages 出力を封じるためのマクロ

shut-up.el というマクロがあり,現在はそちらを使っています.非常に強力です.

(defun hoge ()
  (interactive)
  (if (require 'shut-up nil t)
      (shut-up (recentf-save-list))
    (recentf-save-list)))

以下は以前のアプローチ. recentf-save-listfind-file-hook にぶら下げていますが,そのままだと org-agenda の初回実行時にたくさんのメッセージが出てしまうところ,このマクロを介すだけで抑制可能です. message-log-max で制御できるのがすごい.

(defmacro with-suppressed-message (&rest body)
  "Suppress new messages temporarily in the echo area and the `*Messages*' buffer while BODY is evaluated."
  (declare (indent 0))
  (let ((message-log-max nil))
    `(with-temp-message (or (current-message) "") ,@body)))

エンターキーの挙動

好みの問題ですかね.

(global-set-key (kbd "RET") 'electric-newline-and-maybe-indent)

コマンド入力中に入力過程をミニバッファに反映する

標準値は 1 です.例えば, C-c f r で発動する関数があるとき, C-c を入力するとその直後にはミニバッファに何も表示されませんが, echo-keystrokes だけ経過すると, C-c が表示されます. 0 に設定すると,いくら経過しても何も表示しません.

(setq echo-keystrokes 0.5)

コア設定

Emacs を操作して文書編集する上で欠かせない設定です.

言語/文字コード

徹底的にUTF-8に合わせます.

save-buffer-coding-system を設定すると, buffer-file-coding-system の値を無視して,指定した save-buffer-coding-system の値でバッファを保存する.つまり, buffer-file-coding-system に統一するなら設定不要.

set-default-coding-systemsprefer-coding-system を設定すると,同時に file-name-coding-systemset-terminal-coding-systemset-keyboard-coding-system も同時に設定される.prefer-coding-system は,文字コード自動判定の最上位判定項目を設定する.

set-buffer-file-coding-system は,Xとのデータやりとりを設定する.

(prefer-coding-system 'utf-8-unix)
;; (set-language-environment "Japanese") ;; will take 20-30[ms]
(set-locale-environment "en_US.UTF-8") ; "ja_JP.UTF-8"
(set-default-coding-systems 'utf-8-unix)
(set-selection-coding-system 'utf-8-unix)
(set-buffer-file-coding-system 'utf-8-unix)

日本語入力

NSビルド用のインラインパッチを適用している場合に使います.Lion でも使える自分用にカスタマイズした inline-patch を使っています.

(when (fboundp 'mac-add-key-passed-to-system)
  (setq default-input-method "MacOSX")
  (mac-add-key-passed-to-system 'shift))

[ag.el] 検索

検索には The Silver Searcher を使います.あらかじめインストールしておく必要があります.MacPorts の場合,the_silver_searcher の名称で頒布されています. exec-path/opt/local/bin が含まれていることを確認してください.

the_silver_searcher @0.18.1 (textproc)
 A code-searching tool similar to ack, but faster.

カスタマイズした関数を C-M-f にぶら下げています.helm インタフェースを使う helm-ag もあります.

  (when (and (executable-find "ag")
             (autoload-if-found
              '(my:ag ag)
              "ag" nil t))
    (eval-when-compile
      (require 'ag nil t))
    (with-eval-after-load "ag"
      (setq ag-highlight-search t)
      (setq ag-reuse-buffers t) ;; nil: 別ウィンドウが開く
      (setq ag-reuse-window nil) ;; nil: 結果を選択時に別ウィンドウに結果を出す
      ;; q でウィンドウを抜ける
      ;; (define-key ag-mode-map (kbd "q") 'delete-window)
 
      ;; 自動的に出力バッファに移動
      (defun my:ag ()
        (interactive)
        (call-interactively 'ag)
        (switch-to-buffer-other-frame "*ag search*")))
 
    (global-set-key (kbd "C-M-f") 'my:ag)
    (autoload-if-found '(helm-ag) "helm-ag" nil t))

基本キーバインド

次の機能にキーバインドを設定する.

- Cmd+V でペースト(Mac用) - Cmd と Option を逆にする(Mac用) - 削除

  (when (memq window-system '(mac ns))
    (global-set-key (kbd "M-v") 'yank)
    (when (boundp 'ns-command-modifier)
      (setq ns-command-modifier 'meta))
    (when (boundp 'ns-alternate-modifier)
      (setq ns-alternate-modifier 'super))
    (when (boundp 'ns-pop-up-frames)
      (setq ns-pop-up-frames nil))
    (global-set-key [ns-drag-file] 'ns-find-file)) ; D&D for Emacs23
 
  (global-set-key [delete] 'delete-char)
  (global-set-key [kp-delete] 'delete-char)

ナローイングするか

ナローイングを有効にします.ナローイングを知らないユーザが「データが消えた!」と勘違いしないように,デフォルトでは無効になっています.

Org Mode でナローイングを使う場合は,特に設定しなくてもOKです.

(put 'narrow-to-region 'disabled nil)

fancy-narrow を使うと,通常バッファ上で表示しなくなる領域を目立たないように残すことができます.

(autoload-if-found
 '(fancy-narrow-to-region
   fancy-widen
   org-fancy-narrow-to-block
   org-fancy-narrow-to-element
   org-fancy-narrow-to-subtree)
 "fancy-narrow" nil t)

バッファの終わりでのnewlineを禁止する

;; Avoid adding a new line at the end of buffer
(setq next-line-add-newlines nil)

常に最終行に一行追加する

;; Limit the final word to a line break code (automatically correct)
(setq require-final-newline t)

長い文章を右端で常に折り返す

(setq truncate-lines nil)
(setq truncate-partial-width-windows nil)

バッファが外部から編集された場合に自動で再読み込みする

auto-save-buffers を使っていれば,バッファは常に保存された状態になるため, revert が即座に反映されます.適宜バックアップツールと組み合わせないと,バッファが自動更新されてしまうので不安かもしれません.

helm-config の後に呼んでいるのは,Emacs起動時の単純な高速化対策です.

(with-eval-after-load "helm-config"
  (global-auto-revert-mode 1))

[uniquify.el] 同じバッファ名が開かれた場合に区別する

ビルトインの uniquify を使います.

(setq uniquify-buffer-name-style 'post-forward-angle-brackets)

マウスで選択した領域を自動コピー

マウスで選択すると,勝手にペーストボードにデータが流れます.

(setq mouse-drag-copy-region t)

パッケージ管理

Cask+Palletの環境を採用しました.それまでは,特定のディレクトリに必要な elisp をダウンロードしておいたり,git から取り寄せて,それらをload-pathに設定するスクリプトを準備するなど,個人的なルールで運用してきましたが,希望の機能をCaskが提供しているので,Emacs24.4になるタイミングで移行しました.

ただし,頒布元が危ういようなファイルはやはり個人で管理しておきたいので,Caskで管理する対象は,MEPLA経由で入手可能なメンテナンスが行き届いたパッケージに限定しています.また,普通の使い方(casl.elを読み込んで初期化)をしていると,起動時に少し時間を要するので,所定のディレクトリにCaskで取り寄せたすべてのファイルをコピーして,そのディレクトリだけをload-pathで指定するという使い方もしています.今のところ大きな問題は生じていません.

[cask-mode.el] モード設定

(when (autoload-if-found '(cask-mode) "cask-mode" nil t)
  (push '("/Cask\\'" . cask-mode) auto-mode-alist))

Cask のセットアップ

以下は自分用のメモです.

  1. ~/.cask/bin に PATH を通す (see .zshenv, export PATH=“${HOME}/.cask/bin:{$PATH}”)
  2. cask upgrade
  3. cd ~/.emacs.d
  4. cask init ;; ~/.emacs.d/Cask が存在しない場合だけ実行
  5. cask install

load-path を一箇所にして起動を高速化

Caskを使うと,個々のパッケージが独立にload-pathに設定されます.これにより依存関係がスッキリするわけですが,数が増えると起動時間が遅くなります.重いです.自分の例では,800[ms]のオーバーヘッドでした.これを避けるには,load-pathを一箇所に集約することが効きます.オーバーヘッドは約100[ms]まで削減できました.場合によっては依存関係に問題が生じる可能性がありますが,今のところは問題になっていません.

  1. =~/.emacs.d/.cask/package/<emacs-version>= なるフォルダを作る
  2. =~/.emacs.d/.cask/24.4.1/elpa/*/*= と =~/.emacs.d/.cask/24.4.1/elpa/*/lisp/*= をすべて上記フォルダにコピー
  3. =~/.emacs= で, =~/.emacs.d/.cask/package/<emacs-version>= を load-path に設定し,Caskは読み込まない

M-x lis-packges を使って新しいパッケージをインストールする時だけ,以下のフラグを nil に書き換えてEmacsを起動します. load-path-setter は独自関数です(普通に add-to-list で追加するのと同じです)

(defconst cask-package-dir
  (format "~/.emacs.d/.cask/package/%s" emacs-version))
(if t
    (load-path-setter `(,cask-package-dir) 'load-path)
  (when (or (require 'cask "~/.cask/cask.el" t)
            (require 'cask "/usr/local/opt/cask/cask.el" t)) ;; Homebrew
    (when (fboundp 'cask-initialize) (cask-initialize))) ;; 800[ms]
  (when (require 'pallet nil t)
    (when (fboundp 'pallet-mode) (pallet-mode t))))

Cask で新しいパッケージを導入したり,既存のパッケージを更新したら,その都度,package ディレクトリにコピーします.手動でやると面倒なので,次のようなスクリプトで対処します.アルファリリースなどに対応するときなど,少し調整が必要です.

  #!/bin/sh
 
  # Required setting: alias emacs='/Applications/Emacs.app/Contents/MacOS/Emacs'
  # exec cd ~/.emacs.d && cask upgrade-cask if you upgrade cask itself.
 
  CASKPATH=~/.emacs.d/.cask
  #VERSION=24.5.1
  #VERSION=25.0.95.1
  VERSION=25.2
  #VERSION=25.1.90.1
  SUBDIR=package/$VERSION
  BACKUPDIR=~/Dropbox/backup
  EMACS=`which emacs`
  if [ $HOSTTYPE = "intel-mac" ]; then
  EMACS=/Applications/Emacs.app/Contents/MacOS/Emacs
  fi
  # COMMAND="$EMACS -batch -q -l ~/.emacs -f batch-byte-compile";
  if [ -d "$CASKPATH/$SUBDIR" ]; then
      echo "--- Removing $CASKPATH/$SUBDIR"
      rm -r "$CASKPATH/$SUBDIR"
  else
      echo "--- Target dir does NOT exist ($CASKPATH/$SUBDIR)."
      exit
  fi
  mkdir -p $CASKPATH/$SUBDIR
 
  cd ~/.emacs.d
  echo "--- Cask install"
  EMACS="/Applications/Emacs.app/Contents/MacOS/Emacs" cask install
 
  echo "--- Cask update"
  EMACS="/Applications/Emacs.app/Contents/MacOS/Emacs" cask update
 
  # echo "--- Removing org-mode installed by Cask unexpectedly"
  /bin/rm -rf ~/.emacs.d/.cask/$VERSION/elpa/org-20*
 
  echo "--- Copying elisp files"
  /bin/cp -rf ~/.emacs.d/.cask/$VERSION/elpa/*/* $CASKPATH/$SUBDIR
  /bin/cp -rf ~/.emacs.d/.cask/$VERSION/elpa/*/lisp/* $CASKPATH/$SUBDIR
  cd $CASKPATH/$SUBDIR
  rm -rf ./*~
 
  echo "--- Done"

[paradox.el] パッケージ選択画面の改善

パッケージインストール用のバッファが多機能になります.スターが表示されたり,ミニバッファには様々な情報が表示されるようになります.基本の操作系は同じで,拡張部分は h を押すとミニバッファにディスパッチャが表示されます.

(when (autoload-if-found
       '(paradox-list-packages my:list-packages my:setup-cask)
       "paradox" nil t)
  (with-eval-after-load "paradox"
    (when (fboundp 'paradox-enable)
      (paradox-enable))))

インデント

オープンソース等で他の人のコードを修正する場合は,以下のような設定は良くないかもしれません.例えば差分を取ると見た目は変わらないのに,タブとスペースの違いから差分ありと判定されてしまい,意図しない編集履歴が残ることがあります.ただこの問題は,修正対象のファイルが限定されているならば, M-x tabifyM-x untabify で回避できそうです.

一方, org-mode のソースブロックは半角スペース統一されているため,この設定のほうが都合が良いです.

  (setq-default tab-width 2)
  (setq-default indent-tabs-mode nil)
  (setq indent-line-function 'insert-tab)
 
  ;; (add-hook 'emacs-lisp-mode-hook
  ;;           '(lambda ()
  ;;              (setq indent-tabs-mode t)
  ;;              (setq tab-width 8)
  ;;              (setq indent-line-function 'lisp-indent-line)))

[aggressive-indent] 即時バッファ整形

特定のメジャーモードで,とにかく整形しまくります. python-mode では意図しないインデントになったりします. web-mode だと異常に重かったりします.

  (when (autoload-if-found
         '(aggressive-indent-mode)
         "aggressive-indent" nil t)
 
    (dolist
        (hook
         '(;; python-mode-hook
           ;; nxml-mode-hook
           ;; web-mode-hook
           emacs-lisp-mode-hook
           lisp-mode-hook perl-mode-hook c-mode-common-hook))
      (add-hook hook 'aggressive-indent-mode)))

ファイルリンクを辿る時に確認のメッセージを出さない

そのまま辿ってファイルオープンします.

(setq vc-follow-symlinks t)

MBPビルド用設定

NSビルド版で生じた日本語入力時のチラつきを避けるために,MBP版ビルドに(一時期)浮気しました.以下はその時にNSビルドの振る舞いに近づけるためにがんばった設定です.詳細な情報は,リンク先の記事にあります.

  (when (eq window-system 'mac)
    (mac-auto-ascii-mode 1)
 
    (defvar mac-win-last-ime-status 'off) ;; {'off|'on}
    (defun mac-win-save-last-ime-status ()
      (setq mac-win-last-ime-status
            (if (string-match "\\.\\(Roman\\|US\\)$" (mac-input-source))
                'off 'on)))
    (mac-win-save-last-ime-status) ;; 初期化
 
    (defun mac-win-restore-ime ()
      (when (and mac-auto-ascii-mode
                 (eq mac-win-last-ime-status 'on))
        (mac-select-input-source
         "com.google.inputmethod.Japanese.base")))
 
    (defun advice:mac-auto-ascii-setup-input-source (&optional _prompt)
      "Extension to store IME status"
      (mac-win-save-last-ime-status))
    (advice-add 'mac-auto-ascii-setup-input-source :before
                #'advice:mac-auto-ascii-setup-input-source)
 
    (defun mac-win-restore-ime-target-commands ()
      (when (and mac-auto-ascii-mode
                 (eq mac-win-last-ime-status 'on))
        (mapc (lambda (command)
                (when (string-match
                       (format "^%s" command) (format "%s" this-command))
                  (mac-select-input-source
                   "com.google.inputmethod.Japanese.base")))
              mac-win-target-commands)))
 
    (add-hook 'pre-command-hook 'mac-win-restore-ime-target-commands)
 
    (defvar mac-win-target-commands
      '(find-file save-buffer other-window delete-window split-window))
 
    ;; バッファリストを見るとき
    (add-to-list 'mac-win-target-commands 'helm-buffers-list)
    ;; ChangeLogに行くとき
    (add-to-list 'mac-win-target-commands 'add-change-log-entry-other-window)
    ;; 個人用の関数を使うとき
    ;; (add-to-list 'mac-win-target-commands 'my:)
    ;; 自分で作ったパッケージ群の関数を使うとき
    (add-to-list 'mac-win-target-commands 'change-frame)
    ;; org-mode で締め切りを設定するとき.
    (add-to-list 'mac-win-target-commands 'org-deadline)
    ;; org-mode で締め切りを設定するとき.
    ;; (add-to-list 'mac-win-target-commands 'org-capture)
    ;; query-replace で変換するとき
    (add-to-list 'mac-win-target-commands 'query-replace)
 
    ;; ミニバッファ利用後にIMEを戻す
    ;; M-x でのコマンド選択でIMEを戻せる.
    ;; これ移動先で q が効かないことがある
    (add-hook 'minibuffer-setup-hook 'mac-win-save-last-ime-status)
    (add-hook 'minibuffer-exit-hook 'mac-win-restore-ime)
 
    ;; タイトルバーの振る舞いを NS版に合わせる.
    (setq frame-title-format (format (if (buffer-file-name) "%%f" "%%b")))
 
    ;; なおテーマを切り替えたら,face の設定をリロードしないと期待通りにならない
    (custom-set-faces
     ;; 変換前入力時の文字列用 face
     `(mac-ts-converted-text
       ((((background dark)) :underline "orange"
         :background ,(face-attribute 'hl-line :background))
        (t (:underline "orange"
                       :background ,(face-attribute 'hl-line :background)))))
     ;; 変換対象の文字列用 face
     `(mac-ts-selected-converted-text
       ((((background dark)) :underline "orange"
         :background ,(face-attribute 'hl-line :background))
        (t (:underline "orange"
                       :background ,(face-attribute 'hl-line :background))))))
 
    (when (fboundp 'mac-input-source)
      (run-with-idle-timer 3 t 'my:mac-keyboard-input-source))
 
 
    ;; あまりよいアプローチでは無い気がするけど,org-heading 上とagendaでは
    ;; 1秒アイドルすると,自動的に IME を OFF にする
    (defun my:mac-win-org-heading-auto-ascii ()
      (when (and (eq major-mode 'org-mode)
                 (or (looking-at org-heading-regexp)
                     (equal (buffer-name) org-agenda-buffer-name)))
        (setq mac-win-last-ime-status 'off)
        (mac-auto-ascii-select-input-source)))
    (when (fboundp 'mac-auto-ascii-select-input-source)
      (run-with-idle-timer 1 t 'my:mac-win-org-heading-auto-ascii))
 
    ;; EMP版Emacsの野良ビルド用独自設定群
    ;; IME toggleを Emacs内で有効にする
    (defun mac-win-ime-toggle ()
      (interactive)
      (when (fboundp 'mac-input-source)
        (mac-select-input-source
         (concat "com.google.inputmethod.Japanese"
                 (if (string-match "\\.base$" (mac-input-source))
                     ".Roman" ".base")))))
    (global-set-key (kbd "S-SPC") 'mac-win-ime-toggle)
 
    ;; isearch 中にIMEを切り替えると,[I-Search] の表示が消える.
    (define-key isearch-mode-map (kbd "S-SPC") 'mac-win-ime-toggle)
 
    (setq mac-win-ime-cursor-type my:cursor-type-ime-on)
    ;; minibuffer では↑の背景色を無効にする
    (when (fboundp 'mac-min--minibuffer-setup)
      (add-hook 'minibuffer-setup-hook 'mac-min--minibuffer-setup))
    ;; echo-area でも背景色を無効にする
    (setq mac-win-default-background-echo-area t) ;; *-text の background を無視
    ;; デバッグ用
    (setq mac-win-debug-log nil)
    ;; Testing...
    (setq mac-win-apply-org-heading-face t))

NSビルド用設定 :Mac:

インラインパッチの適用が前提の設定です. S-SPC で日本語IMEのON/OFFができるようになります.インラインパッチの情報はリンク先にあります.

  (when (eq window-system 'ns)
    (when (boundp 'mac-ime-cursor-type) ;; private patch
      (setq mac-ime-cursor-type '(bar . 2)))
 
    (defun ns-org-heading-auto-ascii ()
      (when (and window-focus-p
                 (eq major-mode 'org-mode)
                 (or (looking-at org-heading-regexp)
                     (equal (buffer-name) org-agenda-buffer-name)))
        (mac-toggle-input-method nil)))
 
    (defun ns-ime-toggle ()
      (interactive)
      (when (fboundp 'mac-get-current-input-source)
        (if (my:ime-active-p) (my:ime-off) (my:ime-on))))
    ;; (mac-toggle-input-method
    ;;  (if (string-match "\\.base$" (mac-get-current-input-source))
    ;;      nil t))))
 
    (global-set-key (kbd "S-SPC") 'ns-ime-toggle) ;; toggle-input-method
    (define-key isearch-mode-map (kbd "S-SPC") 'ns-ime-toggle)
 
    (when (fboundp 'mac-toggle-input-method)
      (run-with-idle-timer 1 t 'ns-org-heading-auto-ascii)))

カーソル移動

カーソルの移動は,次のポリシーに従っています.デフォルトでは C-v/M-v で上下移動になっていますが, M-v は windows のペーストに対応するので混乱を招くので使っていません.ページスクロールは標準の cua-base.el に記載されています.

行移動 C-n/C-p
ページ移動(スクロール) M-n/M-p
ウィンドウ移動 C-M-n/C-M-p
バッファ切り替え M-]/M-[
バッファ先頭・末尾 C-M-t/C-M-b

バッファ内のカーソル移動

先頭に移動,最終行に移動,ページ単位の進む,ページ単位の戻る,行数を指定して移動.

(global-set-key (kbd "C-M-t") 'beginning-of-buffer)
(global-set-key (kbd "C-M-b") 'end-of-buffer)
;; Backward page scrolling instead of M-v
(global-set-key (kbd "M-p") 'scroll-down)
;; Frontward page scrolling instead of C-v
(global-set-key (kbd "M-n") 'scroll-up)
;; Move cursor to a specific line
(global-set-key (kbd "C-c g") 'goto-line)

バッファ間のカーソル移動

C-c o でもいいですが,ワンアクションで移動できるようが楽です.次のように双方向で使えるように設定しています.

(global-set-key (kbd "C-M-p") #'(lambda () (interactive) (other-window -1)))
(global-set-key (kbd "C-M-n") #'(lambda () (interactive) (other-window 1)))

スクロールを制御

一行づつスクロールさせます.デフォルトではバッファの端でスクロールすると,半画面移動します.また,上下の端にカーソルがどのくらい近づいたらスクロールとみなすかも指定できます.

非ASCII文字を扱っているときに一行づつスクロールしない場合は,scroll-conservatively の値を1ではなく大きい数字にすると直るかもしれません.

scroll-margin を指定すると,カーソルがウィンドウの端から離れた状態でスクロールされます.

;; Scroll window on a line-by-line basis
(setq scroll-conservatively 1000)
(setq scroll-step 1)
;;  (setq scroll-margin 0) ; default=0

スクロール時のジャンプが気になる場合は次のパッケージを使うとよいです.

(when (require 'smooth-scrolling nil t)
  (setq smooth-scroll-margin 1))

スクロールで表示を重複させる行数

;; Scroll window on a page-by-pabe basis with N line overlapping
(setq next-screen-context-lines 1)

[SmoothScroll.el] カーソル固定でスクロールする

https://raw.github.com/takaxp/EmacsScripts/master/SmoothScroll.el https://github.com/pglotov/EmacsScripts/blob/master/SmoothScroll.el

カーソル位置と行を固定してバッファを背景スクロールできます.

オリジナルのままだとコンパイル時に警告がでるので, line-move-visual で書き換えています.残念ながら最近は使っていません.

(eval-after-autoload-if-found
 '(scroll-one-up scroll-one-down) "smoothscroll" nil t)

キーバインド

(global-set-key (kbd "s-<up>") 'scroll-one-down)
(global-set-key (kbd "s-<down>") 'scroll-one-up)

[smooth-scroll.el] 滑らかなスクロール

良い感じです.スススっとスクロールします.

(eval-after-autoload-if-found
 '(smooth-scroll) "smooth-scroll" nil t nil
    '((smooth-scroll-mode t)
      (setq smooth-scroll/vscroll-step-size 6)
      (setq smooth-scroll/hscroll-step-size 6)))

[point-undo.el] カーソル位置を簡単にたどる

autoload や autoload-if-found で定義すると,使いたい時に履歴が取れていないのでよろしくないです.起動時に有効化します. bm.el で明示的にマーカーを残して履歴をたどる方が気に入っているので,最近は point-undo を使っていません.シングルキーを割り当てておくと使いやすいです.

(when (require 'point-undo nil t)
  ;; [point-undo.el] Move the cursor to the previous position
  (global-set-key (kbd "<f7>") 'point-undo)
  ;; [point-undo.el] Redo of point-undo
  (global-set-key (kbd "S-<f7>") 'point-redo))

[cycle-buffer.el] カレントバッファの表示切り替え

http://www.emacswiki.org/emacs/download/cycle-buffer.el

cycle-buffer を使うと,バッファの履歴をスライドショーのようにたどれます.ミニバッファに前後の履歴が表示されるので,何回キーを押せばいいかの目安になります.それを超える場合には,おとなしくバッファリストを使います.直近数件のバッファをたどるのに便利です.

  (when (autoload-if-found
         '(cycle-buffer cycle-buffer-backward)
         "cycle-buffer" nil t)
    (eval-when-compile
      (require 'cycle-buffer nil t))
    (with-eval-after-load "cycle-buffer"
      (setq cycle-buffer-allow-visible t)
      (setq cycle-buffer-show-length 12)
      (setq cycle-buffer-show-format '(" <(%s)>" . " %s")))
 
    (global-set-key (kbd "M-]") 'cycle-buffer)
    (global-set-key (kbd "M-[") 'cycle-buffer-backward))

[bm.el] カーソル位置をブックマークして追う

bm.elは,カーソル位置をブックマークしておくためのツールです. point-undo と比較して,ユーザが明示的に位置を保存でき,見た目にも使いやすいです.以下の例では, org-mode のツリー内にブックマークがある時にも,上手い具合に表示ができるように調整してあります.カーソル移動は,順方向( bm-next )にだけ使っています.

org-mode との連携には, org-bookmark-heading があります.ただ,私は下記の設定だけでそれほど不自由していません.

  (when (autoload-if-found
         '(my:bm-toggle
           my:bm-next bm-buffer-save bm-buffer-restore bm-buffer-save-all
           bm-repository-save bm-repository-load bm-load-and-restore)
         "bm" nil t)
    (eval-when-compile
      (require 'bm nil t))
    (with-eval-after-load "bm"
      (setq-default bm-buffer-persistence t)
      (setq bm-cycle-all-buffers t)
      ;; (setq bm-toggle-buffer-persistence t)
      (setq bm-repository-file "~/Dropbox/emacs.d/.bookmark")
      ;; autoload との組み合わせでは無意味
      ;;(after-init-hook を利用せよ)
      ;; (setq bm-restore-repository-on-load t)
      (setq bm-buffer-persistence t)
      (setq bm-persistent-face 'bm-face)
      (setq bm-repository-file
            (expand-file-name "~/Dropbox/emacs.d/.bm-repository"))
      (bm-repository-load)
 
      (defun my:bm-toggle ()
        "bm-toggle with updating history"
        (interactive)
        (let ((bm (concat
                   (buffer-name) "::"
                   (if (and (equal major-mode 'org-mode)
                            (not (org-before-first-heading-p)))
                       (nth 4 (org-heading-components))
                     (format "%s" (line-number-at-pos))))))
          (if (bm-bookmark-at (point))
              (bookmark-delete bm)
            (bookmark-set bm)))
        (bm-toggle)
        (bm-save))
 
      (defun my:bm-next ()
        "bm-next with org-mode"
        (interactive)
        (bm-next)
        (when (and (equal major-mode 'org-mode)
                   (not (org-before-first-heading-p)))
          (widen)
          (org-overview)
          (org-reveal)
          (org-cycle-hide-drawers 'all)
          (org-show-entry)
          (show-children)
          (org-show-siblings))))
 
    ;; ファイルオープン時にブックマークを復帰
    (add-hook 'find-file-hook 'bm-buffer-restore)
    (global-set-key (kbd "<f9>") 'my:bm-toggle)
    (global-set-key (kbd "<C-f9>") 'my:bm-next))

[centered-cursor-mode.el] カーソル位置をバッファ中央に固定

isearch-mode の時だけ有効にしています.

  (when (autoload-if-found
         '(centered-cursor-mode)
         "centered-cursor-mode" nil t)
 
    (add-hook 'isearch-mode-hook
              #'(lambda () (centered-cursor-mode 1)))
    (add-hook 'isearch-mode-end-hook
              #'(lambda () (centered-cursor-mode -1))))

[back-button] マークをたどる

現在のバッファと開いている全てのバッファのマークを辿ることができます.いま注目している位置が,マーク全体でどのあたりに位置するのかをミニバッファに表示してくれます.ツールバーを表示している場合は,マークを付けたり辿る用のボタンが追加されます. global-mark-ring-max を設定して,辿れるマークの数を拡張しておきます.

helm-config の後に呼んでいるのは,Emacs起動時の単純な高速化対策です.

  (when (autoload-if-found
         '(back-button-mode
           back-button-local-forward back-button-global-forward)
         "back-button" nil t)
    (with-eval-after-load "back-button"
      (setq global-mark-ring-max 64)
      (setq back-button-local-forward-keystrokes '("<f10>"))
      (setq back-button-global-forward-keystrokes '("C-<f10>"))
      (define-key back-button-mode-map
        (kbd (car back-button-local-forward-keystrokes))
        'back-button-local-forward)
      (define-key back-button-mode-map
        (kbd (car back-button-global-forward-keystrokes))
        'back-button-global-forward)
      (setq back-button-mode-lighter nil)
      (setq back-button-index-timeout 0)))
 
  (with-eval-after-load "helm-config"
    (back-button-mode 1))

[smart-mark] C-g後に元の場所へカーソルを戻す

すぐわかる例は, C-x h で全選択して何もせず, C-g する場合です.通常だとバッファの先頭にカーソルが置き去りにされますが, smart-mark を使うと,全選択を実行した時の位置に自動的に戻してくれます.

helm-config の後に呼んでいるのは,Emacs起動時の単純な高速化対策です.

(with-eval-after-load "helm-config"
  (when (require 'smart-mark nil t)
    (smart-mark-mode 1)))

編集サポート

矩形編集/連番入力

Built-in の cua-base.el(CUA-mode)を使う.矩形選択は,領域選択後 cua-toggle-rectangle-mark でもできるが, 24.4 からは, C-x SPC を押下すると矩形モードに入り直感的に矩形選択ができるようになっています.

(require 'cua-base)
(cua-mode 1)
(setq cua-enable-cua-keys nil)

矩形選択した後に, M-n を押すと,連番をふれる.開始値,増加値を入力してから,hoge%03d.pgm などとすれば,hoge001,hoge002,,,と入力される.これと,org-mode の表機能( C-c ^ で選択部分を簡単に表にできる)を組み合わせれば,連番で数値をふったテーブルを容易に作れる.

なお,標準の rect.el に以下の機能が実装されている.

矩形切り取り C-x r k
矩形削除 C-x r d
矩形貼り付け C-x r y
矩形先頭に文字を挿入 C-x r t
矩形を空白に変換する C-x r c

Yank時に装飾を取る

(setq yank-excluded-properties t)

ファイル保存時に時間を記録する

Built-in の time-stamp.el を使う.

バッファの保存時にタイムスタンプを記録する.以下の設定では,バッファの先頭から10行以内に,“Last Update: ” があると,“Last Update: 2011-12-31@12:00”のようにタイムスタンプが記録される.

(add-hook 'before-save-hook 'time-stamp)
(with-eval-after-load "time-stamp"
  (setq time-stamp-start "Last Update: ")
  (setq time-stamp-format "%04y-%02m-%02d@%02H:%02M")
  (setq time-stamp-end "$")
  (setq time-stamp-line-limit 10)) ; def=8

選択リージョンを使って検索

検索語をミニバッファに入力するのが面倒なので,リージョンをそのまま検索語として利用します.

(defadvice isearch-mode
    (around isearch-mode-default-string
            (forward &optional regexp op-fun recursive-edit word-p) activate)
  (if (and transient-mark-mode mark-active (not (eq (mark) (point))))
      (progn
        (isearch-update-ring (buffer-substring-no-properties (mark) (point)))
        (deactivate-mark)
        ad-do-it
        (if (not forward)
            (isearch-repeat-backward)
          (goto-char (mark))
          (isearch-repeat-forward)))
    ad-do-it))

ChangeLog モード

(setq user-full-name "Your NAME")
(setq user-mail-address "your@address.com")
(add-hook 'change-log-mode-hook
          #'(lambda()
             (orgstruct-mode)
             (setq tab-width 4)
             (setq left-margin 4)))

テキストモード

http://d.hatena.ne.jp/NeoCat/20080211

とは言っても,Org-modeを知ってから .txt もテキストモードで開かなくなったので,ほぼ無意味な設定となりました.しかも, nxml-modeTAB が効かなくなる現象が起きているので,以下の設定はしない方がよさげ.

(add-hook 'text-mode-hook
          #'(lambda()
              (setq tab-width 4)
              (setq indent-line-function 'tab-to-tab-stop)
              (setq tab-stop-list
                    '(4 8 12 16 20 24 28 32 36 40 44 48 52 56 60
                        64 68 72 76 80))))

C/C++モード

(when (autoload-if-found
       '(modern-c++-font-lock-mode)
       "modern-cpp-font-lock" nil t)
  (push '("\\.h$" . c++-mode) auto-mode-alist)
  (add-hook 'c++-mode-hook #'modern-c++-font-lock-mode))

C#モード

(when (autoload-if-found
       '(csharp-mode)
       "csharp-mode" "Major mode for editing C# mode." nil t)
  (push '("\\.cs$" . csharp-mode) auto-mode-alist))

Infoモード

Org-mode の日本語翻訳済みinfoを読むための設定.翻訳プロジェクトで頒布しています.

  (when (autoload-if-found
         '(info org-info-ja)
         "info" nil t)
    (with-eval-after-load "info"
      (add-to-list 'Info-additional-directory-list
                   (expand-file-name "~/devel/mygit/org-ja/work/"))
 
      (defun org-info-ja (&optional node)
        "(Japanese) Read documentation for Org-mode in the info system.
      With optional NODE, go directly to that node."
        (interactive)
        (info (format "(org-ja)%s" (or node ""))))))

Rモード

(when (autoload-if-found
       '(R-mode R)
       "ess-site" "Emacs Speaks Statistics mode" nil t)
  (push '("\\.[rR]$" . R-mode) auto-mode-alist))

nXMLモード

(eval-when-compile
  (require 'nxml-mode nil t))
(add-hook 'nxml-mode-hook
          #'(lambda ()
              (define-key nxml-mode-map "\r" 'newline-and-indent)
              (auto-fill-mode -1)
              (setq indent-tabs-mode t)
              (setq nxml-slash-auto-complete-flag t)
              (setq tab-width 1)
              (setq nxml-child-indent 1)
              (setq nxml-attribute-indent 0)))

yamlモード

(when (autoload-if-found
       '(yaml-mode)
       "yaml-mode" nil t)
  (push '("\\.yml$" . yaml-mode) auto-mode-alist))

jsonモード

(when (autoload-if-found
       '(json-mode)
       "json-mode" nil t)
  (push '("\\.json$" . json-mode) auto-mode-alist))

javascriptモード

  (when (autoload-if-found
         '(js2-mode)
         "js2-mode" nil t)
    (with-eval-after-load "js2-mode"
      (require 'js2-refactor nil t)
      (push '("\\.js$" . js2-mode) auto-mode-alist)
 
      (when (autoload-if-found
             '(ac-js2-mode ac-js2-setup-auto-complete-mode)
             "ac-js2" nil t)
        (add-hook 'js2-mode-hook #'ac-js2-mode))
 
      (eval-when-compile
        (require 'tern nil t)
        (require 'tern-auto-complete nil t))
 
      (if (executable-find "tern")
          (when (autoload-if-found
                 '(tern-mode)
                 "tern" nil t)
            (with-eval-after-load "tern"
              (tern-mode 1)
              ;; tern-command shall be overwritten by actual path
              (setq tern-command `("node" ,(executable-find "tern")))
              (when (require 'tern-auto-complete nil t)
                (tern-ac-setup)))
            (add-hook 'js2-mode-hook #'tern-mode))
        (message "--- tern is NOT installed in this system."))))

csvモード

(when (autoload-if-found
       '(csv-mode)
       "csv-mode" nil t)
  (push '("\\.csv$" . csv-mode) auto-mode-alist))

asciiモード

カーソル下の文字のアスキーコードを別ウィンドウでリアルタイムに確認できます.

(autoload-if-found '(ascii-on ascii-off) "ascii" nil t)

esモード

ElasticSearch のクエリを編集します.org-mode との連携もできます.

(when (autoload-if-found
       '(es-mode)
       "es-mode" nil t)
  (push '("\\.es$" . es-mode) auto-mode-alist))

gnuplotモード

(when (autoload-if-found
       '(gnuplot-mode)
       "gnuplot-mode" nil t)
  (push '("\\.plt$" . gnuplot-mode) auto-mode-alist))

markdown-mode

(when (autoload-if-found
       '(markdown-mode)
       "markdown-mode" nil t)
  (push '("\\.markdown$" . markdown-mode) auto-mode-alist)
  (push '("\\.md$" . markdown-mode) auto-mode-alist))

スペルチェック

Built-in の ispell を使う.チェックエンジンは,aspell を利用する.

'ns sudo port install aspell aspell-dict-en
'x32 installer.exe and aspell-en from http://aspell.net/win32/

コマンドラインから aspell を使う時は,

aspell -l en -c <file>

とすると, ~/.aspell.en.pws を個人辞書と暗黙的に設定して,スペルチェックをしてくれる. hunspell が使える環境ならば,優先して使います.さらに, ~/.aspell.conf に,次を書いておきます.

lang en_US
  (when (autoload-if-found
         '(ispell-region ispell-complete-word)
         "ispell" nil t)
    (with-eval-after-load "ispell"
      (cond
       ((executable-find "aspell")
        ;; (message "--- aspell loaded.")
        (setq-default ispell-program-name "aspell")
        ;; for English and Japanese mixed
        (add-to-list 'ispell-skip-region-alist '("[^\000-\377]+"))
        (add-to-list 'ispell-skip-region-alist
                     '("^#\\+BEGIN_SRC" . "^#\\+END_SRC"))
        (add-to-list 'ispell-skip-region-alist '("~" "~"))
        (add-to-list 'ispell-skip-region-alist '("=" "="))
        (add-to-list 'ispell-skip-region-alist '(org-property-drawer-re))
        (when (eq window-system 'w32)
          (setq-default ispell-program-name
                        "C:/Program Files/Aspell/bin/aspell.exe"))
        (setq ispell-dictionary "english")
        (setq ispell-personal-dictionary "~/Dropbox/emacs.d/.aspell.en.pws")
        ;; This will also avoid an IM-OFF issue for flyspell-mode.
        (setq ispell-aspell-supports-utf8 t)
        (setq ispell-encoding8-command t)
        (setq ispell-local-dictionary-alist
              '((nil "[a-zA-Z]" "[^a-zA-Z]" "'" t
                     ("-d" "en" "--encoding=utf-8") nil utf-8))))
 
       ;; flyspell とペアで使う時に incorrect判定が日本語に反応したり,日本語変換時にASCIIに変わってしまうなど希望の動作にならないので,今のところ aspell を優先する.
       ((executable-find "hunspell")
        (setenv "LC_ALL" "en_US")
        ;; (message "--- hunspell loaded.")
        (setenv "DICPATH" "/Applications/LibreOffice.app/Contents/Resources/extensions/dict-en")
        (ispell-change-dictionary "en_US" t) ;; 必要.しかも ispell-program-name 指定の前で.
        (setq-default ispell-program-name (executable-find "hunspell"))
        (setq ispell-local-dictionary "en_US")
        (setq ispell-dictionary ispell-local-dictionary)
        ;; Not regal way, but it's OK (usually ispell-local-dictionary-alist)
        (setq ispell-local-dictionary-alist
              '(("en_US" "[[:alpha:]]" "[^[:alpha:]]" "[']" nil
                 ("-d" "en_US") nil utf-8)
                ("ja_JP" "[[:alpha:]]" "[^[:alpha:]]" "[']" nil
                 ("-d" "en_US") nil utf-8)))
        (setq ispell-hunspell-dictionary-alist ispell-local-dictionary-alist)
        (setq ispell-personal-dictionary "~/Dropbox/emacs.d/.hunspell.en.dic"))
       (t nil))
      )
 
    ;; Spell checking within a specified region
    (global-set-key (kbd "C-c f 7") 'ispell-region)
    ;; 補完候補の表示(flyspell が使える時はそちらを優先して <f7> にする.
    (global-set-key (kbd "<f7>") 'ispell-word))
  ;; (if (autoload-if-found '(helm-ispell) "helm-ispell" nil t)
  ;;     #'helm-ispell #'ispell-word)))
  ;;; Use aspell for spell checking instead of ispell.
  (when (and (executable-find "aspell")
             (autoload-if-found
              '(ispell-region ispell-complete-word)
              "ispell" nil t))
    (with-eval-after-load "ispell"
      (setq-default ispell-program-name "aspell")
      (when (eq window-system 'w32)
        (setq-default ispell-program-name
                      "C:/Program Files/Aspell/bin/aspell.exe"))
      ;; for English and Japanese mixed
      (add-to-list 'ispell-skip-region-alist '("[^\000-\377]+"))
      (add-to-list 'ispell-skip-region-alist
                   '("^#+BEGIN_SRC" . "^#+END_SRC"))
      ;; (setq ispell-dictionarry "english")
      ;; (setq ispell-personal-dictionary
      ;;       "~/Dropbox/emacs.d/.aspell.en.pws")
 
      ;; This will also avoid an IM-OFF issue for flyspell-mode.
      ;;  (setq ispell-aspell-supports-utf8 t)
      ;;  (setq ispell-encoding8-command t)
      ;; (setq ispell-local-dictionary-alist
      ;;       '((nil "[a-zA-Z]" "[^a-zA-Z]" "'" t
      ;;              ("-d" "en" "--encoding=utf-8") nil utf-8)))
      )
 
    ;; Spell checking within a specified region
    (global-set-key (kbd "C-c f 7") 'ispell-region)
    ;; 補完候補の表示
    (global-set-key (kbd "<f7>") 'ispell-word))

リアルタイムスペルチェック

Built-in の flyspell.el を使います.flyspell は内部で ispell を読み込んでいるので,辞書機能自体はそちらの設定が使われます.

http://www.morishima.net/~naoto/fragments/archives/2005/12/20/flyspell/

  (when (autoload-if-found
         '(flyspell-prog-mode flyspell-mode)
         "flyspell" nil t)
    (with-eval-after-load "flyspell"
      ;; C-; をオーバーライド
      (eval-when-compile
        (require 'flyspell nil t))
      (define-key flyspell-mode-map (kbd "C-;") 'comment-dwim)
      (setq flyspell-duplicate-distance 0)
      (setq flyspell-mode-line-string " F")
      ;; (setq flyspell-large-region 200)
      (set-face-attribute 'flyspell-duplicate nil
                          :foreground "#EA5506" :bold t
                          :background nil :underline t)
      (set-face-attribute 'flyspell-incorrect nil
                          :foreground "#BA2636" :bold nil
                          :background nil :underline t)
      ;; ispell-complete-word のキーバインドを上書き
      (when (and (require 'helm nil t)
                 (require 'flyspell-correct-helm nil t))
        (global-set-key (kbd "<f7>") 'flyspell-correct-word-generic))
      ;; Auto complete との衝突を回避
      (with-eval-after-load "auto-complete"
        (ac-flyspell-workaround))
      (defun my:flyspell-on ()
        (cond
         ((memq major-mode major-mode-with-flyspell)
          (turn-on-flyspell))
         ((memq major-mode major-mode-with-flyspell-prog)
          (flyspell-prog-mode))
         (t nil)))
      (defun my:flyspell-off ()
        (when (memq major-mode my:flyspell-target-modes)
          (turn-off-flyspell)))
      ;; [FIXME] nextstep+inline-patch版で flyspell すると,日本語nyuuのようになる場合があるので,それを回避(IME が ONになったら一時的に flyspell を止める)
      (add-hook 'my:ime-off-hook 'my:flyspell-on)
      (add-hook 'my:ime-on-hook 'my:flyspell-off))
 
    (defvar major-mode-with-flyspell
      '(text-mode change-log-mode latex-mode yatex-mode
                  git-commit-mode org-mode))
    (defvar major-mode-with-flyspell-prog
      '(c-mode-common emacs-lisp-mode perl-mode python-mode))
    (defvar my:flyspell-target-modes
      (append major-mode-with-flyspell
              major-mode-with-flyspell-prog))
 
    ;; バッファ内の全てをチェック対象にするモードの hook に flyspell 起動を登録
    (dolist (hook major-mode-with-flyspell)
      (add-hook (intern (format "%s-hook" hook))
                #'(lambda () (flyspell-mode 1))))
    ;; コメント行のみを対象にする
    (dolist (hook major-mode-with-flyspell-prog)
      (add-hook (intern (format "%s-hook" hook))
                'flyspell-prog-mode)))

[latex-math-preview.el] TeX数式をプレビュー

以下の設定では, 数式で を押すとプレビューが走り,さらに を押すとプレビューウィンドウを閉じるように動作します.通常,q でプレビューを閉じられます.

  (when (autoload-if-found
         '(latex-math-preview-expression
           latex-math-preview-insert-symbol
           latex-math-preview-save-image-file
           latex-math-preview-beamer-frame)
         "latex-math-preview" nil t nil)
    (eval-when-compile
      (require 'latex-math-preview nil t))
    (with-eval-after-load "latex-math-preview"
      (setq latex-math-preview-command-path-alist
            '((latex . "latex")
              (dvipng . "dvipng")
              (dvips . "dvips")))
      (define-key latex-math-preview-expression-mode-map (kbd "<f6>")
        'latex-math-preview-delete-buffer))
 
    (global-set-key (kbd "<f6>") 'latex-math-preview-expression))

[po-mode.el] 翻訳ファイルの編集

;;(autoload 'po-mode "po-mode+" nil nil)
;;(autoload 'po-mode "po-mode" nil t)
(when (autoload-if-found
       '(po-mode)
       "po-mode" nil t)
  (push '("\\.po[tx]?\\'\\|\\.po\\$" . po-mode) auto-mode-alist))

[word-count.el] リージョン内の文字をカウントする

有効な頒布元に変更があった.word-count.el から新しい頒布元にたどりつける.

(when (eval-after-autoload-if-found
       '(word-count-mode) "word-count" "Minor mode to count words." t)
  (global-set-key (kbd "M-=") 'word-count-mode))

と思ったら,ビルドインの simple.el に十分な機能なのがあった.

(global-set-key (kbd "M-=") 'count-words)

[yatex.el] YaTeXモード

  (when (autoload-if-found
         '(yatex-mode)
         "yatex" "Yet Another LaTeX mode" t)
 
    (with-eval-after-load "yatex"
      ;; 1=Shift JIS, 2=JIS, 3=EUC, 4=UTF-8
      ;; (setq YaTeX-kanji-code nil)
      (modify-coding-system-alist 'file "\\.tex$'" 'utf-8))
 
    (push '("\\.tex$" . yatex-mode) auto-mode-alist)
    ;; Disable auto line break
    (add-hook 'yatex-mode-hook
              #'(lambda ()
                  (setq auto-fill-function nil))))

[auxtex.el] AUCTEXモード

(when (autoload-if-found
       '(autotex-latexmk)
       "autotex-latexmk" nil t)
  (with-eval-after-load "autotex-latexmk"
    (setq TeX-auto-save t)
    (setq TeX-parse-self t)
    (setq-default TeX-master nil)
    (setq TeX-PDF-mode t)
    (auctex-latexmk-setup))
  (push '("\\.tex$" . autotex-latexmk) auto-mode-alist))

[display-time-world-mode] 世界時計

世界の時刻を確認するために wclock.el がありました(参考:https://pxaka.tokyo/wiki/doku.php?idemacs)が,現在はビルトインの time.eldisplay-time-world-mode として吸収されているようです. display-time-world-buffer-name= に wclock が設定されているところが名残と思われます.

(when (autoload-if-found
       '(display-time-world)
       "time" nil t)
  (with-eval-after-load "time"
    (define-key display-time-world-mode-map "q" 'delete-window)))

[yasnippet.el] Emacs用のテンプレートシステム

Org-modeとの衝突を避ける

↑のサイトで紹介されている回避策とは異なり,新たな my:yas-expand を作ることで,orgバッファのソースブロック中で TAB 押下してもエラーを受けないようにしました.ソースコードは C-c ' で開く別バッファで編集します.

↑どうやら本家で対応がされたようです. my:yas-expand なしで所望の動作になりました.ありがたや,ありがたや.

  (when (autoload-if-found
         '(yas-minor-mode yas-global-mode)
         "yasnippet" nil t)
    (eval-when-compile
      (require 'yasnippet nil t))
    (with-eval-after-load "yasnippet"
      (setq yas-verbosity 2)
      (setq yas-snippet-dirs
            (list "~/Dropbox/emacs.d/yas-dict"
                  'yas-installed-snippets-dir)) ;; for Cask
 
      (defun my:yas-expand-src-edit (&optional field)
        "Override `yas-expand'. Kick `org-edit-special' directly in src-block."
        (interactive)
        (cond ((and (equal major-mode 'org-mode)
                    (org-in-src-block-p t))
               (org-edit-special))
              (t
               (yas-expand field))))
 
      (defun my:yas-expand (&optional field)
        "Disable `yas-expand' in src-block."
        (interactive)
        (cond ((and (equal major-mode 'org-mode)
                    (org-at-heading-p))
               (org-cycle))
              ((and (equal major-mode 'org-mode)
                    (org-in-src-block-p t)
                    (not (and (fboundp 'org-src-edit-buffer-p)
                              (org-src-edit-buffer-p))))
               (org-cycle))
              (t (yas-expand field))))
 
      ;; 本家できちんと対応されたので,不要になった.
      ;; (define-key yas-minor-mode-map (kbd "<tab>") 'my:yas-expand)
 
      (yas-global-mode 1))
 
    (dolist (hook
             (list
              'perl-mode-hook 'c-mode-common-hook 'js2-mode-hook 'org-mode-hook
              'python-mode-hook 'emacs-lisp-mode-hook))
      (add-hook hook 'yas-minor-mode)))

[sdic.el] 英辞郎で英単語を調べる

http://www.namazu.org/~tsuchiya/sdic/index.html

Emacs から辞書を使う.lookup を使う方法もあるが,Emacsから使うのは英辞郎に限定.

  (when (eval-after-autoload-if-found
         '(sdic-describe-word sdic-describe-word-at-point) "sdic" nil t nil
         '((setq sdic-face-color "#3333FF")
           (setq sdic-default-coding-system 'utf-8)
           ;; Dictionary (English => Japanese)
           (setq sdic-eiwa-dictionary-list
                 '((sdicf-client "~/Dropbox/Dic/EIJIRO6/EIJI-128.sdic")))
           ;; Dictionary (Japanese => English)
           (setq sdic-waei-dictionary-list
                 '((sdicf-client "~/Dropbox/Dic/EIJIRO6/WAEI-128.sdic")))))
 
    ;; カーソルの位置の英単語の意味を調べる
    (global-set-key (kbd "C-M-w") 'sdic-describe-word-at-point)
    ;; ミニバッファに英単語を入れて英辞郎を使う
    (global-set-key (kbd "C-c w") 'sdic-describe-word))

MacOSのdictionary.appで辞書をひく

osx-dictionary なるパッケージが存在します.さくさくと高速に動作します.

  (when (autoload-if-found
         '(osx-dictionary-search-pointer osx-dictionary-search-input)
         "osx-dictionary" nil t)
    (eval-when-compile
      (require 'osx-dictionary nil t))
    (with-eval-after-load "osx-dictionary"
      (setq osx-dictionary-dictionary-choice "英辞郎 第七版"))
 
    (global-set-key (kbd "C-c f w") #'osx-dictionary-search-input)
    (global-set-key (kbd "C-M-w") #'osx-dictionary-search-pointer))

COBUILD5をデフォルトで使うには,次のサイト参照してください.

私の場合は,できあがった辞書を /Library/Dictionaries/ 以下に置いています.その状態で dictionary.app の設定で辞書の優先順位を変えることで,常にCOBUILD5の情報を引っ張り出せます.もしくは, osx-dictionary-dictionary-choice で辞書名を指定します.

MacOSのdictionary.appでCOBUILD5の辞書をひく(旧)

OS標準の辞書アプリ(dictionary.app)を経由して,バッファにCOBUILD5のデータを流し込むことができます.

以下の関数を準備します.

  (defun dictionary ()
    "dictionary.app"
    (interactive)
 
    (let ((editable (not buffer-read-only))
          (pt (save-excursion (mouse-set-point last-nonmenu-event)))
          beg end)
 
      (if (and mark-active
               (<= (region-beginning) pt) (<= pt (region-end)) )
          (setq beg (region-beginning)
                end (region-end))
        (save-excursion
          (goto-char pt)
          (setq end (progn (forward-word) (point)))
          (setq beg (progn (backward-word) (point)))
          ))
 
      (let ((word (buffer-substring-no-properties beg end))
            ;;            (win (selected-window))
            (tmpbuf " * dict-process*"))
        (pop-to-buffer tmpbuf)
        (erase-buffer)
        (insert "Query: " word "\n\n")
        (start-process "dict-process" tmpbuf "dict.py" word)
        (goto-char 0)
        ;;        (select-window win)
        )))

これでカーソル以下の単語の情報が別ウィンドウに出ます.チェックし終わったら C-x 1 (delete-other-windows) で表示を閉じます. q で閉じられるようにしたり,ツールチップで表示したりもできるはずです.

マスタカさんのナイスソリューションをまだ試していないので,こちらの方がエレガントかもしれません.

なお,COBUILD5の辞書データをdictionary.appで引けるようにするには以下の操作が必要です.

私の場合は,できあがった辞書を /Library/Dictionaries/ 以下に置いています.その状態で dictionary.app の設定で辞書の優先順位を変えることで,常にCOBUILD5の情報を引っ張り出せます.

マイナーモード化

q で閉じたくなったのでマイナーモードを作りました.これまで通り, C-M-w でカーソル下の単語を調べてポップアップで表示.カーソルはその新しいバッファに移しておき, q で閉じられます.新しいバッファ内で別な単語を C-M-w で調べると,同じバッファに結果を再描画します.

マイナーモード化した elisp は,gistで公開しています.

キーバインド

マイナーモード化した dict-app を使う場合は以下のようにします.sdic を使っている人は,sdic 用の設定と衝突しないように気をつけます.

(when (eval-after-autoload-if-found
       '(dict-app-search) "dict-app" nil t)
  ;; カーソルの位置の英単語の意味を調べる
  (global-set-key (kbd "C-M-w") 'dict-app-search))

[lookup.el] 辞書

最近使っていません.

  ;; .lookup/cache.el
  (setq lookup-init-directory "~/env/dot_files/.lookup")
 
  (autoload 'lookup "lookup" nil t)
  (autoload 'lookup-region "lookup" nil t)
  (autoload 'lookup-word "lookup" nil t)
  (autoload 'lookup-select-dictionaries "lookup" nil t)
 
  (setq lookup-search-modules
        '(("default"
           ("ndeb:/Users/taka/Dropbox/Dic/COBUILD5/cobuild" :priority t)
           ("ndeb:/Users/taka/Dropbox/Dic/COBUILD5/wordbank" :priority t)
           ("ndeb:/Users/taka/Dropbox/Dic/LDOCE4/ldoce4" :priority t)
           ("ndeb:/Users/taka/Dropbox/Dic/LDOCE4/bank" :priority t)
           ("ndeb:/Users/taka/Dropbox/Dic/LDOCE4/colloc" :priority t)
           ("ndeb:/Users/taka/Dropbox/Dic/LDOCE4/activ" :priority t))))
 
  (setq lookup-agent-attributes
        '(("ndeb:/Users/taka/Dropbox/Dic/COBUILD5"
           (dictionaries "cobuild" "wordbank"))
          ("ndeb:/Users/taka/Dropbox/Dic/LDOCE4"
           (dictionaries "ldoce4" "bank" "colloc" "activ"))))
 
  (setq lookup-dictionary-attributes
        '(("ndeb:/Users/taka/Dropbox/Dic/COBUILD5/cobuild"
           (title . "COBUILD 5th Edition")
           (methods exact prefix))
          ("ndeb:/Users/taka/Dropbox/Dic/COBUILD5/wordbank"
           (title . "Wordbank")
           (methods))
          ("ndeb:/Users/taka/Dropbox/Dic/LDOCE4/ldoce4"
           (title . "Longman 4th Edition")
           (methods exact prefix))
          ("ndeb:/Users/taka/Dropbox/Dic/LDOCE4/bank"
           (title . "LDOCE4 Examples and Phrases")
           (methods exact prefix menu))
          ("ndeb:/Users/taka/Dropbox/Dic/LDOCE4/colloc"
           (title . "LDOCE4 Collocation")
           (methods exact prefix))
          ("ndeb:/Users/taka/Dropbox/Dic/LDOCE4/activ"
           (title . "Longman Activator")
           (methods exact prefix menu))))
 
  (setq lookup-default-dictionary-options
        '((:stemmer .  stem-english)))
  (setq lookup-use-kakasi nil)
 
  ;;; lookup for dictionary (require EB Library, eblook, and lookup.el)
  ;; package download: http://sourceforge.net/projects/lookup
  ;; http://lookup.sourceforge.net/docs/ja/index.shtml#Top
  ;; http://www.bookshelf.jp/texi/lookup/lookup-guide.html#SEC_Top
  ;;(load "lookup-autoloads") ; for 1.99
  ;;(autoload 'lookup "lookup" nil t)
  ;;(autoload 'lookup-region "lookup" nil t)
  ;;(autoload 'lookup-word "lookup" nil t)
  ;;(autoload 'lookup-select-dictionaries "lookup" nil t)
  ;; Search Agents
  ;; ndeb option requries "eblook" command
  ;; Use expand-file-name!
  ;;(setq lookup-search-agents `((ndeb ,(concat homedir "/Dropbox/Dic/COBUILD5"))
  ;;                            (ndeb ,(concat homedir "/Dropbox/Dic/LDOCE4"))))
  ;;(setq lookup-use-bitmap nil)
  ;;(setq ndeb-program-name "/usr/bin/eblook")
  ;;(when (eq window-system 'ns)
  ;;  (setq ndeb-program-name "/opt/local/bin/eblook")
  ;;  (setq ndeb-program-arguments '("-q" "-e" "euc-jp"))
  ;;  (setq ndeb-process-coding-system 'utf-8)) ; utf-8-hfs

キーバインド

(global-set-key (kbd "<f6>") 'lookup-word)

[cacoo] Cacoo で描く

画像をリサイズしてバッファに表示する用途にも使える.

  (when (eval-after-autoload-if-found
         '(toggle-cacoo-minor-mode) "cacoo" nil t nil
         '((require 'cacoo-plugins)))
 
    (global-set-key (kbd "M--") 'toggle-cacoo-minor-mode))

[iedit] バッファ内の同じ文字列を一度に編集する

iedit.el を使うと,バッファ内の同じ文字列を一度に編集することができる.部分重複のない変数名を置き換えるときに有用な場合がある.

(require 'iedit nil t)

[web-mode] HTML編集

HTML編集をするなら web-mode がお勧めです.古いHTMLモードを使っている方は,移行時期です.以下の my:web-indent-fold では, タブキーを打つたびにタグでくくられた領域を展開/非表示して整形します.Org-mode っぽい動作になりますが,操作の度にバッファに変更が加わったと判断されるので好みが分かれると思います.自動保存を有効にしているとそれほど気になりません.

  (when (autoload-if-found
         '(web-mode)
         "web-mode" "web-mode" t)
    (eval-when-compile
      (require 'web-mode nil t))
    (with-eval-after-load "web-mode"
      (defun my:web-indent-fold ()
        (interactive)
        (web-mode-fold-or-unfold)
        (web-mode-buffer-indent)
        (indent-for-tab-command))
 
      ;; indent
      (setq web-mode-markup-indent-offset 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.
       '(web-mode-comment-face ((t (:foreground "#D9333F"))))
       '(web-mode-css-at-rule-face ((t (:foreground "#FF7F00"))))
       '(web-mode-css-pseudo-class-face ((t (:foreground "#FF7F00"))))
       '(web-mode-css-rule-face ((t (:foreground "#A0D8EF"))))
       '(web-mode-doctype-face ((t (:foreground "#82AE46"))))
       '(web-mode-html-attr-name-face ((t (:foreground "#C97586"))))
       '(web-mode-html-attr-value-face ((t (:foreground "#82AE46"))))
       '(web-mode-html-tag-face ((t (:foreground "##4682ae" :weight bold))))
       '(web-mode-server-comment-face ((t (:foreground "#D9333F")))))
      (define-key web-mode-map (kbd "<tab>") 'my:web-indent-fold))
 
    ;; web-mode で開くファイルの拡張子を指定
    (push '("\\.phtml\\'" . web-mode) auto-mode-alist)
    (push '("\\.tpl\\.php\\'" . web-mode) auto-mode-alist)
    (push '("\\.jsp\\'" . web-mode) auto-mode-alist)
    (push '("\\.as[cp]x\\'" . web-mode) auto-mode-alist)
    (push '("\\.erb\\'" . web-mode) auto-mode-alist)
    (push '("\\.mustache\\'" . web-mode) auto-mode-alist)
    (push '("\\.djhtml\\'" . web-mode) auto-mode-alist)
    (push '("\\.html?\\'" . web-mode) auto-mode-alist))

[emmet-mode] zencoding の後継

(when (autoload-if-found
       '(emmet-mode)
       "emmet-mode" nil t nil)
  (with-eval-after-load "emmet-mode"
    (setq emmet-indentation 2)
    (setq emmet-move-cursor-between-quotes t))
  (push '("\\.xml\\'" . nxml-mode) auto-mode-alist)
  (push '("\\.rdf\\'" . nxml-mode) auto-mode-alist)
  (dolist (hook
           '(sgml-mode-hook
             nxml-mode-hook css-mode-hook html-mode-hook web-mode-hook))
    (add-hook hook 'emmet-mode)))

[zencoding-mode] HTML編集の高速化(旧)

zencoding でタグ打ちを効率化します.今は emmet-mode を使います.

  (when (eval-after-autoload-if-found
         '(zencoding-mode zencoding-expand-line)
         "zencoding-mode" "Zen-coding" t nil
         '((define-key zencoding-mode-keymap
             (kbd "M-<return>") 'zencoding-expand-line)))
 
    (add-hook 'sgml-mode-hook 'zencoding-mode)
    (add-hook 'html-mode-hook 'zencoding-mode)
    (add-hook 'web-mode-hook 'zencoding-mode))

[describe-number] 16進数などを確認

describe-number.el を使うと,16進数表示や文字コードを確認できます.

(autoload-if-found
 '(describe-number describe-number-at-point) "describe-number" nil t)

[web-beautify.el] ソースコード整形

ソースコードを読みやすい表示に整形します.バッファの自動時に自動で整形を実施するには, after-save-hook を使えばOKですね.

JavaScript M-x web-beautify-js
HTML M-x web-beautify-html
CSS M-x web-beautify-css
(if (executable-find "js-beautify")
    (when (autoload-if-found
           '(js2-mode)
           "js2-mode" nil t)
      (eval-when-compile
        (require 'js2-mode nil t))
      (with-eval-after-load "js2-mode"
        (when (require 'web-beautify nil t)
          (define-key js2-mode-map (kbd "C-c b") 'web-beautify-js)
          (define-key js2-mode-map (kbd "C-c b") 'web-beautify-css))))
  (message "--- js-beautify is NOT installed.")
  (message "--- Note: npm -g install js-beautify"))

[smartparens.el] 対応するカッコの挿入をアシスト

helm-config の後に呼んでいるのは,Emacs起動時の単純な高速化対策です.

(with-eval-after-load "helm-config"
  (when (require 'smartparens nil t)
    (sp-local-pair 'org-mode "$" "$")
    (sp-local-pair 'yatex-mode "$" "$")
    (sp-pair "`" nil :actions :rem)
    (sp-pair "'" nil :actions :rem)
    (smartparens-global-mode)))

[replace-from-region.el] 選択領域を別の文字列に置き換える

(autoload-if-found
 '(query-replace-from-region query-replace-regexp-from-region)
 "replace-from-region" nil t)

[selected.el] リージョン選択時のアクションを制御

選択した後に右クリック的な感じでリージョンに対するアクションを制御できます.選択領域に対するスピードコマンドですね.普通にシングルキーを割り当てると,日本語IMEが有効な時に上手くいかないので, activate-mark-hookdeactivate-mark-hook に細工しています.

helm-config の後に呼んでいるのは,Emacs起動時の単純な高速化対策です.

  (with-eval-after-load "helm-config"
    (when (require 'selected nil t)
      (defvar my:ime-flag nil)
      (declare-function my:ime-active-p "init" nil)
      (declare-function my:ime-on "init" nil)
      (declare-function my:ime-off "init" nil)
      (when (fboundp 'mac-set-input-method-parameter)
        (add-hook 'activate-mark-hook
                  #'(lambda ()
                      (if (not (my:ime-active-p))
                          (setq my:ime-flag nil)
                        (setq my:ime-flag t)
                        (my:ime-off))))
        (add-hook 'deactivate-mark-hook
                  #'(lambda ()
                      (when my:ime-flag
                        (my:ime-on)))))
      (define-key selected-keymap (kbd ";") #'comment-dwim)
      (define-key selected-keymap (kbd "=") #'count-words-region)
      (define-key selected-keymap (kbd "f") #'describe-function)
      (define-key selected-keymap (kbd "v") #'describe-variable)
      (define-key selected-keymap (kbd "w") #'osx-dictionary-search-pointer)
      (define-key selected-keymap (kbd "5") #'query-replace-from-region)
      (define-key selected-keymap (kbd "g") #'my:google-this)
      (define-key selected-keymap (kbd "s") #'osx-lib-say-region)
      (setq selected-org-mode-map (make-sparse-keymap))
      (define-key selected-org-mode-map (kbd "t") #'org-table-convert-region)
      (define-key selected-keymap (kbd "q") #'keyboard-quit)
 
      (when (require 'help-fns+ nil t)
        (defun my:describe-selected-keymap ()
          (interactive)
          (describe-keymap 'selected-keymap))
        (define-key selected-keymap (kbd "h") #'my:describe-selected-keymap))
      (selected-global-mode 1)))

TODO [git-complete.el] GIT grep を使う補完エンジン

(when (autoload-if-found
       '(git-complete)
       "git-complete" nil t)
  (global-set-key (kbd "C-c f <tab>") 'git-complete))

表示サポート

モードラインのモード名を短くする

以前は自作したパッケージを使っていましたが,不具合も多く,調べると diminish.el という素晴らしいパッケージがあったので移行しました.これはマイナーモードの短縮表示なので,メジャーモードは個別にフックで mode-name を書き換えて対応します. use-package.el を使っていると依存関係から自動的にインストールされます.

diminish.el を使えば,短縮名に書き換えることも,存在自体を消してしまうこともできます.helm だけ行儀が悪いので,後段での設定時に diminish を呼ぶようにしています.代替パッケージに,rich-minority-modeがあります.

メジャーモードの短縮表示は diminish に頼らず,単純に各モードの hook で対処します.

  (when (require 'diminish nil t)
    (with-eval-after-load "yasnippet" (diminish 'yas-minor-mode " y"))
    (with-eval-after-load "aggressive-indent"
      (diminish 'aggressive-indent-mode " Ai"))
    (with-eval-after-load "ggtags" (diminish 'ggtags-mode " GG"))
    (with-eval-after-load "auto-complete" (diminish 'auto-complete-mode))
    (with-eval-after-load "isearch" (diminish 'isearch-mode))
    (with-eval-after-load "autorevert" (diminish 'auto-revert-mode))
    (with-eval-after-load "smooth-scroll" (diminish 'smooth-scroll-mode))
    (with-eval-after-load "whitespace" (diminish 'global-whitespace-mode))
    (with-eval-after-load "centered-cursor-mode"
      (diminish 'centered-cursor-mode))
    (with-eval-after-load "volatile-highlights"
      (diminish 'volatile-highlights-mode))
    (with-eval-after-load "emmet-mode" (diminish 'emmet-mode))
    (with-eval-after-load "abbrev" (diminish 'abbrev-mode))
    (with-eval-after-load "doxymacs" (diminish 'doxymacs-mode))
    (with-eval-after-load "editorconfig" (diminish 'editorconfig-mode))
    (with-eval-after-load "rainbow-mode" (diminish 'rainbow-mode))
    (with-eval-after-load "guide-key" (diminish 'guide-key-mode))
    (with-eval-after-load "highlight-symbol" (diminish 'highlight-symbol-mode))
    (with-eval-after-load "which-key" (diminish 'which-key-mode))
    (with-eval-after-load "fancy-narrow" (diminish 'fancy-narrow-mode))
    (with-eval-after-load "smartparens" (diminish 'smartparens-mode))
    (with-eval-after-load "selected" (diminish 'selected-minor-mode))
    ;; (with-eval-after-load "org-autolist" (diminish 'org-autolist-mode))
    ;;;  (with-eval-after-load "helm" (diminish 'helm-mode " H"))
    )
 
  ;; メジャーモードの短縮
  (add-hook 'c-mode-hook #'(lambda () (setq mode-name "C")))
  (add-hook 'js2-mode-hook #'(lambda () (setq mode-name "JS")))
  (add-hook 'c++-mode-hook #'(lambda () (setq mode-name "C++")))
  (add-hook 'csharp-mode-hook #'(lambda () (setq mode-name "C#")))
  (add-hook 'prog-mode-hook #'(lambda () (setq mode-name "S")))
  (add-hook 'emacs-lisp-mode-hook #'(lambda () (setq mode-name "el")))
  (add-hook 'python-mode-hook #'(lambda () (setq mode-name "py")))
  (add-hook 'perl-mode-hook #'(lambda () (setq mode-name "pl")))
  (add-hook 'web-mode-hook #'(lambda () (setq mode-name "W")))
  (add-hook 'lisp-interaction-mode-hook #'(lambda () (setq mode-name "Lisp")))

モードラインのNarrowを短くする

標準では「Narrow」と表示されますが,「N」に短縮します.

(with-eval-after-load "org"
  (setq mode-line-modes
        (mapcar
         (lambda (entry)
           (if (and (stringp entry)
                    (string= entry "%n"))
               '(:eval (if (and (= 1 (point-min))
                                (= (1+ (buffer-size)) (point-max))) ""
                         " N")) entry))
         mode-line-modes)))

モードラインの節約(VC-mode編)

定形で表示されている Git を消します.

(with-eval-after-load "vc-hooks"
  (setcdr (assq 'vc-mode mode-line-format)
          '((:eval (replace-regexp-in-string "^ Git" " " vc-mode)))))

モードラインの色をカスタマイズする

  (set-face-attribute 'mode-line nil :overline "#203e6f" :box nil)
  (set-face-foreground 'mode-line "#203e6f")
  (set-face-background 'mode-line "#b2cefb")
 
  (set-face-attribute 'mode-line-inactive nil :overline "#94bbf9" :box nil)
  (set-face-foreground 'mode-line-inactive  "#94bbf9")
  (set-face-background 'mode-line-inactive "#d8e6fd")

色セット例

  • 青/白
background foreground overline
active 558BE2 FFFFFF 566f99
inactive 94bbf9 EFEFEF a4bfea
background foreground overline
active b2cefb 203e6f 203e6f
inactive 94bbf9 94bbf9 94bbf9
background foreground overline
active b1fbd6 206f47 206f47
inactive 95f9c7 95f9c7 95f9c7

visible-bell のカスタマイズ

http://www.emacswiki.org/emacs/MilesBader を参考にカスタマイズしていました.現在は後継パッケージ(http://www.emacswiki.org/emacs/echo-bell.el)があり,MELPAから取れます.

visibl-bell を使うと,操作ミスで発生するビープ音を,視覚的な表示に入れ替えられます.ただ,デフォルトではバッファ中央に黒い四角が表示されて少々鬱陶しいので,ミニバッファの点滅に変更します.

(eval-after-autoload-if-found
 '(echo-area-bell) "echo-area-bell" nil t nil
 '((setq visible-bell t)
   (setq ring-bell-function 'echo-area-bell)))
;; パッケージ(echo-bell)の場合
(when (require 'echo-bell nil t)
  (echo-bell-mode 1)
  (setq echo-bell-string "")
  (setq echo-bell-background "#FFDCDC")
  (setq echo-bell-delay 0.1))

ビープ音も無しかつ視覚効果も無くすには,次のようにします.

see http://yohshiy.blog.fc2.com/blog-entry-171.html

;;  (setq visible-bell nil) ;; default=nil
  (setq ring-bell-function 'ignore)

常に *scratch* を表示して起動する

session.eldesktop.el を使っていても,いつも *scratch* バッファを表示する.そうじゃないと安心できない人向け.

使われるメジャーモードと表示する文字列も制御できます.

;; Start Emacs with scratch buffer even though it call session.el/desktop.el
(add-hook 'emacs-startup-hook #'(lambda () (switch-to-buffer "*scratch*")))
(setq initial-major-mode 'text-mode)
(setq initial-scratch-message
      (concat "                                                              "
              (format-time-string "%Y-%m-%d (%a.)") "\n"
              "-----------------------------------------------------"
              "--------------------------\n"))

最近は,起動用にメジャーモードを書いて対応しています.詳しくはリンク先にて.

  (when (require 'buffer nil t)
    (setq initial-buffer-choice t)
    (setq initial-scratch-message nil)
    (setq initial-major-mode 'buffer-mode)
    ;;  :underline "#203e6f"
    (set-face-foreground 'header-line "#333333") ;; "#203e6f"
    (set-face-background 'header-line "#ffb08c")
    (set-face-attribute 'header-line nil
                        :inherit nil
                        :overline nil
                        :underline nil)
    (setq header-line-format
          (concat
           "  Buffers                                                    "
           (format-time-string "W%U: %Y-%m-%d %a.")))
    )
 
  (global-set-key (kbd "C-M-s") #'(lambda () (interactive)
                                    (switch-to-buffer "*scratch*")))

バッテリー情報をモードラインに表示する

;; Show battery information on the mode line.
(display-battery-mode t)

スクロールバーを非表示にする

スクロールバーを非表示にするには,nil を指定します. 右側に表示したい場合は,'right とします.

;; Show scroll bar or not
(when window-system
  (set-scroll-bar-mode -1)) ; 'right

[yascroll] フリンジにスクロールバーを出す

yascroll を使います.

helm-config の後に呼んでいるのは,Emacs起動時の単純な高速化対策です.

(with-eval-after-load "helm-config"
  (when (require 'yascroll nil t)
    (setq yascroll:delay-to-hide 2)
    (setq yascroll:disabled-modes '(org-mode))
    (set-face-foreground 'yascroll:thumb-fringe "#b2cefb")
    (set-face-background 'yascroll:thumb-fringe "#b2cefb")
    (global-yascroll-bar-mode 1)))

ツールバーを非表示にする

ツールバーは使わないので非表示にします.

;; Disable to show the tool bar.
(when window-system
  (tool-bar-mode -1))

起動時のスプラッシュ画面を表示しない

;; Disable to show the splash window at startup
(setq inhibit-startup-screen t)

カーソル行の行数をモードラインに表示する

;; Show line number in the mode line.
(with-eval-after-load "helm-config"
  (line-number-mode 1))

カーソル行の関数名をモードラインに表示する

  • emacs24.3 で重く感じるので外している.
;; Show function name in the mode line.
(which-function-mode t)

時刻をモードラインに表示する

helm-config の後に呼んでいるのは,Emacs起動時の単純な高速化対策です.

;; Show clock in in the mode line
(with-eval-after-load "helm-config"
  (setq display-time-format "%H%M.%S") ;; %y%m%d.
  (setq display-time-interval 1)
  (setq display-time-default-load-average nil)
  (display-time-mode 1))

対応するカッコをハイライトする

Built-in の paren.el が利用できる.拡張版として mic-paren.el があり,現在はこれを利用している. helm の起動で有効化しています.

helm-config の後に呼んでいるのは,Emacs起動時の単純な高速化対策です.

(with-eval-after-load "helm-config"
  (when (require 'mic-paren nil t)
    (setq paren-sexp-mode nil)
    (set-face-foreground 'paren-face-match "#FFFFFF")
    ;; Deep blue: #6666CC, orange: #FFCC66
    (set-face-background 'paren-face-match "#66CC66")
    (paren-activate)))

paren.el の場合は以下の設定.

(setq show-paren-delay 0)
(show-paren-mode t)
;; (setq show-paren-style 'expression) ; カッコ内も強調
;;(set-face-background 'show-paren-match-face "#5DA4ff") ; カーソルより濃い青
(set-face-background 'show-paren-match-face "#a634ff")
(set-face-foreground 'show-paren-match-face "#FFFFFF")
(set-face-underline-p 'show-paren-match-face nil)
(setq show-paren-style 'parenthesis)

全角スペースと行末タブ/半角スペースを強調表示する

英語で原稿を書く時に全角スペースが入っているを苦労するので,強調表示して編集中でも気づくようにします.また,行末のタブや半角スペースも無駄なので,入り込まないように強調しています.パッケージを使うと too much かなという印象があったので,個別の設定だけを使わせてもらっています.

  (with-eval-after-load "helm-config"
    ;; スペース
    (defface my:face-b-1
      '((t (:background "gray" :bold t :underline "red")))
      nil :group 'font-lock-highlighting-faces)
    ;; タブだけの行
    (defface my:face-b-2
      '((t (:background "orange" :bold t :underline "red")))
      nil :group 'font-lock-highlighting-faces)
    ;; 半角スペース
    (defface my:face-b-3 '((t (:background "orange")))
      nil :group 'font-lock-highlighting-faces)
 
    (defvar my:face-b-1 'my:face-b-1)
    (defvar my:face-b-2 'my:face-b-2)
    (defvar my:face-b-3 'my:face-b-3)
    (defadvice font-lock-mode (before my:font-lock-mode ())
      (font-lock-add-keywords
       major-mode
       ;; "[\t]+$" 行末のタブ
       '((" " 0 my:face-b-1 append)
         ("[ ]+$" 0 my:face-b-3 append)
         ("[\t]+$" 0 my:face-b-2 append))))
    (ad-enable-advice 'font-lock-mode 'before 'my:font-lock-mode)
    (ad-activate 'font-lock-mode))
 
  ;;show EOF
  ;; (defun set-buffer-end-mark()
  ;;   (let ((overlay (make-overlay (point-max) (point-max))))
  ;;     (overlay-put overlay 'before-string #("[EOF]" 0 5 (face highlight)))
  ;;     (overlay-put overlay 'insert-behind-hooks
  ;;                  '((lambda (overlay after beg end &optional len)
  ;;                      (when after
  ;;                        (move-overlay overlay (point-max) (point-max))))))))
  ;; (add-hook 'find-file-hooks 'set-buffer-end-mark)

バッファの終わりをフリンジで明示

以下の設定では,ウィンドウ以下にバッファが続いているかを表す矢印と,続いていないことを示すカギカッコをフリンジに表示します.

(setq-default indicate-buffer-boundaries
              '((top . nil) (bottom . right) (down . right)))

[migemo.el] ローマ字入力で日本語を検索する

http://0xcc.net/migemo/#download

以下は,cmigemo を使う設定です.

  (when (autoload-if-found
         '(migemo-init)
         "migemo" nil t)
    (eval-when-compile
      (require 'migemo nil t))
    (with-eval-after-load "migemo"
      (setq completion-ignore-case t) ;; case-independent
      (setq migemo-command "cmigemo")
      (setq migemo-options '("-q" "--emacs" "-i" "\a"))
      (setq migemo-dictionary "/usr/local/share/migemo/utf-8/migemo-dict")
      (setq migemo-user-dictionary nil)
      (setq migemo-regex-dictionary nil)
      (setq migemo-use-pattern-alist t)
      (setq migemo-use-frequent-pattern-alist t)
      (setq migemo-pattern-alist-length 1024)
      (setq migemo-coding-system 'utf-8-unix))
 
    (if (executable-find "cmigemo")
        (add-hook 'isearch-mode-hook 'migemo-init)
      (message "--- cmigemo is NOT installed.")))

[anything.el] 何でも絞り込みインターフェイス(旧)

  • helm に移行しました.

http://svn.coderepos.org/share/lang/elisp/anything-c-moccur/trunk/anything-c-moccur.el http://d.hatena.ne.jp/IMAKADO/20080724/1216882563

  (when (eval-after-autoload-if-found
         '(anything-other-buffer anything-complete anything-M-x
                                 anything-c-moccur-occur-by-moccur)
         "anything-startup" nil t nil
         '((require 'anything-c-moccur nil t)
           ;;  (setq moccur-split-word t)
           ;;  (setq anything-c-locate-options `("locate" "-w"))
 
           ;; M-x install-elisp-from-emacswiki recentf-ext.el
           ;; http://www.emacswiki.org/cgi-bin/wiki/download/recentf-ext.el
           ;;  (autoload-if-found 'recentf-ext "recentf-ext" nil t)
           ;;              (require 'recentf-ext nil t)
 
           (when (require 'migemo nil t)
             (setq moccur-use-migemo t))
           ;; M-x anything-grep-by-name
           (setq anything-grep-alist
                 '(("Org-files" ("egrep -Hin %s *.org" "~/Dropbox/org/"))
                   (".emacs.d" ("egrep -Hin %s *.el" "~/.emacs.d/"))
                   ("ChangeLog" ("egrep -Hin %s ChangeLog" "~/"))))))
    ;; ("Spotlight" ("mdfind %s -onlyin ~/Dropbox/Documents/Library/" ""))))
 
    (defun my:anything ()
      (interactive)
      (anything-other-buffer
       '(anything-c-source-recentf
         anything-c-source-file-name-history
         anything-c-source-buffers
         anything-c-source-emacs-commands
         anything-c-source-locate)
       " *my:anything*"))
 
    (defun my:anything-buffer ()
      (interactive)
      (anything-other-buffer
       '(anything-c-source-buffers)
       " *my:anthing-buffer*"))
 
    (when (memq window-system '(mac ns))
      (defun my:anything-spotlight ()
        "Spotlight search with anything.el"
        (interactive)
        (anything-other-buffer
         '(anything-c-source-mac-spotlight)
         " *anything-spotlight*")))
 
    (setq anything-candidate-number-limit 50) ; 50
    (setq anything-input-idle-delay 0.1)      ; 0.1
    (setq anything-idle-delay 0.5)            ; 0.5
    (setq anything-quick-update nil))        ; nil

キーバインド

普通に anything-startup を呼んでいる場合には,anything-M-xを設定する必要はない.

;; Show ibuffer powered by anything
;;  (with-eval-after-load "anything-startup"
(global-set-key (kbd "M-x") 'anything-M-x)
(global-set-key (kbd "C-c o") 'anything-c-moccur-occur-by-moccur)
(global-set-key (kbd "C-M-r") 'my:anything)
(global-set-key (kbd "C-M-s") 'my:anything-spotlight)
(global-set-key (kbd "C-x C-b") 'my:anything-buffer)
;;)

[helm.el] 続・何でも絞り込みインターフェイス

M-shelm-swoop にあてていましたが, M-s を入り口にたくさんの検索系コマンドが割り振られているため M-s M-s に変えました.

  (when (autoload-if-found
         '(helm-M-x
           helm-locate helm-recentf helm-buffers-list helm-descbinds
           helm-occur helm-swoop helm-flycheck helm-bookmarks)
         "helm-config" nil t)
    (eval-when-compile
      (require 'helm nil t)
      (require 'helm-config nil t))
    (with-eval-after-load "helm-config"
      (helm-mode 1)
      (when (require 'diminish nil t)
        (diminish 'helm-mode " H"))
 
      (when (require 'helm-swoop nil t)
        ;; カーソルの単語が org の見出し(*の集まり)なら検索対象にしない.
        (setq helm-swoop-pre-input-function
              #'(lambda()
                  (unless (thing-at-point-looking-at "^\\*+")
                    (thing-at-point 'symbol))))
        ;; 配色設定
        (set-face-attribute
         'helm-swoop-target-line-face nil :background "#FFEDDC")
        (set-face-attribute
         'helm-swoop-target-word-face nil :background "#FF5443"))
 
      (when (require 'helm-files nil t)
        (define-key helm-find-files-map
          (kbd "<tab>") 'helm-execute-persistent-action)
        (define-key helm-read-file-map
          (kbd "<tab>") 'helm-execute-persistent-action))
 
      (when (require 'helm-google nil t)
        (setq helm-google-tld "co.jp"))
 
      ;; (require 'recentf-ext nil t)
      ;; helm-find-files を呼ばせない
      ;; (add-to-list 'helm-completing-read-handlers-alist '(find-file . nil))
      ;; helm-mode-ag を呼ばせない
      (add-to-list 'helm-completing-read-handlers-alist '(ag . nil))
      ;; helm-mode-org-set-tags を呼ばせない
      (add-to-list 'helm-completing-read-handlers-alist
                   '(org-set-tags . nil))
      (setq helm-display-source-at-screen-top nil)
      ;;         (setq helm-display-header-line nil)
 
      ;; helm-autoresize-mode を有効にしつつ 30% に固定
      (helm-autoresize-mode 1)
      (setq helm-autoresize-max-height 30)
      (setq helm-autoresize-min-height 30)
      (set-face-attribute 'helm-source-header nil
                          :height 1.0 :family "Verdana" :weight 'normal
                          :foreground "#666666" :background "#DADADA")
      (when (memq window-system '(mac ns))
        (setq helm-locate-command "mdfind -name %s %s"))
 
      (require 'helm-css-scss nil t)
      (require 'helm-emmet nil t)
      (require 'helm-bm nil t)
      (require 'helm-descbinds nil t))
 
    ;; この修正が必要
    ;; (when (require 'helm-migemo nil t)
    ;;   (defun helm-compile-source--candidates-in-buffer (source)
    ;;     (helm-aif (assoc 'candidates-in-buffer source)
    ;;         (append source
    ;;                 `((candidates
    ;;                    . ,(or (cdr it)
    ;;                           (lambda ()
    ;;                             ;; Do not use `source' because other plugins
    ;;                             ;; (such as helm-migemo) may change it
    ;;                             (helm-candidates-in-buffer
    ;;                              (helm-get-current-source)))))
    ;;                   (volatile) (match identity)))
    ;;       source)))
 
    (global-set-key (kbd "M-x") 'helm-M-x)
    (global-set-key (kbd "C-M-r") 'helm-recentf)
    (global-set-key (kbd "C-M-l") 'helm-locate)
    (global-set-key (kbd "C-c f b") 'helm-bookmarks)
    (global-set-key (kbd "C-x C-b") 'helm-buffers-list)
    (global-set-key (kbd "M-s M-s") 'helm-swoop)
    (global-set-key (kbd "C-c o") 'helm-occur)
    (global-set-key (kbd "C-h d") 'helm-descbinds))

[stripe-buffer.el] テーブルの色をストライプにする

stripe-buffer.elを使います.重くツリーが多いOrgバッファだと激重になる可能性があります.

(when (eval-after-autoload-if-found
       '(org-mode) "org" "Org Mode" t nil
       '((require 'stripe-buffer nil t)))
  (add-hook 'org-mode-hook 'turn-on-stripe-table-mode))

[rainbow-delimiters] 対応するカッコに色を付ける

複数のカッコが重なる言語では,カッコの対応関係がひと目で理解し難い場合があります. rainbow-delimiters を使うと,対応するカッコを七色に色付けして見やすくできます.デフォルトだと色がパステル調で薄いので,パラメータを追加して調整します.

org-block 内でうまく動かないようなので,本格導入は様子見中です.

  (with-eval-after-load "rainbow-delimiters"
    ;; https://yoo2080.wordpress.com/2013/12/21/small-rainbow-delimiters-tutorial/
    (require 'cl-lib)
    (require 'color)
    (cl-loop
     for index from 1 to rainbow-delimiters-max-face-count
     do
     (let ((face (intern (format "rainbow-delimiters-depth-%d-face" index))))
       (cl-callf color-saturate-name (face-foreground face) 50))))
 
  (add-hook 'prog-mode-hook
            #'(lambda ()
                (unless (equal (buffer-name) "*scratch*")
                  (rainbow-delimiters-mode))))

[git-gutter-fringe] 編集差分をフレーム端で視覚化

編集差分の視覚化は元々 git-gutter が提供している機能です.有効にするとフレームの幅が若干広がってしまうので,気になる人は git-gutter-fringe を使えばよいです.

  (when (eval-after-autoload-if-found
         '(git-gutter-mode) "git-gutter-fringe" nil t nil
         '((setq git-gutter:lighter "")
           ;; "!"
           (fringe-helper-define 'git-gutter-fr:modified nil
             "...XX..."
             "...XX..."
             "...XX..."
             "...XX..."
             "...XX..."
             "........"
             "...XX..."
             "...XX...")
           ;; "+"
           (fringe-helper-define 'git-gutter-fr:added nil
             "........"
             "...XX..."
             "...XX..."
             ".XXXXXX."
             ".XXXXXX."
             "...XX..."
             "...XX..."
             "........")
           ;; "-"
           (fringe-helper-define 'git-gutter-fr:deleted nil
             "........"
             "........"
             "........"
             ".XXXXXX."
             ".XXXXXX."
             "........"
             "........"
             "........")
           (setq git-gutter-fr:side 'left-fringe)
           (set-face-foreground 'git-gutter-fr:added    "#FF2600")
           (set-face-foreground 'git-gutter-fr:modified "orange")
           (set-face-foreground 'git-gutter-fr:deleted  "medium sea green")))
 
    (add-hook 'emacs-lisp-mode-hook 'git-gutter-mode)
    (add-hook 'lisp-mode-hook 'git-gutter-mode)
    (add-hook 'perl-mode-hook 'git-gutter-mode)
    (add-hook 'python-mode-hook 'git-gutter-mode)
    (add-hook 'c-mode-common-hook 'git-gutter-mode)
    (add-hook 'nxml-mode-hook 'git-gutter-mode)
    (add-hook 'web-mode-hook 'git-gutter-mode))

[zlc.el] find-file バッファを zsh ライクにする

ファイル選択を zsh ライクに変更できます.

(when (require 'zlc nil t)
  ;; http://d.hatena.ne.jp/mooz/20101003/p1
  (zlc-mode 1)
  (set-face-attribute 'zlc-selected-completion-face nil
                      :foreground "#000000" :background "#9DFFD2" :bold t)
  ;;    (setq zlc-select-completion-immediately t)
  (let ((map minibuffer-local-map))
    ;; like menu select
    (define-key map (kbd "C-n") 'zlc-select-next-vertical)
    (define-key map (kbd "C-p") 'zlc-select-previous-vertical)
    (define-key map (kbd "C-f") 'zlc-select-next)
    (define-key map (kbd "C-b") 'zlc-select-previous)
    ;; reset selection
    (define-key map (kbd "C-c") 'zlc-reset)))

[japanese-holidays] カレンダーをカラフルにする

ビルドインの holidays と, japanese-holidays を使います.土日祝日に色を着けます.土曜日と日曜祝日で異なる配色にできます.

  (with-eval-after-load "calendar"
    (add-hook 'calendar-today-visible-hook 'calendar-mark-today)
 
    (when (require 'japanese-holidays nil t)
      (setq calendar-holidays
            (append japanese-holidays
                    holiday-local-holidays holiday-other-holidays))
      (setq mark-holidays-in-calendar t)
      (setq japanese-holiday-weekend-marker
            '(holiday nil nil nil nil nil japanese-holiday-saturday))
      (setq japanese-holiday-weekend '(0 6))
      (add-hook 'calendar-today-visible-hook 'japanese-holiday-mark-weekend)
      (add-hook 'calendar-today-invisible-hook 'japanese-holiday-mark-weekend)))

[calendar.el] カレンダーで週番号を表示する

ビルドインの calendar.el にある calendar-intermonth-text をカスタマイズすると,カレンダーに週番号を表示させることが可能です.ただ, calendar.el に記載されている例だと, calendar-week-start-day1 以外の時に計算結果がおかしくなるので,次のように calendar-absolute-from-gregorian に渡す値を補正する必要があります.

  (with-eval-after-load "calendar"
    (setq calendar-week-start-day 1)
    (copy-face 'default 'calendar-iso-week-header-face)
    (set-face-attribute 'calendar-iso-week-header-face nil
                        :height 1.0 :foreground "#1010FF"
                        :background (face-background 'default))
    (setq calendar-intermonth-header
          (propertize " w"
                      'font-lock-face 'calendar-iso-week-header-face))
 
    (copy-face font-lock-constant-face 'calendar-iso-week-face)
    (set-face-attribute 'calendar-iso-week-face nil
                        :height 1.0 :foreground "orange"
                        :background (face-background 'default))
 
    (setq calendar-intermonth-text
          '(propertize
            (format "%02d"
                    (car
                     (calendar-iso-from-absolute
                      (calendar-absolute-from-gregorian
                       (list month
                             (- day (1- calendar-week-start-day)) year)))))
            'font-lock-face 'calendar-iso-week-face)))
 
  (global-set-key (kbd "C-c f c c") 'calendar)

[guide-key] キーバインドの選択肢をポップアップする

自分用の関数にキーバインドを付けたのはいいけど,覚えられない時に使っています.以下の例では, helm もしくは org が読み込まれた時についでに有効化し, C-c f を押して, 0.5秒経つと,その後ろに続くキーの一覧がポップします.すでに覚えたキーバインドならば,0.5秒以内に打てるでしょうから,ポップ表示無しで通常通りにコマンドが発行します.色分けも効くのでわかりやすいです.

  (when (eval-after-autoload-if-found
         '(guide-key-mode) "guide-key" nil t nil
         '((setq guide-key/guide-key-sequence '("C-c f" "C-c f c"))
           (setq guide-key/popup-window-position 'bottom)
           (setq guide-key/idle-delay 0.5)
           (setq guide-key/highlight-command-regexp
                 '(("my:" . "red")
                   ("takaxp:" . "blue")))
           (guide-key-mode 1)))
 
    (with-eval-after-load "helm" (require 'guide-key nil t))
    (with-eval-after-load "org" (require 'guide-key nil t)))

[which-key] キーバインドの選択肢をポップアップする

guide-key.el の後発. guide-key.el の改良でもあり,ディスパッチャが見やすく,直感的でとても使いやすい.

起動時間を短縮するため,設定の読み込みは org-modehelm 起動時に行うように遅延設定している.

  (when (autoload-if-found
         '(which-key-mode)
         "which-key" nil t)
    (eval-when-compile
      (require 'which-key nil t))
    (with-eval-after-load "which-key"
      (setq which-key-idle-delay 1.0)
      (which-key-mode 1))
 
    (add-hook 'org-mode-hook #'which-key-mode)
    (add-hook 'helm-after-initialize-hook #'which-key-mode))

[stock-ticker] 株価をモードラインに表示

日経平均やダウ平均の状況をモードラインに表示します.表示が長くなる傾向があるので, stock-ticker--parse を再定義して,銘柄(3桁のみ)と変動率だけを表示しています.

起動時には不要なので,ウィンドウにフォーカスが移った時に開始して,さらに1分でモードラインから消えるようにしています.

色々と不安定になってきたので,最近は使っていません.

  (when (autoload-if-found
         '(my:activate-stock-ticker stock-ticker-global-mode)
         "stock-ticker" nil t)
    (eval-when-compile
      (require 'stock-ticker nil t))
    (with-eval-after-load "stock-ticker"
      (defun stock-ticker--parse (data)
        "Parse financial DATA into list of display strings."
        (let ((qs (assoc-default
                   'quote (assoc-default
                           'results (assoc-default 'query data)))))
          (mapcar
           (lambda (q)
             (let ((percent (assoc-default 'PercentChange q))
                   (name (assoc-default 'Name q))
                   (symbol (assoc-default 'Symbol q))
                   (change (assoc-default 'Change q)))
               (format " %s:%s"
                       (substring
                        (if (or
                             (string-match "=" symbol)
                             (string-match "\\^" symbol))
                            name symbol) 0 3)
                       (if percent percent ""))))
           qs)))
      (setq stock-ticker-display-interval 5)
      (setq stock-ticker-symbols '("^N225" "DOW"))
      (setq stock-ticker-update-interval 300)
 
      (defun my:activate-stock-ticker (&optional duration)
        "Activate stock-ticker within the given duration."
        (stock-ticker-global-mode 1)
        (unless (numberp duration)
          (setq duration 90))
        (run-with-timer duration nil 'stock-ticker-global-mode -1)))
 
    (add-hook 'focus-in-hook 'my:activate-stock-ticker))

[mode-icons] 使用中のモード表示をアイコンで代替

しばらく使ってみたが,統一感が失われるので使用停止中.

(when (require 'mode-icons nil t)
  ;; アイコンを保存しているディレクトリを指定
  (setq mode-icons--directory
        (expand-file-name "~/.emacs.d/.cask/package/icons"))
  (mode-icons-mode 1))

[highlight-symbol] 同じ名前のシンボルをハイライトする

一定時間が過ぎると,カーソル下のワードをバッファ内で検索し,ハイライトしてくれる.殺風景なバッファに動きが出て良い.また, highlight-symbol-nav-mode を使うと,シンボル間を M-n/M-p で移動できるので,毎度検索しなくてよい.

  (when (autoload-if-found
         '(highlight-symbol-mode highlight-symbol-nav-mode)
         "highlight-symbol" nil t)
    (eval-when-compile
      (require 'highlight-symbol nil t))
    (with-eval-after-load "highlight-symbol"
      (setq highlight-symbol-idle-delay 0.5))
 
    (dolist (hook '(emacs-lisp-mode-hook c-mode-common-hook prog-mode-hook))
      (add-hook hook 'highlight-symbol-mode)))

[all-the-icons-dired] フォントを使ったアイコンを表示

diredneotree で,ファイルのアイコンを表示します. all-the-icons をインストール後に, M-x all-the-icons-install-fonts を忘れずに実行する必要があります. neotree の設定は別セクションに記載しています.

  (when (autoload-if-found
         '(all-the-icons-dired-mode)
         "all-the-icons-dired" nil t)
 
    (add-hook 'dired-mode-hook 'all-the-icons-dired-mode))

メディアサポート

[bongo.el] Emacsのバッファで音楽ライブラリを管理する

iTunes の代わりに Emacs を使う

autoload を設定すると, *.bango-playlist*.bongo-library から起動できないので,明示的に require している.なお,bongo-mplayer を使う場合,bongo を先にrequireするとうまく動作しない(bongo.el の最後で,bongo-mplayer が provide されているからだと思われる).

以下の設定では,autoload で使いつつ,M-x init-bongo でプレイリストを読み込んでいる.これならば,Emacs起動時は軽量で,かつ,プレイリストの訪問で Bongo を開始できる.

  (eval-after-autoload-if-found
   '(bongo) "bongo-mplayer" nil t nil
   '(;; Volume control
     ;;         (require volume.el nil t)
     (setq bongo-mplayer-extra-arguments '("-volume" "1"))
     ;; Avoid error when editing bongo buffers
     (setq yank-excluded-properties nil)
     ;; Use mplayer
     (setq bongo-enabled-backends '(mplayer))
 
     (defun init-bongo ()
       (interactive)
       (bongo)
       (find-file "~/Desktop/next/Tidy/hoge.bongo-playlist"))))

org-player.el を使えば,org-mode のバッファから Bongo を操作できる.

(eval-after-autoload-if-found
 '(org-mode) "org-player" nil t)

音量コントロールには,volume.elが必要です.設定がうまくいかないので保留中

(autoload 'volume "volume" "Tweak your sound card volume." t)

[GoogleMaps.el] GoogleMaps を Emacs 内で使う

http://julien.danjou.info/software/google-maps.el

M-x google-maps で起動します.

(when (autoload-if-found
       '(google-maps)
       "google-maps" nil t)
  (with-eval-after-load "google-maps"
    (require 'org-location-google-maps nil t)))

+/- でズーム, 矢印 で移動, q で終了します.また, w でURLを取得してコピー, t で地図の種別を変更できます.

Org-mode を使っている場合には, C-c M-L で表示されるプロンプトで検索すると,プロパティにそのキーワードが記録されます.後から C-c M-l すれば,いつでも地図を表示できるようになります.

[org-google-weather.el] org-agenda に天気を表示する

残念ながら Google API が変更になり動かなくなったそうです.

http://julien.danjou.info/software/google-weather.el

(require 'google-weather nil t)
(when (require 'org-google-weather nil t)
  '(org-google-weather-use-google-icons t))

[japanlaw.el] Emacs 電子六法

Emacs で総務省の「法令データ提供システム」に登録された法令データを閲覧します. w3m が必要です.

(if (executable-find "w3m")
    (autoload-if-found
     '(japanlaw)
     "japanlaw" nil t)
  (message "--- w3m is NOT installed."))

履歴/ファイル管理

[dired] ファイラのサポートツール

dired.el をリッチに使うツール群.

  (with-eval-after-load "dired"
    (when (require 'gited nil t)
      (define-key dired-mode-map (kbd "C-x C-g") 'gited-list-branches))
    ;; https://github.com/Fuco1/dired-hacks
 
    (when (require 'dired-narrow nil t)
      (define-key dired-mode-map (kbd "/") 'dired-narrow))
 
    (require 'dired-du nil t))

Undoバッファを無限に取る

(setq undo-outer-limit nil)

[undo-tree] 編集履歴をわかりやすくたどる

Undoのツリーが表示され,履歴をたどれます. C-x uq に対して,フレームサイズの変更を紐付けています.また, auto-save-buffers が org-files をどんどん保存して記録してしまうので,ツリーを選んでいる時に auto-save-buffers が発動するのを別途抑制しています.加えて, org-tree-slide でナローイングしていると,タイムスタンプが記録される時に履歴が辿れなくなるので, org-tree-slide が有効の時は,タイムスタンプを押させないように別途制限を加えています.

  (when (autoload-if-found
         '(my:undo-tree-visualize)
         "undo-tree" nil t)
    (eval-when-compile
      (require 'moom nil t)
      (require 'undo-tree nil t))
    (with-eval-after-load "undo-tree"
      (global-undo-tree-mode)
      (defvar undo-tree-active nil)
      (setq undo-tree-mode-lighter nil) ;; モードライン領域を節約
      (defun my:undo-tree-visualizer-quit ()
        (interactive)
        (undo-tree-visualizer-quit)
        (delete-window)
        (when undo-tree-active
          (set-frame-width (selected-frame)
                           (- (frame-width) 63))
          (setq undo-tree-active nil))
        (when (< (frame-width) moom--target-frame-width)
          (set-frame-width (selected-frame) moom--target-frame-width)))
      (defun my:undo-tree-visualize ()
        (interactive)
        (when (and (not undo-tree-active) (not (eq buffer-undo-list t)))
          (set-frame-width (selected-frame)
                           (+ (frame-width) 63))
          (setq undo-tree-active t))
        (undo-tree-visualize))
 
      (define-key undo-tree-visualizer-mode-map (kbd "q")
        'my:undo-tree-visualizer-quit)
      ;; undo-tree-map にも必要
      (define-key undo-tree-map (kbd "C-x u")
        'my:undo-tree-visualize))
 
    (global-set-key (kbd "C-x u") 'my:undo-tree-visualize))

バッファ保存時にバックアップファイルを生成する

バッファが保存されるとき,必ずバックアップを生成する.

;; Backup the buffer whenever the buffer is saved
(global-set-key (kbd "C-x C-s")
                #'(lambda () (interactive) (save-buffer 16)))

バッファ保存時にバックアップを生成させない

;; *.~
(setq make-backup-files nil)
;; .#*
(setq auto-save-default nil)
;; auto-save-list
(setq auto-save-list-file-prefix nil)

ミニバッファの履歴を保存しリストアする

(when (require 'savehist nil t)
  ;; ヒストリファイルを明示的に指定
  (setq savehist-file "~/Dropbox/emacs.d/.history")
  (savehist-mode 1))

履歴サイズを大きくする

tで無限大に指定する.

(setq history-length 2000)

Emacs終了時に開いていたバッファを起動時に復元する

Built-in の desktop.el を使う.

org バッファを CONTENT view で大量に開いていると,再起動が非常に遅くなるので利用を中止した.代替手段として,session.el と recentf の組み合わせがある.最近利用したファイルとそのカーソル位置が保持されるため,最後に訪問していたファイルを比較的簡単に復元できる.頻繁に復元するバッファには,別途キーバインドを割り当てておけば問題ない.

(eval-after-autoload-if-found
 '(desktop-save desktop-clear desktop-load-default desktop-remove)
 "desktop" nil t nil
 '((desktop-save-mode 1)
   (setq desktop-files-not-to-save "\\(^/tmp\\|^/var\\|^/ssh:\\)")))

最近開いたファイルリストを保持

Built-in の recentf.el を使う.

http://d.hatena.ne.jp/tomoya/20110217/1297928222

session.el でも履歴管理できるが,anything のソースとして使っているので併用している.

起動直後から有効にするので,autolad-if-load で括る必要はない.

recentf-auto-cleanup を 'mode などにすると起動時にファイルのクリーニングが行われるてしまうので,'never で回避し,アイドルタイマーなどで対応する.これだけで50[ms]ほど起動を高速化できる.

  (when (autoload-if-found
         '(rencetf-mode recentf-save-list-without-msg recentf-open-files)
         "recentf" nil t)
    (with-eval-after-load "recentf"
      (defun recentf-save-list-without-msg ()
        (interactive)
        (let ((message-log-max nil))
          (if (require 'shut-up nil t)
              (shut-up (recentf-save-list))
            (recentf-save-list)))
        (message ""))
      (defun recentf-cleanup-without-msg ()
        (interactive)
        (let ((message-log-max nil))
          (if (require 'shut-up nil t)
              (shut-up (recentf-cleanup))
            (recentf-cleanup)))
        (message ""))
      (add-hook 'focus-out-hook 'recentf-save-list-without-msg)
      (add-hook 'focus-out-hook 'recentf-cleanup-without-msg)
 
      (setq recentf-max-saved-items 2000)
      (setq recentf-save-file
            (expand-file-name "~/.emacs.d/recentf"))
      (setq recentf-auto-cleanup 'never)
      (setq recentf-exclude
            '(".recentf" "^/tmp\\.*"
              "^/private\\.*" "^/var/folders\\.*" "/TAGS$")))
 
    (add-hook 'after-init-hook 'recentf-mode))

深夜にバッファを自動整理する

http://www.emacswiki.org/emacs-zh/CleanBufferList

(when (require 'midnight nil t)
  (setq clean-buffer-list-buffer-names
        (append clean-buffer-list-kill-buffer-names
                '("note.txt")))
  (setq clean-buffer-list-delay-general 1)
  (setq clean-buffer-list-delay-special 10))

[auto-save-buffers.el] 一定間隔でバッファを保存する

http://0xcc.net/misc/auto-save/

同じ機能で比較的新しいパッケージに, real-auto-save があります.ただ,私の場合は,以下のようなモードごとの制御がうまくできなかったので移行していません.

helm-config の後に呼んでいるのは,Emacs起動時の単純な高速化対策です.

(with-eval-after-load "helm-config"
  (when (require 'auto-save-buffers nil t)
    (defun my:auto-save-buffers ()
      (cond ((equal major-mode 'undo-tree-visualizer-mode) nil)
            ((equal major-mode 'diff-mode) nil)
            ((string-match "Org Src" (buffer-name)) nil)
            (t (if (require 'shut-up nil t)
                   (shut-up (auto-save-buffers))
                 (auto-save-buffers)))))
    (run-with-idle-timer 1.6 t #'my:auto-save-buffers)))

[backup-dir.el] バックアップファイルを一箇所に集める

backup-each-save を使うようになりました.

(make-variable-buffer-local 'backup-inhibited)
(setq backup-files-store-dir "~/.emacs.d/backup")
(unless (file-directory-p backup-files-store-dir)
  (message "!!! %s does not exist. !!!" backup-files-store-dir)
  (sleep-for 1))
(when (require 'backup-dir nil t)
  (when (file-directory-p backup-files-store-dir)
    ;; backup path
    (setq bkup-backup-directory-info '((t "~/.emacs.d/backup" ok-create)))
    ;; for tramp
    (setq tramp-bkup-backup-directory-info bkup-backup-directory-info)
    ;; generation properties
    (setq delete-old-versions t
          kept-old-versions 0
          kept-new-versions 5
          version-control t)))

[backup-each-save] クラッシュに備える

直近のファイルを常にバックアップします. backup-dir.el でも良いですが,バックアップの目的が,バッファ編集中に emacs が落ちる時の保険ならば, backup-each-save の方が適切な場合があります.以下の例では,すべてのファイルを保存の度に保存しつつ, emacs 終了時に7日前までのバックアップファイルをすべて削除するようにしています.

helm-config の後に呼んでいるのは,Emacs起動時の単純な高速化対策です.

  (when (autoload-if-found
         '(backup-each-save)
         "backup-each-save" nil t)
    (with-eval-after-load "backup-each-save"
      (setq backup-each-save-mirror-location "~/.emacs.d/backup")
      (setq backup-each-save-time-format "%y-%m-%d_%M:%S")
      (setq backup-each-save-size-limit 1048576))
 
    ;; なぜか (backup-each-save) の直接呼び出しだとだめ
    (with-eval-after-load "helm-config"
      (require 'backup-each-save nil t)
      ;; %y-%m-%d_%M:%S で終わるファイルを本来のメジャーモードで開く
      (add-to-list 'auto-mode-alist '("-[0-9-]\\{8\\}_[0-9:]\\{5\\}$" nil t)))
 
    (add-hook 'after-save-hook
              #'(lambda () (unless (equal (buffer-name) "recentf")
                             (backup-each-save)))))
 
  (when (autoload-if-found
         '(recursive-delete-backup-files delete-backup-files)
         "utility" nil t)
 
    ;; backup-each-save が作るファイルのうち条件にあうものを終了時に削除
    (add-hook 'kill-emacs-hook
              #'(lambda ()
                  (when (fboundp 'recursive-delete-backup-files)
                    (recursive-delete-backup-files 7)))))

特定のファイルを Dropbox 以下にバックアップする

複数の端末でEmacsを使うと,稀に端末の環境に依存した設定ファイルが必要になり,それらは端末間で共有しません.私の場合は, recentf がそれに該当します.とは言えバックアップしていないのは不安なので,なんとかします.引数にバックアップ対象のファイルリストを渡せます.

ちょっとダサいのですが,予め ~/Dropbox/backup の下に, system-name で得られる値のディレクトリを作成する必要があります. my:backup./utility.el で実装しています.

helm-config の後に呼んでいるのは,Emacs起動時の単純な高速化対策です.

(with-eval-after-load "helm-config"
  (defun my:backup-recentf ()
    (my:backup "~/.emacs.d/recentf"))
  (run-with-idle-timer 180 t 'my:backup-recentf))

[session.el] 様々な履歴を保存し復元に利用する

http://emacs-session.sourceforge.net/

  • 入力履歴の保持(検索語,表示したバッファ履歴)
  • 保存時のカーソル位置の保持
  • キルリングの保持
  • 変更が加えられたファイル履歴の保持

M-x session-save-session

session-undo-check を指定していると,保存時ではなくバッファを閉じるときの状態を保持する.

Org Mode と併用する場合は,my:org-reveal-session-jump の設定が必須.

  (when (autoload-if-found
         '(session-initialize)
         "session" nil t)
    (eval-when-compile
      (require 'session nil t))
    (with-eval-after-load "session"
      (add-to-list 'session-globals-exclude 'org-mark-ring)
      ;; Change save point of session.el
      (setq session-save-file
            (expand-file-name "~/Dropbox/emacs.d/.session"))
      (setq session-initialize '(de-saveplace session keys menus places)
            session-globals-include '((kill-ring 100)
                                      (session-file-alist 100 t)
                                      (file-name-history 200)
                                      search-ring regexp-search-ring))
      (setq session-undo-check -1))
 
    (add-hook 'after-init-hook 'session-initialize))
 
  ;; FIXME
  ;;  (setq session-set-file-name-exclude-regexp
  ;;        "^/private/\\.\\*"))
  ;;          "[/\\]\\.overview\\|[/\\]\\.session\\|News[/\\]\\|^/private\\.*\\|^/var/folders\\.*"))

次はテスト中.orgバッファを開いたらカーソル位置をorg-revealしたいが,time-stampなどと組み合わせたり,org-tree-slideと組み合わせていると,うまくいかない.バッファを表示した時に org-reveal (C-c C-r) を打つのをサボりたいだけなのだが...

http://www.emacswiki.org/emacs/EmacsSession

  (when (autoload-if-found
         '(session-initialize)
         "session" nil t)
    (add-hook 'after-init-hook 'session-initialize)
    (eval-after-load "session"
      '(progn
         ;; For Org-mode
         (defun my:maybe-reveal ()
           (interactive)
           (when (and (or (memq major-mode '(org-mode outline-mode))
                          (and (boundp 'outline-minor-mominor-de)
                               outline-minor-mode))
                      (outline-invisible-p))
             (if (eq major-mode 'org-mode)
                 (org-reveal)
               (show-subtree))))
 
         (defun my:org-reveal-session-jump ()
           (message "call!")
           (when (and (eq major-mode 'org-mode)
                      (outline-invisible-p))
             (org-reveal)))
 
         ;; C-x C-/
         (add-hook 'session-after-jump-to-last-change-hook
                   'my:maybe-reveal))))

[wakatime-mode.el] WakaTime を利用して作業記録する

  1. https://www.wakati.me/(API発行とログGUI表示)
  2. https://github.com/wakatime/wakatime(ログ記録用スクリプト)
  3. https://github.com/nyuhuhuu/wakatime-mode(Emacs用プラグイン)

利用開始前に,ログ表示サイトでルールをカスタマイズしておくとよい.例えば,拡張子が .org なファイルの場合,言語設定を Text にする,という具合に.すると,グラフ表示がわかりやすくなる.

  (when (require 'wakatime-mode nil t)
    (setq wakatime-api-key "<insert your own api key>")
    (setq wakatime-cli-path "/Users/taka/Dropbox/emacs.d/bin/wakatime-cli.py")
    ;; すべてのバッファで訪問時に記録を開始
;    (global-wakatime-mode)
    )

[neotree.el] ディレクトリ情報をツリー表示

  (when (autoload-if-found
         '(neotree neotree-toggle)
         "neotree" nil t)
    (eval-when-compile
      (require 'neotree nil t))
 
    (with-eval-after-load "neotree"
      (require 'moom nil t)
      (setq neo-show-hidden-files nil)
      (setq neo-persist-show t)
      (setq neo-theme 'arrow)
      (setq neo-smart-open t)
      (when (require 'all-the-icons-dired nil t)
        (setq neo-theme (if (display-graphic-p) 'icons 'arrow)))
      (defun advice:neotree-show ()
        "Extension to support change frame width when opening neotree."
        (unless (neo-global--window-exists-p)
          (set-frame-width (selected-frame) (+ (frame-width) 26))
          (sit-for 0.01)
          (set-frame-width (selected-frame) (+ (frame-width) 2))))
      (advice-add 'neotree-show :before #'advice:neotree-show)
      (defun advice:neotree-hide ()
        "Extension to support change frame width when hiding neotree."
        (when (neo-global--window-exists-p)
          (set-frame-width (selected-frame) (- (frame-width) 2))
          (sit-for 0.01)
          (set-frame-width (selected-frame) (- (frame-width) 26)))
        (when (< (frame-width) moom--target-frame-width)
          (set-frame-width (selected-frame) moom--target-frame-width)))
      (advice-add 'neotree-hide :before #'advice:neotree-hide)
      (when neo-persist-show
        (add-hook 'popwin:before-popup-hook
                  #'(lambda () (setq neo-persist-show nil)))
        (add-hook 'popwin:after-popup-hook
                  #'(lambda () (setq neo-persist-show t)))))
 
    (global-set-key (kbd "C-c n") 'neotree-toggle))

[osx-trash] system-move-file-to-trash を有効にする

osx-trash は,OSXで system-move-file-to-trash を使えるようにする.単独で使うのはあまり考えられないので,読み込みを dired に紐付けます.

(with-eval-after-load "dired"
  (setq dired-use-ls-dired nil)
  (when (require 'osx-trash nil t)
    (setq delete-by-moving-to-trash t)
    (osx-trash-setup)))

TODO [helpful] リッチなヘルプページ

(when (autoload-if-found
       '(helpful-function)
       "helpful" nil t)
  (with-eval-after-load "helpful"
    (require 'helm-config nil t))
  (global-set-key (kbd "C-h f") 'helpful-function))

開発サポート

便利キーバインド

(global-set-key (kbd "C-;") 'comment-dwim) ;; M-; is the defualt
(global-set-key (kbd "C-c c") 'compile)

[gist.el] Gist インターフェイス

(autoload-if-found '(gist) "gist" nil t)

[doxymacs.el] Doxygen のコメントを簡単に入力する

http://doxymacs.sourceforge.net/

  (when (autoload-if-found
         '(doxymacs-mode)
         "doxymacs" nil t)
    (eval-when-compile
      (require 'doxymacs nil t))
    (with-eval-after-load "doxymacs"
      (setq doxymacs-doxygen-style "JavaDoc")
      (add-hook 'font-lock-mode-hook
                #'(lambda ()
                    (when (memq major-mode '(c-mode c++-mode))
                      (doxymacs-font-lock))))
      (define-key doxymacs-mode-map (kbd "C-c C-s") 'ff-find-other-file))
 
    (add-hook 'c-mode-common-hook 'doxymacs-mode))

[matlab.el] Matlab用の設定 :Mac:

(when (and (memq window-system '(mac ns))
           (> emacs-major-version 23))
  (when (autoload-if-found
         '(matlab-mode matlab-shell)
         "matlab" nil t)
    (push '("\\.m$" . matlab-mode) auto-mode-alist)))

[flycheck.el] 構文エラー表示

auto-complete より前に hook設定しておくと余計なエラーが出ないようです.

  ;;http://qiita.com/senda-akiha/items/cddb02cfdbc0c8c7bc2b
  (when (autoload-if-found
         '(flycheck-mode)
         "flycheck" nil t)
    (with-eval-after-load "flycheck"
      (require 'helm-flycheck nil t)
      (setq flycheck-gcc-language-standard "c++11")
      (setq flycheck-clang-language-standard "c++11")
      (when (require 'flycheck-pos-tip nil t)
        '(custom-set-variables
          '(flycheck-display-errors-function
            #'flycheck-pos-tip-error-messages))))
 
    ;; (flycheck-add-next-checker 'javascript-jshint
    ;; 'javascript-gjslint)
 
    (dolist
        (hook
         '(js2-mode-hook c-mode-common-hook perl-mode-hook python-mode-hook))
      (add-hook hook 'flycheck-mode)))

[auto-complete.el] 自動補完機能

http://cx4a.org/software/auto-complete/manual.ja.html

  • 辞書データを使う( =ac-dictionary-directories= )
  • auto-complete.el, auto-complete-config.el, fuzzy.el, popup.el を使う.
  • ac-auto-start を 4 にしておけば,3文字までは TAB を yasnippet に渡せる.

Org-mode ユーザにとって TAB は非常に重要なコマンド.そこに auto-completeyasnippetTAB を奪いに来るので,住み分けが重要になる.ac-auto-start4にすると,<sTAB によるソースブロックの短縮入力を yasnippet で実行できる(この目的だけならば3を指定してもいい).<sys などと4文字入力すると,auto-complete が動いて <system> などを補完してくれる.もちろん,見出しで TAB を押すときには,ツリーの表示/非表示の切り替えになる.

情報源については,オンラインマニュアルを参照のこと.

auto-complete が正しく効いているかは,バッファ内で適当にパスを打ち込んで,補完候補が表示されるかで判定判定できると思います( /home を入力とか)

  (when (autoload-if-found
         '(ac-default-setup ac-org-mode-setup)
         "auto-complete" nil t)
    (eval-when-compile
      (require 'auto-complete nil t))
    (with-eval-after-load "auto-complete"
      (require 'auto-complete-config nil t)
      (ac-config-default)
      ;; 追加のメジャーモードを設定
      (add-to-list 'ac-modes 'objc-mode)
      (add-to-list 'ac-modes 'org-mode)
      ;; ac-modes にあるメジャーモードで有効にする
      ;;lisp, c, c++, java, perl, cperl, python, makefile, sh, fortran, f90
      (global-auto-complete-mode t)
      ;; 辞書
      (add-to-list 'ac-dictionary-directories "~/.emacs.d/ac-dict")
      ;; history
      (setq ac-comphist-file "~/Dropbox/config/ac-comphist.dat")
      ;; n文字以上で補完表示する("<s TAB" の場合 yasnippet が呼ばれる)
      (setq ac-auto-start 4)
      ;; n秒後にメニューを表示
      (setq ac-auto-show-menu 2.0)
      ;; ツールチップの表示
      (setq ac-use-quick-help t)
      (setq ac-quick-help-delay 2.0)
      (setq ac-quick-help-height 10)
      ;; C-n/C-p でメニューをたどる
      (setq ac-use-menu-map t)
      ;; TAB で補完(org-mode でも効くようにする)
      (define-key ac-completing-map [tab] 'ac-complete)
      ;; RET での補完を禁止
      (define-key ac-completing-map "\r" nil)
      ;; 補完メニューの表示精度を高める
      (setq popup-use-optimized-column-computation nil)
      ;;(setq ac-candidate-max 10)
 
      (defun ac-org-mode-setup ()
        ;;            (message " >> ac-org-mode-setup")
        (setq ac-sources '(
                           ac-source-abbrev ; Emacs の略語
                                     ;;; ac-source-css-property ; heavy
                           ac-source-dictionary ; 辞書
                           ac-source-features
                           ac-source-filename
                           ac-source-files-in-current-dir
                           ac-source-functions
                                     ;;; ac-source-gtags
                                     ;;; ac-source-imenu
                                     ;;; ac-source-semantic
                           ac-source-symbols
                           ac-source-variables
                                     ;;; ac-source-yasnippet
                           )))
 
      (defun ac-default-setup ()
        ;;            (message " >> ac-default-setup")
        ;; ac-source-words-in-same-mode-buffers
        (setq ac-sources '(ac-source-filename
                           ac-source-abbrev
                           ac-source-dictionary
                           ))))
 
    (dolist (hook
             (list 'org-mode-hook 'python-mode-hook
                   'perl-mode-hook 'objc-mode-hook))
      (add-hook hook 'ac-default-setup))
    ;; *scratch* バッファでは無効化
    (add-hook 'lisp-mode-hook
              #'(lambda () (unless (equal "*scratch*" (buffer-name))
                             (ac-default-setup))))
    (add-hook 'org-mode-hook 'ac-org-mode-setup))

[auto-complete-clang.el] オムニ補完

C++バッファでメソッドを補完対象とする.try-catch を使っている場合, -fcxx-exceptions オプションが必要で,これはプリコンパイルヘッダを生成する時も同じだ.ここ示す設定では, ~/.emacs.d/ 以下に stdafx.pch を生成する必要があり,以下のコマンドを用いてプリコンパイルヘッダを生成する.ヘッダファイルのパスを適切に与えれば,Boostや自作のライブラリも補完対象に設定できる.

現状では,補完直後にデフォルトの引数がすべて書き込まれてしまう.なんかうまいことしたいものだ.

clang -cc1 -x c++-header -fcxx-exceptions ./stdafx.h -emit-pch -o ./stdafx.pch -I/usr/local/include -I/usr/local/include/netpbm

以下の設定は,先に auto-complete.el に関する設定を読み込んでいることを前提としている.

  (when (autoload-if-found
         '(auto-complete ac-cc-mode-setup)
         "auto-complete" nil t)
    (eval-when-compile
      (require 'auto-complete nil t))
    (with-eval-after-load "auto-complete"
      (require 'auto-complete-clang nil t)
      ;; ac-cc-mode-setup のオーバーライド
      (defun ac-cc-mode-setup ()
        (setq ac-clang-prefix-header "~/.emacs.d/stdafx.pch")
        (setq ac-clang-flags '("-w" "-ferror-limit" "1"
                               "-fcxx-exceptions"))
        (setq ac-sources '(ac-source-clang
                           ac-source-yasnippet
                           ac-source-gtags))))
 
    (add-hook 'c-mode-common-hook 'ac-cc-mode-setup))

次のコードを hoge.cpp として保存し, vt について補完できれば, STLBoost のプリコンパイルヘッダが有効になっていることを確認できる.

#include <iostream>
#include <vector>
#include <boost/timer.hpp>
 
int main(){
  std::vector<int> v;
  v; // ここ
  boost::timer t;
  cout << t; // ここ
  return 1;
}

参考サイト

[hideshowvis.el] 関数の表示/非表示

  (when (and (memq window-system '(mac ns))
             (> emacs-major-version 23))
    (when (eval-after-autoload-if-found
           '(hideshowvis-enable hideshowvis-minor-mode) "hideshowvis" nil t nil
           '((define-key hideshowvis-mode-map (kbd "C-(") 'hs-hide-block)
             (define-key hideshowvis-mode-map (kbd "C-)") 'hs-show-block)))
 
      (add-hook 'emacs-lisp-mode-hook
                #'(lambda () (unless (equal "*scratch*" (buffer-name))
                               (hideshowvis-enable))))
      (dolist (hook (list 'perl-mode-hook 'c-mode-common-hook))
        (add-hook hook 'hideshowvis-enable))))

[origami.el] 関数の折りたたみ

  (when (autoload-if-found
         '(origami-mode origami-toggle-node)
         "origami" nil t)
    (eval-when-compile
      (require 'origami nil t))
 
    (with-eval-after-load "origami"
      (define-key origami-mode-map (kbd "C-t") #'origami-toggle-node)
      (define-key origami-mode-map (kbd "C-u C-t")
        #'origami-toggle-all-nodes))
 
    (dolist (hook '(emacs-lisp-mode-hook c-mode-common-hook yatex-mode-hook))
      (add-hook hook #'origami-mode)))

[quickrun.el] お手軽ビルド

カレントバッファで編集中のソースコードをビルド・実行して,別バッファに結果を得ます.

  (when (autoload-if-found
         '(quickrun)
         "quickrun" nil t)
 
    (eval-when-compile
      (require 'python-mode nil t)
      (require 'perl-mode nil t)
      (require 'gnuplot-mode nil t))
 
    (add-hook 'c-mode-common-hook
              #'(lambda () (define-key c++-mode-map (kbd "<f5>") 'quickrun)))
    (add-hook 'python-mode-hook
              #'(lambda () (define-key python-mode-map (kbd "<f5>") 'quickrun)))
    (add-hook 'perl-mode-hook
              #'(lambda () (define-key perl-mode-map (kbd "<f5>") 'quickrun)))
    (add-hook 'gnuplot-mode-hook
              #'(lambda () (define-key gnuplot-mode-map (kbd "<f5>") 'quickrun))))

[ggtags.el] タグジャンプ

# brew install global –with-exuberant-ctags –with-pygments

  (if (executable-find "gtags")
      (when (autoload-if-found
             '(ggtags-mode)
             "ggtags" nil t)
        (eval-when-compile
          (require 'ggtags nil t))
 
        (with-eval-after-load "ggtags"
          (setq ggtags-completing-read-function t)
          (define-key ggtags-mode-map (kbd "M-]") nil))
 
        (dolist (hook (list
                       'perl-mode-hook 'emacs-lisp-mode-hook 'js2-mode-hook
                       'python-mode-hook  'c-mode-common-hook))
          (add-hook hook #'(lambda () (ggtags-mode 1)))))
 
    (message "--- gtags is NOT installed in this system."))

[0xc] N進数変換

実施頻度の高い16進数と10進数の相互変換に重宝します.

(when (autoload-if-found
       '(0xc-convert 0xc-convert-point)
       "0xc" nil t)
  (global-set-key (kbd "C-c f h") '0xc-convert))

TODO [EditorConfig] コードスタイルの強制

helm-config の後に呼んでいるのは,Emacs起動時の単純な高速化対策です.

(with-eval-after-load "helm-config"
  (if (executable-find "editorconfig")
      (when (require 'editorconfig nil t)
        ;; (add-to-list 'editorconfig-exclude-modes 'org-mode)
        ;; (when (require 'editorconfig-charset-extras nil t)
        ;;   (add-hook 'editorconfig-custom-hooks
        ;;             'editorconfig-charset-extras))
        (editorconfig-mode 1))
    (message "editorconfig is NOT installed.")))

例えば,次のようなファイルを共有プロジェクトに保存しておきます. .editorconfig として配置します.

  root = true
 
  [*]
  charset = utf-8
  end_of_line = lf
  insert_final_newline = true
  indent_style = space
  indent_size = 2
  trim_trailing_whitespace = true

[uuid.el] UUID の生成

新しい UUID を生成してカーソル位置に書き出すように my:uuid-string を定義しています.

(when (autoload-if-found
       '(uuid-string my:uuid-string)
       "uuid" nil t)
  (with-eval-after-load "uuid"
    (defun my:uuid-string ()
      (interactive)
      (insert (uuid-string)))))

Org Mode

基本設定

  (when (autoload-if-found
         '(org-mode)
         "org" "Org Mode" t)
    (with-eval-after-load "org"
      (require 'org-habit nil t)
      (require 'org-mobile nil t)
 
      ;; C-c & が yasnippet にオーバーライドされているのを張り替える
      (define-key org-mode-map (kbd "C-c 4") 'org-mark-ring-goto)
 
      ;; Set checksum program path for windows
      (when (eq window-system 'w32)
        (setq org-mobile-checksum-binary "~/Dropbox/do/cksum.exe"))
 
      ;; org ファイルの集中管理
      (setq org-directory "~/Dropbox/org/")
 
      ;; Set default table export format
      (setq org-table-export-default-format "orgtbl-to-csv")
 
      ;; Toggle inline images display at startup
      (setq org-startup-with-inline-images t)
 
      ;; dvipng
      (setq org-export-with-LaTeX-fragments t)
 
      ;; orgバッファ内の全ての動的ブロックを保存直前に変更する
      ;; (add-hook 'before-save-hook 'org-update-all-dblocks)
 
      ;; アーカイブファイルの名称を指定
      (setq org-archive-location "%s_archive::")
 
      ;; タイムスタンプによるログ収集設定
      (setq org-log-done t) ; t ではなく,'(done), '(state) を指定できる
 
      ;; ログをドロアーに入れる
      (setq org-log-into-drawer t)
 
      ;; アンダースコアをエクスポートしない(_{}で明示的に表現できる)
      (setq org-export-with-sub-superscripts nil)
 
      ;; #+OPTIONS: \n:t と同じ
      (setq org-export-preserve-breaks t)
 
      ;; タイマーの音
      ;; (lsetq org-clock-sound "");
 
      ;; org-clock の計測時間をモードラインではなくタイトルに表示する
      (setq org-clock-clocked-in-display 'frame-title)
 
      ;; helm を立ち上げる
      (require 'helm-config nil t)
 
      ;; - を優先.親のブリッツ表示を継承させない
      (setq org-list-demote-modify-bullet
            '(("+" . "-")
              ("*" . "-")
              ("1." . "-")
              ("1)" . "-")
              ("A)" . "-")
              ("B)" . "-")
              ("a)" . "-")
              ("b)" . "-")
              ("A." . "-")
              ("B." . "-")
              ("a." . "-")
              ("b." . "-"))))
 
    (push '("\\.txt$" . org-mode) auto-mode-alist))

contribution を使う

(setq load-path (append '("~/devel/git/org-mode/contrib/lisp") load-path))

iCal との連携

  ;; ~/Dropbox/Public は第三者に探索される可能性があるので要注意
  ;; default = ~/org.ics
  ;; C-c C-e i org-export-icalendar-this-file
  ;; C-c C-e I org-export-icalendar-all-agenda-files
  ;; C-c C-e c org-export-icalendar-all-combine-agenda-files
  (when (autoload-if-found
         '(my:ox-icalendar my:ox-icalendar-cleanup)
         "ox-icalendar" nil t)
    (eval-when-compile
      (require 'ox-icalendar nil t))
    (with-eval-after-load "ox-icalendar"
      (setq org-icalendar-combined-agenda-file "~/Desktop/org-ical.ics")
      ;; iCal の説明文
      (setq org-icalendar-combined-description "OrgModeのスケジュール出力")
      ;; カレンダーに適切なタイムゾーンを設定する(google 用には nil が必要)
      (setq org-icalendar-timezone "Asia/Tokyo")
      ;; DONE になった TODO はアジェンダから除外する
      (setq org-icalendar-include-todo t)
      ;; (通常は,<>--<> で区間付き予定をつくる.非改行入力で日付がNoteに入らない)
      (setq org-icalendar-use-scheduled '(event-if-todo))
           ;;; DL 付きで終日予定にする:締め切り日(スタンプで時間を指定しないこと)
      ;; (setq org-icalendar-use-deadline '(event-if-todo event-if-not-todo))
      (setq org-icalendar-use-deadline '(event-if-todo))
 
      (defun my:ox-icalendar ()
        (interactive)
        (let ((temp-agenda-files org-agenda-files))
          (setq org-agenda-files '("~/Dropbox/org/org-ical.org"))
          ;; org-icalendar-export-to-ics を使うとクリップボードが荒れる
          (org-icalendar-combine-agenda-files)
          (setq org-agenda-files temp-agenda-files)
          ;; Dropbox/Public のフォルダに公開する
          ;;           (shell-command
          ;;            (concat "cp " org-icalendar-combined-agenda-file " "
          ;;                    org-icalendar-dropbox-agenda-file))
          (if (eq 0 (shell-command
                     (concat "scp -o ConnectTimeout=5 "
                             org-icalendar-combined-agenda-file " "
                             org-ical-file-in-orz-server)))
              (message "Uploading... [DONE]")
            (message "Uploading... [MISS]"))
          (my:ox-icalendar-cleanup)))
 
      (defun my:ox-icalendar-cleanup ()
        (interactive)
        (when (file-exists-p
               (expand-file-name org-icalendar-combined-agenda-file))
          (shell-command-to-string
           (concat "rm -rf " org-icalendar-combined-agenda-file))))))

スピードコマンド

(with-eval-after-load "org"
  (setq org-use-speed-commands t)
  (add-to-list 'org-speed-commands-user '("d" org-todo "DONE"))
  (add-to-list 'org-speed-commands-user '("P" my:proportional-font-toggle))
  (add-to-list 'org-speed-commands-user
               '("$" call-interactively 'org-archive-subtree)))

Pomodoro

http://orgmode.org/worg/org-gtd-etc.html

  (with-eval-after-load "org"
    (add-to-list 'org-modules 'org-timer)
    (setq org-timer-default-timer "25")
    ;; (add-hook 'org-clock-in-hook
    ;;        '(lamda ()
    ;;                (if (not org-timer-current-timer)
    ;;                    (org-timer-set-timer '(16)))))
 
    (setq growl-pomodoro-default-task-name "doing the task")
    (setq growl-pomodoro-task-name 'growl-pomodoro-default-task-name)
 
    (defun set-growl-pomodoro-task-name ()
      (interactive "P")
      (setq growl-pomodoro-task-name
            (read-from-minibuffer "Task Name: " growl-pomodoro-default-task-name)))
    (add-hook 'org-timer-set-hook 'set-growl-pomodoro-task-name)
 
    (defun growl-pomodoro-timer ()
      (interactive)
      (shell-command-to-string
       (concat "growlnotify -s -a Emacs -t \"++ Pomodoro ++\" -m \""
               "The end of " growl-pomodoro-task-name "!\""))
      (shell-command-to-string
                                          ;   (concat "say The end of " growl-pomodoro-task-name)
       (concat "say -v Kyoko " growl-pomodoro-task-name)
       ))
 
    (add-hook 'org-timer-done-hook 'growl-pomodoro-timer))

face 関連

  (with-eval-after-load "org"
    ;; Font lock を使う
    (global-font-lock-mode 1)
    (add-hook 'org-mode-hook 'turn-on-font-lock)
    ;; ウィンドウの端で折り返す(想定と逆の振る舞い.どこかにバグがある)
    (setq org-startup-truncated nil)
    ;; サブツリー以下の * を略式表示する
    (setq org-hide-leading-stars t)
    ;; Color setting for TODO keywords
    ;; Color for priorities
    ;; (setq org-priority-faces
    ;;  '(("?A" :foreground "#E01B4C" :background "#FFFFFF" :weight bold)
    ;;    ("?B" :foreground "#1739BF" :background "#FFFFFF" :weight bold)
    ;;    ("?C" :foreground "#575757" :background "#FFFFFF" :weight bold)))
    ;; Color setting for Tags
 
    ;; #CC3333
    (setq org-todo-keyword-faces
          '(("FOCUS"    :foreground "#FF0000" :background "#FFCC66")
            ("BUG"      :foreground "#FF0000" :background "#FFCC66")
            ("CHECK"    :foreground "#FF9900" :background "#FFF0F0" :underline t)
            ("ICAL"     :foreground "#33CC66")
            ("APPROVED" :foreground "#66CC66")
            ("QUESTION" :foreground "#FF0000")
            ("WAIT"     :foreground "#CCCCCC" :background "#666666")
            ("EDIT"     :foreground "#FF33CC")
            ("READ"     :foreground "#9933CC")
            ("MAIL"     :foreground "#CC3300" :background "#FFEE99")
            ("PLAN"     :foreground "#FF6600")
            ("PLAN2"    :foreground "#FFFFFF" :background "#FF6600")
            ("REV1"     :foreground "#3366FF")
            ("REV2"     :foreground "#3366FF" :background "#99CCFF")
            ("REV3"     :foreground "#FFFFFF" :background "#3366FF")
            ("SLEEP"    :foreground "#9999CC")))
 
    ;; (:foreground "#0000FF" :bold t)     ; default. do NOT put this bottom
    (setq org-tag-faces
          '(("Achievement" :foreground "#66CC66")
            ("Report"      :foreground "#66CC66")
            ("Background"  :foreground "#66CC99")
            ("Chore"       :foreground "#6699CC")
            ("Domestic"    :foreground "#6666CC")
            ("BeMerged"    :foreground "#6666CC")
            ("Doing"       :foreground "#FF0000")
            ("Review"      :foreground "#6633CC")
            ("Revisit"     :foreground "#6633CC")
            ("Redmine"     :foreground "#CC6666")
            ("Ongoing"     :foreground "#CC6666") ; for non scheduled/reminder
            ("Repeat"      :foreground "#CC9999") ; for interval tasks
            ("Mag"         :foreground "#9966CC")
            ("buy"         :foreground "#9966CC")
            ("pay"         :foreground "#CC6699")
            ("secret"      :foreground "#FF0000")
            ("emacs"       :foreground "#6633CC")
            ("note"        :foreground "#6633CC")
            ("print"       :foreground "#6633CC")
            ("Study"       :foreground "#6666CC")
            ("Implements"  :foreground "#CC9999" :weight bold)
            ("Coding"      :foreground "#CC9999")
            ("Editing"     :foreground "#CC9999" :weight bold)
            ("work"        :foreground "#CC9999" :weight bold)
            ("Survey"      :foreground "#CC9999" :weight bold)
            ("Home"        :foreground "#CC9999" :weight bold)
            ("Open"        :foreground "#CC9999" :weight bold)
            ("Blog"        :foreground "#9966CC")
            ("Test"        :foreground "#FF0000" :weight bold)
            ("Attach"      :foreground "#FF0000" :underline t :weight bold)
            ("drill"       :foreground "#66BB66" :underline t)
            ("DEBUG"       :foreground "#FFFFFF" :background "#9966CC")
            ("EVENT"       :foreground "#FFFFFF" :background "#9966CC")
            ("Thinking"    :foreground "#FFFFFF" :background "#96A9FF")
            ("Schedule"    :foreground "#FFFFFF" :background "#FF7D7D")
            ("INPUT"       :foreground "#FFFFFF" :background "#CC6666")
            ("OUTPUT"      :foreground "#FFFFFF" :background "#66CC99")
            ("CYCLE"       :foreground "#FFFFFF" :background "#6699CC")
            ("weekend"     :foreground "#FFFFFF" :background "#CC6666")
            ("Log"         :foreground "#008500"))))
  ;;#5BDF8D

TODOキーワードのカスタマイズ

キーワードには日本語も使えます.

  (with-eval-after-load "org"
    (setq org-todo-keywords
          '((sequence "TODO(t)" "PLAN(p)" "PLAN2(P)" "|" "DONE(d)")
            (sequence "READ(r)" "EDIT(e)" "|" "DONE(d)")
            (sequence "CHECK(C)" "FOCUS(f)" "ICAL(c)"  "|" "DONE(d)")
            (sequence "WAIT(w)" "SLEEP(s)" "QUESTION(q)" "|" "DONE(d)")
            (sequence "REV1(1)" "REV2(2)" "REV3(3)" "|" "APPROVED(a)")))
 
    ;; Global counting of TODO items
    (setq org-hierarchical-todo-statistics nil)
    ;; Global counting of checked TODO items
    (setq org-hierarchical-checkbox-statistics nil)
 
    ;; block-update-time
    (defun org-dblock-write:block-update-time (params)
      (let ((fmt (or (plist-get params :format) "%Y-%m-%d")))
        (insert "" (format-time-string fmt (current-time)))))
 
    ;; すべてのチェックボックスの cookies を更新する
    (defun do-org-update-statistics-cookies ()
      (interactive)
      (org-update-statistics-cookies 'all)))

ImageMagick を使って様々な画像をインライン表示する

システムに OpenJPEG と ImageMagick がインストールされていれば,JPEG 2000 などの画像形式もバッファに表示できます.

(with-eval-after-load "org"
  (setq org-image-actual-width 256)
  (add-to-list 'image-file-name-extensions "jp2")
  ;; (add-to-list 'image-file-name-extensions "j2c")
  (add-to-list 'image-file-name-extensions "bmp")
  (add-to-list 'image-file-name-extensions "psd"))

次の例では,同じ画像を2度インライン表示しようと指定ますが,前者は横幅が128ピクセルで表示され,後者は org-image-actual-width で指定した256ピクセルで表示されます.

[[~/Desktop/lena_std.jp2]]
 
[[~/Desktop/lena_std.jp2]]
(org-toggle-inline-images)

[org-agenda] タスク/予定管理

  (with-eval-after-load "org-agenda"
    ;; sorting strategy
    (setq org-agenda-sorting-strategy
          '((agenda habit-down time-up timestamp-up priority-down category-keep)
            (todo priority-down category-keep)
            (tags priority-down category-keep)
            (search category-keep)))
    ;; Set the view span as day in an agenda view, the default is week
    (setq org-agenda-span 'day)
    ;; アジェンダに警告を表示する期間
    (setq org-deadline-warning-days 0)
    ;; 時間幅が明示的に指定されない場合のデフォルト値(分指定)
    (setq org-agenda-default-appointment-duration 60)
    ;; アジェンダビューでFOLLOWを設定
    ;; (setq org-agenda-start-with-follow-mode t)
    ;; Customized Time Grid
    (setq org-agenda-time-grid
          '((daily today require-timed)
            "----------------"
            (0800 1000 1200 1400 1600 1800 2000 2200 2400)))
    (setq org-agenda-current-time-string "< d('- ' ) now!")
    (setq org-agenda-timegrid-use-ampm t)
 
    ;; アジェンダ作成対象(指定しないとagendaが生成されない)
    ;; ここを間違うと,MobileOrg, iCal export もうまくいかない
    (setq org-agenda-files
          '("~/Dropbox/org/org-ical.org" "~/Dropbox/org/next.org"
            "~/Dropbox/org/trigger.org" "~/Dropbox/org/wg1.org"
            "~/Dropbox/org/work.org" "~/Dropbox/org/academic.org"))
 
    (add-hook 'org-finalize-agenda-hook
              #'(lambda () (org-agenda-to-appt t '((headline "TODO")))))
 
    ;; 移動直後にagendaバッファを閉じる(ツリーの内容はSPACEで確認可)
    (org-defkey org-agenda-mode-map [(tab)]
                #'(lambda () (interactive)
                    (org-agenda-goto)
                    (with-current-buffer "*Org Agenda*"
                      (org-agenda-quit))))
 
    (custom-set-faces
     ;; '(org-agenda-clocking ((t (:background "#300020"))))
     '(org-agenda-structure ((t (:underline t :foreground "#6873ff"))))
     '(org-agenda-date-today ((t (:weight bold :foreground "#4a6aff"))))
     '(org-agenda-date ((t (:weight bold :foreground "#6ac214"))))
     '(org-agenda-date-weekend ((t (:weight bold :foreground "#ff8d1e"))))
     '(org-time-grid ((t (:foreground "#0a4796"))))
     '(org-warning ((t (:foreground "#ff431a"))))
     '(org-upcoming-deadline ((t (:inherit font-lock-keyword-face))))
     )
 
    ;; 所定の時刻に強制的にAgendaを表示
    (defvar my:org-agenda-auto-popup-list
      '("01:00" "11:00" "14:00" "17:00" "20:00" "23:00"))
    (defun my:popup-agenda ()
      (interactive)
      (let ((status use-dialog-box))
        (setq use-dialog-box nil)
        (when (y-or-n-p-with-timeout "Popup agenda now?" 10 nil)
          (org-agenda-list))
        (message "")
        (setq use-dialog-box status)))
    (defun my:popup-agenda-set-timers ()
      (interactive)
      (cancel-function-timers 'my:popup-agenda)
      (dolist (triger my:org-agenda-auto-popup-list)
        (unless (passed-clock-p triger)
          (run-at-time triger nil 'my:popup-agenda))))
    (my:popup-agenda-set-timers)
    (run-at-time "24:00" nil 'my:popup-agenda-set-timers)) ;; for next day
 
  (with-eval-after-load "org"
 
    (define-key org-mode-map (kbd "<f11>") 'my:toggle-doing-tag)
    (define-key org-mode-map (kbd "C-<f11>") 'my:sparse-doing-tree)
 
    ;; 特定タグを持つツリーリストを一発移動(org-tags-view, org-tree-slide)
    (defvar my:doing-tag "Doing")
    (defun my:sparse-doing-tree ()
      (interactive)
      (org-tags-view nil my:doing-tag))
    ;; Doingタグをトグルする
    (defun my:toggle-doing-tag ()
      (interactive)
      (when (eq major-mode 'org-mode)
        (save-excursion
          (save-restriction
            (org-back-to-heading t)
            ;; before 9
            ;; (unless (org-at-heading-p)
            ;;   (outline-previous-heading))
            (org-toggle-tag my:doing-tag
                            (if (string-match
                                 (concat ":" my:doing-tag ":")
                                 (org-get-tags-string))
                                'off 'on))
            (org-set-tags nil t)))
        (org-reveal)))
 
    ;; ついでに calendar.app も定期的に強制起動する
    (defun my:popup-calendar ()
      (interactive)
      (if (window-focus-p)
          (shell-command-to-string "open -a calendar.app")
        (message "--- input focus is currently OUT.")))
    (defun my:popup-calendar-set-timers ()
      (interactive)
      (cancel-function-timers 'my:popup-calendar)
      (dolist (triger my:org-agenda-auto-popup-list)
        (unless (passed-clock-p triger)
          (run-at-time triger nil 'my:popup-calendar))))
    (when (memq window-system '(mac ns))
      (my:popup-calendar-set-timers)
      (run-at-time "24:00" nil 'my:popup-calendar-set-timers))) ;; for next day

TODO [orgbox.el] スケジュール追加のわかりやすい入力

C-c C-s をオーバーライドして orgbox-schedule を実行する.

(with-eval-after-load "org"
  (require 'orgbox nil t))

TODO [org-review.el] レビューフローのサポート

(with-eval-after-load "org-agenda"
  (when (require 'org-review nil t)
    (add-to-list 'org-agenda-custom-commands
                 '("r" "Review projects" tags-todo "-CANCELLED/"
                   ((org-agenda-overriding-header "Reviews Scheduled")
                    (org-agenda-skip-function 'org-review-agenda-skip)
                    (org-agenda-cmp-user-defined 'org-review-compare)
                    (org-agenda-sorting-strategy '(user-defined-down)))))
    (org-defkey org-agenda-mode-map "\C-c\C-r"
                'org-review-insert-last-review)))

[appt.el] アラーム設定

  • Growl や Terminal Notifier と連携していると,Emacsがバックグラウンドにあってもアラームに気づける.
  (with-eval-after-load "org"
    ;; アラーム表示を有効にする
    (appt-activate 1)
    ;; window を フレーム内に表示する
    (setq appt-display-format 'window)
    ;; window を継続表示する時間[s]
    (setq appt-display-duration 5)
    ;; ビープ音の有無
    (setq appt-audible nil)
    ;; 何分前から警告表示を開始するか[m]
    (setq appt-message-warning-time 30)
    ;; 警告表示開始から何分ごとにリマインドするか[m]
    (setq appt-display-interval 5)
    ;; モードラインにアラームを表示する
    (setq appt-display-mode-line t)
    ;; org-agenda の内容をアラームに登録する
    ;; 定期的に更新する
    (defun my:org-agenda-to-appt ()
      (interactive)
      (org-agenda-to-appt t '((headline "TODO"))))
    (run-with-idle-timer 500 t 'my:org-agenda-to-appt)
 
    (define-key org-mode-map (kbd "C-c f 3") 'my:org-agenda-to-appt))

[org-capture] 高速にメモを取る

  (when (autoload-if-found
         '(org-capture)
         "org-capture" nil t)
    (eval-when-compile
      (require 'org-capture nil t))
    (with-eval-after-load "org-capture"
      ;; 2010-06-13 の形式では,タグとして認識されない
      (defun get-current-date-tags () (format-time-string "%Y%m%d"))
      (setq org-default-notes-file (concat org-directory "next.org"))
      (defvar org-capture-words-notes-file (concat org-directory "words.org"))
      (defvar org-capture-notes-file (concat org-directory "note.org"))
      (defvar org-capture-academic-file (concat org-directory "academic.org"))
      (defvar org-capture-buffer-file (concat org-directory "buffer.org"))
      (defvar org-capture-today-file (concat org-directory "trigger.org"))
      (defvar org-capture-ical-file (concat org-directory "org-ical.org"))
      (defvar org-capture-article-file (concat org-directory "article.org"))
 
      ;; see org.pdf:p73
      (setq org-capture-templates
            `(("t" "TODO 項目を INBOX に貼り付ける" entry
               (file+headline ,org-default-notes-file "INBOX") "** TODO %?\n\t")
              ("a" "記事リストにエントリー" entry
               (file+headline ,org-capture-article-file "INBOX")
               "** READ %?\n\t")
              ("c" "同期カレンダーにエントリー" entry
               (file+headline ,org-capture-ical-file "Scheduled")
               "** TODO %?\n\t")
              ("d" "Doingタグ付きのタスクをInboxに投げる" entry
               (file+headline ,org-default-notes-file "INBOX")
               "** TODO %? :Doing:\n  - \n")
              ("l" "本日のチェックリスト" entry
               (file+headline ,org-capture-today-file "Today")
               "** FOCUS 本日のチェックリスト %T\n(起床時間の記録)[[http://www.hayaoki-seikatsu.com/users/takaxp/][早起き日記]] \n(朝食)\n  - [ ] %?\n(昼食)\n(帰宅/夕食)\n----\n(研究速報)\n  - [ ] \n")
              ("i" "アイディアを書き込む" entry (file+headline ,org-default-notes-file "INBOX")
               "** %?\n  - \n\t%U")
              ("b" "Bug タグ付きの TODO 項目を貼り付ける" entry
               (file+headline ,org-default-notes-file "INBOX")
               "** TODO %? :bug:\n %i\n %a %t")
              ("w" ,(concat "英単語を " org-capture-words-notes-file
                            " に書き込む") entry
                            (file+headline ,org-capture-words-notes-file "WORDS")
                            "** %? :%(get-current-date-tags):\n「」\n  - ")
              ("g" ,(concat "英語ノートを " org-capture-words-notes-file
                            " に書き込む")
               entry (file+headline ,org-capture-words-notes-file "GRAMMER")
               "** %? :%(get-current-date-tags):\n\n%U")
              ("T" "時間付きエントリー" entry (file+headline ,org-default-notes-file "INBOX")
               "** %? %T--\n")
              ("n" "ノートとしてINBOXに貼り付ける" entry
               (file+headline ,org-default-notes-file "INBOX")
               "** %? :note:\n\t%U")
              ("D" "「ドラッカー365の金言」をノートする" entry
               (file+headline ,org-capture-notes-file "The Daily Drucker")
               "** 「%?」\nDrucker) \n  - \n  - \nACTION POINT:\n  - \nQUESTION:\n  - \n")
              ("r" ,(concat "研究ノートを " org-capture-academic-file
                            " に書き込む")
               entry (file+headline ,org-capture-academic-file "Survey")
               "** %? :note:\n# \n  - \n\t%U")
              ("`" ,(concat "ノートをバッファ " org-capture-buffer-file
                            " に書き込む")
               entry (file+headline ,org-capture-buffer-file "Buffers")
               "** %(get-random-string 16) %U\n\n%?\n\n----")))))

[org-refile] orgツリーの高速移動

# BUG サブツリーが一つもない場所に refile すると [0/1] などに更新されない…

  (with-eval-after-load "org"
    ;; 履歴が生成されるのを抑制.
    ;; [2/3]のような完了数が見出しにある時に転送先候補が重複するため.
 
    (defun advice:org-refile (&optional arg default-buffer rfloc msg)
      "Extension to support keeping org-refile-history empty."
      (let ((l (org-outline-level))
            (b (buffer-name)))
        (apply arg default-buffer rfloc msg)
        (save-excursion
          (save-restriction
            (if (> l (org-outline-level))
                (outline-backward-same-level 1)
              (outline-up-heading 1))
            (org-update-statistics-cookies nil) ;; Update in source
            (org-refile-goto-last-stored)
            (org-update-parent-todo-statistics) ;; Update in destination
            (unless (equal b (buffer-name))
              (switch-to-buffer b))))
        )
      (setq org-refile-history nil)
      (org-refile-cache-clear))
    (advice-add 'org-refile :around #'advice:org-refile)
 
    (setq org-refile-targets
          (quote (("org-ical.org" :level . 1)
                  ("academic.org" :level . 1)
                  ("maybe.org" :level . 1)
                  ("article.org" :level . 1)
                  ("work.org" :level . 1)
                  ("english.org" :level . 1)
                  ("wg1.org" :level . 1)
                  ("univ.org" :level . 1)
                  ("trigger.org" :level . 1)
                  ("next.org" :level . 1)
                  ("sleep.org" :level . 1))))
    )

[org-babel] 基本設定

  (with-eval-after-load "ob-core"
    (setq org-confirm-babel-evaluate nil)
    (setq org-src-fontify-natively t)
    (setq org-src-tab-acts-natively t)
    ;; org-src-window-setup (current-window, other-window, other-frame)
    (setq org-src-window-setup 'current-window)
    (require 'ob-http nil t)
    (require 'ob-gnuplot nil t)
 
    ;; Add ":results output" after program name
    (org-babel-do-load-languages
     'org-babel-load-languages
     '((dot . t)
       (C . t)
       (gnuplot . t)
       (perl . t)
       (shell . t)
       (latex . t)
       (sqlite . t)
       (R . t)
       (python . t)))
    ;; (require 'ob-C nil t)
    ;; (require 'ob-perl nil t)
    ;; (require 'ob-sh nil t)
    ;; (require 'ob-python nil t)
 
    ;; 実装済みの言語に好きな名前を紐付ける
    (add-to-list 'org-src-lang-modes '("cs" . csharp))
    (add-to-list 'org-src-lang-modes '("zsh" . sh)))

[org-babel] ソースブロックの入力キーをカスタマイズ

ソースブロックを入力するときは, <+ TAB でテンプレートを高速に入力できます.しかし,利用する言語までは指定できないので,特定の内容について対応するコマンドを割り当てて起きます.以下の例を設定として追加すると, <S+ TABemacs-lisp を, <C+ TAB でコメントブロックを指定できます.

(with-eval-after-load "org"
  (add-to-list 'org-structure-template-alist
               '("C" "#+BEGIN_COMMENT\n?\n#+END_COMMENT" ""))
  (add-to-list 'org-structure-template-alist
               '("S" "#+BEGIN_SRC emacs-lisp\n?\n#+END_SRC" "<src lang=\"emacs-lisp\">\n\n</src>")))

[MobileOrg] iOS との連携

http://orgmode.org/manual/Setting-up-the-staging-area.html

  (with-eval-after-load "org"
    ;;(setq org-mobile-files '("~/Dropbox/org/next.org" "1.org" "2.org"))
    (setq org-mobile-files '("~/Dropbox/org/next.org"))
    ;;(setq org-mobile-force-id-on-agenda-items nil)
 
    ;; Set a file to capture data from iOS devices
    (setq org-mobile-inbox-for-pull (concat org-directory "captured.org"))
 
    ;; Upload location stored org files (index.org will be created)
    (setq org-mobile-directory "~/Dropbox/Apps/MobileOrg/")
 
  ;;; Menu to push or pull org files using MobileOrg
    (defun org-mobile-sync ()
      (interactive)
      (let
          (org-mobile-sync-type
           (read-from-minibuffer "How do you sync the org files? (pull or push) "))
        (message "%s" org-mobile-sync-type)
        (cond
         ((string= "pull" org-mobile-sync-type) (org-mobile-pull))
         ((string= "push" org-mobile-sync-type) (org-mobile-push))))))

[org-tree-slide] Org でプレゼンテーション

  ;; (require 'use-package nil t)
  ;; (use-package org-tree-slide
  ;;   :bind (("<f8>" . org-tree-slide-mode)
  ;;          ("S-<f8>" . org-tree-slide-skip-done-toggle))
  ;;   :defer t
  ;;   :init
  ;;   :config
  ;;   (define-key org-tree-slide-mode-map (kbd "<f9>")
  ;;     'org-tree-slide-move-previous-tree)
  ;;   (define-key org-tree-slide-mode-map (kbd "<f10>")
  ;;     'org-tree-slide-move-next-tree)
  ;;   (org-tree-slide-narrowing-control-profile)
  ;;   (setq org-tree-slide-modeline-display 'outside)
  ;;   (setq org-tree-slide-skip-outline-level 5)
  ;;   (setq org-tree-slide-skip-done nil))
 
  (when (autoload-if-found
         '(org-tree-slide-mode)
         "org-tree-slide" nil t)
    (eval-when-compile
      (require 'org-tree-slide nil t))
    (with-eval-after-load "org-tree-slide"
      ;; <f8>/<f9>/<f10>/<f11> are assigned to control org-tree-slide
      (define-key org-tree-slide-mode-map (kbd "<f9>")
        'org-tree-slide-move-previous-tree)
      (define-key org-tree-slide-mode-map (kbd "<f10>")
        'org-tree-slide-move-next-tree)
      (org-tree-slide-narrowing-control-profile)
      (setq org-tree-slide-modeline-display 'outside)
      (setq org-tree-slide-skip-outline-level 5)
      (setq org-tree-slide-skip-done nil))
 
    (global-set-key (kbd "<f8>") 'org-tree-slide-mode)
    (global-set-key (kbd "S-<f8>") 'org-tree-slide-skip-done-toggle))

Doing タグのトグルに f11 を割り当てたので,コンテンツモードへの切り替えは,異なるキーバインドに変更.

[org-tree-slide] クロックインとアウトを自動化する

特定のファイルを編集している時, org-tree-slide でフォーカスしたら org-clock-in で時間計測を始めて,ナローイングを解く時や次のツリーに移る時に org-clock-out で計測を停止するように設定しています.基本的に org-tree-slide にあるhookに色々とぶら下げるだけです.

  (with-eval-after-load "org-tree-slide"
    (defun my:org-clock-in ()
      (setq vc-display-status nil) ;; モードライン節約
      (org-clock-in))
 
    (defun my:org-clock-out ()
      (setq vc-display-status t) ;; モードライン節約解除
      (require 'org-clock nil t)
      (when (org-clocking-p) (org-clock-out)))
 
    (add-hook 'org-tree-slide-before-move-previous-hook
              'my:org-clock-out)
    (add-hook 'org-tree-slide-before-move-next-hook
              'my:org-clock-out)
    (add-hook 'org-tree-slide-stop-hook 'my:org-clock-out)
 
    (add-hook 'org-tree-slide-before-narrow-hook
              #'(lambda ()
                  (when
                      (and (member (buffer-name) '("work.org" "effort.org"))
                           (and (memq (org-outline-level) '(2 3))
                                (looking-at (concat "^\\*+ "
                                                    org-not-done-regexp))))
                    (my:org-clock-in)))))

[org-tree-slide] 特定のツリーをプロポーショナルフォントで表示する

ツリーのプロパティに,プロポーショナルで表示するか否かの制御フラグを加えます.ツリーにフォーカス時にPROPORTIONAL指定がプロパティにあると,そのツリーを動的にプロポーショナルフォントでレンダリングします.変更は下位ツリーの全てに継承しています.

  (when (autoload-if-found
         '(org-tree-slide-mode my:proportional-font-toggle)
         "org-tree-slide" nil t)
    (eval-when-compile
      (require 'org-tree-slide nil t))
    (with-eval-after-load "org-tree-slide"
      (defcustom use-proportional-font nil
        "The status of FONT property"
        :type 'boolean
        :group 'org-mode)
 
      (set-face-attribute 'variable-pitch nil
                          :family "Verdana"
                          ;; :family "Comic Sans MS"
                          :height 125)
 
      (defun my:proportional-font-toggle ()
        (interactive)
        (setq use-proportional-font (not use-proportional-font))
        (if use-proportional-font
            (org-entry-put nil "FONT" "PROPORTIONAL")
          (org-delete-property "FONT")))
 
      (add-hook 'org-tree-slide-before-narrow-hook
                #'(lambda ()
                    (if (equal "PROPORTIONAL"
                               (org-entry-get-with-inheritance "FONT"))
                        (buffer-face-set 'variable-pitch)
                      (buffer-face-mode 0))))
      (add-hook 'org-tree-slide-stop-hook
                #'(lambda ()
                    (buffer-face-mode 0))))
 
    (with-eval-after-load "org"
      (define-key org-mode-map (kbd "C-c f p") 'my:proportional-font-toggle)))

[org-tree-slide] ヘッドラインをリッチにする

org-tree-slide が有効な時だけ org-bullets を有効にして,ヘッドラインをリッチにします.元ネタは, org-beautify-theme.el です.

(when (eval-after-autoload-if-found
       '(org-bullets-mode) "org-bullets" nil t)
  (add-hook 'org-tree-slide-play-hook #'(lambda () (org-bullets-mode 1)))
  (add-hook 'org-tree-slide-stop-hook #'(lambda () (org-bullets-mode -1))))

TODO [org-tree-slide] BEGIN_SRCとEND_SRCを消して背景色を変える

hide-lines.el を使うことで,プレゼン時に BEGIN_SRCENC_SRC を非表示にしてすっきりさせます.さらに,ソースブロックの背景色を変えます(以下の例では, emacs-lisp を言語で指定している場合に限定).

  (when (autoload-if-found
         '(org-tree-slide-mode)
         "org-tree-slide" nil t)
    (eval-when-compile
      (require 'org-tree-slide nil t))
    (with-eval-after-load "org-tree-slide"
      ;; FIXME 複数のバッファで並行動作させるとおかしくなる.hide-lines の問題?
      (when (and nil (require 'hide-lines nil t))
        (defvar my:org-src-block-faces nil)
        (defun my:show-headers ()
          (setq org-src-block-faces 'my:org-src-block-faces)
          (hide-lines-show-all))
        (defun my:hide-headers ()
          (setq my:org-src-block-faces 'org-src-block-faces)
          (setq org-src-block-faces
                '(("emacs-lisp" (:background "cornsilk"))))
          (hide-lines-matching "#\\+BEGIN_SRC")
          (hide-lines-matching "#\\+END_SRC"))
        (add-hook 'org-tree-slide-play-hook 'my:hide-headers)
        (add-hook 'org-tree-slide-stop-hook 'my:show-headers)
 
        ;; (defun advice:org-edit-src-code (&optional code edit-buffer-name)
        (defun advice:org-edit-src-code ()
          (interactive)
          (my:show-headers))
        (advice-add 'org-edit-src-code :before #'advice:org-edit-src-code)
        ;; Block 外で呼ばれると,my:show-headers が呼ばれてしまう
        (defun advice:org-edit-src-exit ()
          (interactive)
          (my:hide-headers))
        (advice-add 'org-edit-src-exit :after #'advice:org-edit-src-exit))))

TODO [org-fstree] ディレクトリ構造を読み取る

(with-eval-after-load "org"
  (require 'org-fstree nil t))

[calfw-org] calfw に org の予定を表示する

org-mode の表のようにフェイスを統一しています. calfw を起動する時に,自動的にフレームサイズを拡大するような独自関数をぶら下げています.

  (when (autoload-if-found
         '(my:cfw-open-org-calendar cfw:open-org-calendar)
         "calfw-org" "Rich calendar for org-mode" t)
    (eval-when-compile
      (require 'calfw-org nil t))
    (with-eval-after-load "calfw-org"
      ;; icalendar との連結
      (setq cfw:org-icalendars '("~/Dropbox/org/org-ical.org"))
 
      ;; org で使う表にフェイスを統一
      (setq cfw:fchar-junction ?+
            cfw:fchar-vertical-line ?|
            cfw:fchar-horizontal-line ?-
            cfw:fchar-left-junction ?|
            cfw:fchar-right-junction ?|
            cfw:fchar-top-junction ?+
            cfw:fchar-top-left-corner ?|
            cfw:fchar-top-right-corner ?| )
 
      (defun my:org-mark-ring-goto-calfw ()
        (interactive)
        (org-mark-ring-goto))
 
      (defun my:cfw-open-org-calendar ()
        (interactive)
        (moom-change-frame-width-double)
        (cfw:open-org-calendar))
 
      (defun my:cfw-burry-buffer ()
        (interactive)
        (bury-buffer)
        (moom-change-frame-width-single))
 
      (defun cfw:org-goto-date ()
        "Move the cursor to the specified date."
        (interactive)
        (cfw:navi-goto-date
         (cfw:emacs-to-calendar (org-read-date nil 'to-time))))
 
      (define-key cfw:calendar-mode-map (kbd "j") 'cfw:org-goto-date)
      (define-key cfw:org-schedule-map (kbd "q") 'my:cfw-burry-buffer))
 
    (global-set-key (kbd "C-c f c w") 'my:cfw-open-org-calendar))
 
  ;;         (add-hook 'window-configuration-change-hook 'cfw:resize-calendar)
  ;; (defun cfw:resize-calendar ()
  ;;   (interactive)
  ;;   (when (eq major-mode 'cfw:calendar-mode)
  ;;     (cfw:refresh-calendar-buffer nil)
  ;;     (message "Calendar resized.")))
 
  ;; (defun open-calfw-agenda-org ()
  ;;   (interactive)
  ;;   (cfw:open-org-calendar))
 
  ;; (setq org-agenda-custom-commands
  ;;       '(("w" todo "FOCUS")
  ;;         ("G" open-calfw-agenda-org "Graphical display in calfw"))))))

[org-export-generic] エクスポート機能を拡張する

org-set-generic-type を使うことで,エクスポート機能を好みに拡張できる.contrib の中の org-export-generic.el が必要なので注意する.

(注意)次の設定は古い内容.動かないかもしれません.

  (with-eval-after-load "org"
    (org-set-generic-type
     "textile"
     '(:file-suffix
       ".textile"
       :key-binding ?T
       :title-format    "Title: %s\n\n"
       ;;   :date-format     "Date: %s\n"
       :date-export nil
       :toc-export      nil
       :author-export   nil
       :tags-export     nil
       :drawers-export  nil
       :date-export     t
       :timestamps-export  t
       :priorities-export  nil
       :todo-keywords-export t
       :body-line-fixed-format "\t%s\n"
                                          ;:body-list-prefix "\n"
       :body-list-format "* %s"
       :body-list-suffix "\n"
       :body-bullet-list-prefix ("* " "** " "*** " "**** " "***** ")
       :body-number-list-format "# %s"
       :body-number-list-suffix "\n"
       :header-prefix ("" "" "### " "#### " "##### " "###### ")
       :body-section-header-prefix ("h1. " "h2. " "h3. " "h4. " "h5. " "h6. ")
       :body-section-header-format "%s"
       :body-section-header-suffix ("\n\n")
       :body-header-section-numbers nil
       :body-header-section-number-format "%s) "
       :body-line-format "%s\n"
       :body-newline-paragraph "\n"
       :bold-format "*%s*"
       :italic-format "_%s_"
       :underline-format "+%s+"
       :strikethrough-format "-%s-"
       :verbatim-format "`%s`"
       :code-format "@%s@"
       :body-line-wrap   75
       :blockquote-start "\n<pre>\n"
       :blockquote-end "\n</pre>\n"
       ))
 
    (org-set-generic-type
     "markdown" 
     '(:file-suffix
       ".markdown"
       :key-binding     ?M
       :title-format    "Title: %s\n"
       :date-format     "Date: %s\n"
       :toc-export      nil
       :author-export   t
       :tags-export     nil
       :drawers-export  nil
       :date-export     t
       :timestamps-export  t
       :priorities-export  nil
       :todo-keywords-export t
       :body-line-fixed-format "\t%s\n"
       ;;:body-list-prefix "\n"
       :body-list-format "- %s"
       :body-list-suffix "\n"
       :header-prefix ("" "" "### " "#### " "##### " "###### ")
       :body-section-header-prefix ("" "" "### " "#### " "##### " "###### ")
       :body-section-header-format "%s\n"
       :body-section-header-suffix (?= ?- "")
       :body-header-section-numbers nil
       :body-header-section-number-format "%s) "
       :body-line-format "%s\n"
       :body-newline-paragraph "\n"
       :bold-format "**%s**"
       :italic-format "_%s_"
       :verbatim-format "`%s`"
       :code-format "`%s`"
       :body-line-wrap   75
       )))

org-set-generic-type.emacs に追記した後, C-c C-e g とすればよい. org-set-generic-type で設定する値である.2つ目は,Markdown へのエクスポーターである.

TODO [ox] 出力形式の拡張

(with-eval-after-load "ox"
  (require 'ox-pandoc nil t)
  (require 'ox-qmd nil t) ;; Quita-style
  (require 'ox-gfm nil t)) ;; Github-style

[org-odt] ODT形式に出力

(when (autoload-if-found
       '(ox-odt)
       "ox-odt" nil t)
  (with-eval-after-load "ox-odt"
    (add-to-list 'org-odt-data-dir
                 (concat (getenv "HOME") "/Dropbox/emacs.d/config/"))
    (setq org-odt-styles-file
          (concat (getenv "HOME") "/Dropbox/emacs.d/config/style.odt"))
    ;; (setq org-odt-content-template-file
    ;;       (concat (getenv "HOME") "/Dropbox/emacs.d/config/style.ott"))
    (setq org-odt-preferred-output-format "pdf") ;; docx
    ;; ox-odt.el の 自作パッチの変数(DOCSTRINGが記述されていない)
    (setq org-odt-apply-custom-punctuation t)
    (setq org-odt-convert-processes
          '(("LibreOffice"
             "/Applications/LibreOffice.app/Contents/MacOS/soffice --headless --convert-to %f%x --outdir %d %i")
            ("unoconv" "unoconv -f %f -o %d %i")))))

[ox-twbs] Twitter Bootstrap 互換のHTML出力

[org-crypt] ツリーを暗号化する

M-x org-encrypt-entry でカーソル位置のツリーを暗号化できます.復号は, M-x org-decrypt-entry にて.ただし,バッファのバックアップファイルが生成されていることに気をつけてください.自分の場合は,バックアップファイルは外部ホストに同期されない設定にしてあるので,とりあえず問題なしと考えています.

M-x org-encrypt-entries で,特定のタグが付けられたツリーを一括処理することもできますが,私は安全性を考慮して使っていません.

なお,実戦投入には十分なテストをしてからの方がよいでしょう.org バッファを外部ホストと同期している場合,転送先のホストでも暗号化/復号ができるかを確認するべきです.他方のホストでツリーにドロワーが付くと,復号できなくなったりします.その時は慌てずにプロパティのドロワーを削除すればOKです.

(with-eval-after-load "org"
  (when (require 'org-crypt nil t)
    (setq org-crypt-key "<insert your key>")
    ;; org-encrypt-entries の影響を受けるタグを指定
    (setq org-tags-exclude-from-inheritance (quote ("secret")))
    ;; 自動保存の確認を無効に
    (setq org-crypt-disable-auto-save 'nil)
    (define-key org-mode-map (kbd "C-c f c e") 'org-encrypt-entry)
    (define-key org-mode-map (kbd "C-c f c d") 'org-decrypt-entry)))

org-mac-link を使うと,外部アプリの表示状態をリンクとして取得して,orgバッファに流し込めます.Mac環境用です.簡単な例ではURLで,取得したリンクを C-c C-o で開けばブラウザが起動してリンク先が表示できます.同じ話を,ファインダーで表示しているディレクトリ,メーラーで表示していた特定のメール,PDFビューアで表示していた特定のファイルの特定のページなどで実施できます.対応している外部アプリは,Finder, Mail.app, Outlook, Addressbook, Safari, Firefox, Chrome, そして Skimです.

次のように設定すると,org-modeの時に C-c c すればミニバッファにどのアプリからリンク情報を取るか選べます.Chrome には c が当たっているので,ブラウジング中に記になる記事があったらEmacsに切り替えて, C-c c c とすると,URLが自動でバッファに入ります.単なるURLではなく,タイトルで表示されるのでわかりやすいです.

(with-eval-after-load "org"
  (add-to-list 'org-modules 'org-mac-iCal)
  (add-to-list 'org-modules 'org-mac-link) ;; includes org-mac-message
  (define-key org-mode-map (kbd "C-c c") 'org-mac-grab-link))

TODO Parers3.app からリンクを取得する

  (with-eval-after-load "org-mac-link"
    (defcustom org-mac-grab-Papers-app-p t
      "Add menu option [P]apers to grab links from the Papers.app."
      :tag "Grab Papers.app links"
      :group 'org-mac-link
      :type 'boolean)
 
    (defun org-mac-papers-insert-frontmost-paper-link ()
      (interactive)
      (let ((result (org-mac-papers-get-frontmost-paper-link)))
        (if result
            (insert result)
          (message "Please open Papers.app and select a paper."))))
 
    (defun org-mac-papers-get-frontmost-paper-link ()
      (interactive)
      (message "Applescript: Getting Papers link...")
      (let ((result (org-as-mac-papers-get-paper-link)))
        (if (or (eq result nil) (string= result ""))
            nil
          (org-mac-paste-applescript-links result))))
 
    (defun org-as-mac-papers-get-paper-link ()
      (do-applescript
       (concat
        "if application \"Papers\" is running then\n"
        "	tell application \"Papers\" to activate\n"
        "	delay 0.3\n"
        "	set the clipboard to \"\"\n"
        "	tell application \"System Events\" to tell process \"Papers\"\n"
        "		keystroke \"l\" using {command down, shift down}\n"
        "	end tell\n"
        "	delay 0.2\n"
        "	set aLink to the clipboard\n"
        "	tell application \"System Events\" to tell process \"Papers\"\n"
        ;; "		keystroke \"c\" using {command down, alt down\}\n"
        "		keystroke \"m\" using {command down, option down\}\n"
        "	end tell\n"
        "	delay 0.2\n"
        "	set aName to the clipboard\n"
        "	tell application \"Emacs\" to activate\n"
        "	return (get aLink) & \"::split::\" & (get aName) as string\n"
        "else\n"
        "	return\n"
        "end if\n"))
 
      (add-to-list 'org-mac-link-descriptors
                   `("P" "apers" org-mac-papers-insert-frontmost-paper-link
                     ,org-mac-grab-Papers-app-p) t)))

TODO Papers3.app のリンクを開けるようにする

Papers3.app は,各文献に papers3:// で始まるURIを割り当てています.このリンクを org バッファにペーストし, org-open-at-point (C-c C-o) で開けるようにします.

(with-eval-after-load "org"
  (when (eq system-type 'darwin)
    ;; Open `papers3://' link by C-c C-o.
    ;; (org-add-link-type will be obsoleted from Org 9.
    (org-link-set-parameters
     "papers3"
     :follow (lambda (path)
               (let ((cmd (concat "open papers3:" path)))
                 (shell-command-to-string cmd)
                 (message "%s" cmd))))))

TODO [org-attach] 外部ファイルを紐付ける

  (when (autoload-if-found
         '(org-attach du-org-attachments)
         "org-attach" nil t)
    (eval-when-compile
      (require 'org-attach nil t))
    (with-eval-after-load "org-attach"
      ;; org-insert-link で添付ファイルへのリンクをペーストできるようにする
      (setq org-attach-store-link-p t)
      ;; 自動付与されるタグの名前を変更
      (setq org-attach-auto-tag "Attach")
      ;; git-annex を使用しない
      (setq org-attach-git-annex-cutoff nil)
 
      (defvar org-attach-directory-absolute
        (concat (getenv "HOME")
                "/Dropbox/org/"
                (if (boundp 'org-attach-directory)
                    "data/")))
 
      (defun du-org-attachments ()
        "Show directory size for org-attachments."
        (interactive)
        (message "--- %s"
                 (chomp (shell-command-to-string
                         (concat "/usr/bin/du -sh "
                                 org-attach-directory-absolute)))))))

TODO [org-screenshot] スクリーンショットを貼り付ける

(How?)

  • [ ] 所定のウィンドウだけをキャプチャする方法
  • [ ] Emacs バッファを抜いてキャプチャする方法
  • [ ] Emacs だけキャプチャする方法
  (when (autoload-if-found
         '(org-attach-screenshot my:org-attach-screenshot)
         "org-attach-screenshot" nil t)
    (eval-when-compile
      (require 'org-attach-screenshot nil t))
    (with-eval-after-load "org-attach-screenshot"
      (when (executable-find "screencapture")
        (setq org-attach-screenshot-command-line "screencapture %f"))
      (defun my:org-attach-screenshot ()
        (interactive)
        (org-attach-screenshot t "")))
 
    (with-eval-after-load "org"
      (define-key org-mode-map (kbd "C-c f <f12>") 'my:org-attach-screenshot)))

[terminal-notifier] イベント通知

Mac の通知機能を使って,Emacsで発生するイベントをユーザに通知します. appt-disp-window をカスタマイズして org-notify を呼ぶことで, org-agenda のアイテムも通知されます.

org-show-notification-handlerterminal-notifier.app を呼ぶ関数をぶら下げることで, org-notify で簡単に通知機能を使えるようになります.

terminal-notifier-soundterminal-notifier.app で指定可能な音声ファイル名を指定すると,通知音を制御できます.

  (when (executable-find "terminal-notifier")
    (defun terminal-notifier-notify (title message &optional sound)
      "Show a message with `terminal-notifier-command`."
      (start-process "terminal-notifier" "*terminal-notifier*"
                     terminal-notifier-command
                     "-title" title "-message" message
                     "-activate" "org.gnu.Emacs"
                     (if (and sound (not (string= sound ""))) "-sound" "")
                     (if (and sound (not (string= sound ""))) sound ""))))
 
  (with-eval-after-load "org"
    (defvar terminal-notifier-command
      (executable-find
       "terminal-notifier.app/Contents/MacOS/terminal-notifier")
      "Path to terminal-notifier.
     Download from https://github.com/julienXX/terminal-notifier/releases")
    (defvar terminal-notifier-sound nil)
    (with-eval-after-load "org-clock"
      (when (not org-clock-sound)
        ;; Select from Preferences: { Funk | Glass | ... | Purr | Pop ... }
        (setq terminal-notifier-sound "Pop")))
 
    (defvar use-terminal-notifier t)
    (defun terminal-notifier-toggle ()
      (interactive)
      (setq use-terminal-notifier (not use-terminal-notifier))
      (my:org-agenda-to-appt)
      (message "terminal-notifier: %s" use-terminal-notifier))
 
    ;; eval (org-notify "hoge") to test this setting
    (setq org-show-notification-handler
          #'(lambda (message)
              (when use-terminal-notifier
                (terminal-notifier-notify
                 "Message from org-mode" message terminal-notifier-sound))))
 
    (defun advice:appt-disp-window (min-to-app new-time appt-msg)
      "Extension to support org-notify."
      (let ((time-msg (concat "in " min-to-app " min.")))
        (when (and (string= min-to-app "0") new-time) ;; for lexical argument
          (setq time-msg "<= Do Now!!"))
        (org-notify (concat "\\\"" appt-msg "\" " time-msg))))
    (advice-add 'appt-disp-window :before #'advice:appt-disp-window))

References

[org-grep] org ファイルを grep する

  (when (autoload-if-found
         '(org-grep)
         "org-grep" nil t)
    (eval-when-compile
      (require 'org-grep nil t))
    (with-eval-after-load "org-grep"
      (setq org-grep-extensions '(".org" ".org_archive"))
      (add-to-list 'org-grep-directories "~/.emacs.d")
      (add-to-list 'org-grep-directories "~/.emacs.d/.cask/package")
 
      ;; "q"押下の挙動を調整
      (defun org-grep-quit ()
        (interactive)
        (delete-window))
 
      ;; for MacOSX
      (when (memq window-system '(mac ns))
        (defun org-grep-from-org-shell-command (regexp)
          (if org-grep-directories
              (concat "find -E "
                      (if org-grep-directories
                          (mapconcat #'identity org-grep-directories " ")
                        org-directory)
                      (and org-grep-extensions
                           (concat " -regex '.*("
                                   (mapconcat #'regexp-quote org-grep-extensions "|")
                                   ")$'"))
                      " -print0 | xargs -0 grep " org-grep-grep-options
                      " -n -- " (shell-quote-argument regexp))
            ":"))))
 
    (global-set-key (kbd "C-M-g") 'org-grep))

[ox-reveal] ナイスなHTML5プレゼンテーション出力

C-c C-e R エクスポータを呼び出せます.続けて B を押せば,ブラウザで出力後の見た目を確認できます.ただし別途 reveal.js が使える状態にないとダメです. org-reveal-root を設定すれば,clone した reveal.js の場所を指定できます.

(with-eval-after-load "ox"
  (require 'ox-reveal nil t))

README を常に org-mode で開く

(when (autoload-if-found
       '(org-mode)
       "org" nil t)
  (push '("[rR][eE][aA][dD][mM][eE]" . org-mode) auto-mode-alist))

Growlnotify と org-mode でアラーム管理

(注)Growlnotify の代わりに terminal-notifier を使うこともできます.

growlnotify と org-mode のバッファを組み合わせてアラームリストを管理しています.アラームをorgバッファに書き込むだけなので,とても楽です.機能としては,特定のorgバッファに,時刻とアラームの内容を表の形式として保存しておくだけで,Emacs が起動している限りにおいて growl がそのアラームを表示してくれます.つまり,アラームリストは org-mode の表で一覧化されているので,管理も楽ですし,見た目もわかりやすいです.

アラームとして解釈される表は,オプション,時刻(HH:MM形式),アラーム内容の3列で構成していればOKです.オプションの列にXを入れておくと,growl がStickyモードで動作するので,アラームを見逃しません.

アラームは複数登録することができます.不要になったアラームを削除するのは,単純に表から当該の行を削除するだけで済みます.実際のところは,バッファが保存される時にアラームリストの変更が自動的にシステムに反映されるので,余計な作業は不要です.

set-alarms-from-file は,utility.elに記述した関数です.

  (with-eval-after-load "utility"
    (set-alarms-from-file "~/Dropbox/org/trigger.org"))
 
  (when (library-p "utility")
    (add-hook 'after-save-hook 'my:update-alarms-from-file))

キーバインド

  (with-eval-after-load "org"
    (defun my:do-org-update-staistics-cookies ()
      (interactive)
      (message "Update statistics ...")
      (do-org-update-statistics-cookies))
    ;; (org-transpose-element) が割り当てられているので取り返す.
    (org-defkey org-mode-map "\C-\M-t" 'beginning-of-buffer)
 
    ;;(define-key org-mode-map (kbd "C-c 1")
    ;;  'org-export-icalendar-combine-agenda-files)
    (define-key org-mode-map (kbd "C-c f 1") 'my:ox-icalendar)
    (define-key org-mode-map (kbd "C-c f 2")
      'my:do-org-update-staistics-cookies)
    (define-key org-mode-map (kbd "C-c m") 'org-mobile-sync)
    (define-key org-mode-map (kbd "<f5>") 'org-narrow-to-subtree)
    (define-key org-mode-map (kbd "S-<f5>") 'widen))
 
  (global-set-key (kbd "S-<f12>")
                  #'(lambda () (interactive) (show-org-buffer "work.org")))
  (global-set-key (kbd "C-M-o")
                  #'(lambda () (interactive) (show-org-buffer "next.org")))
  (global-set-key (kbd "C-M-c")
                  #'(lambda () (interactive) (show-org-buffer "org-ical.org")))
  (global-set-key (kbd "C-c l") 'org-store-link)
  (global-set-key (kbd "C-c a") 'org-agenda)
  (global-set-key (kbd "C-c r") 'org-capture)

org-mode の latex エクスポート関数をオーバーライド

;;; Tex export (org-mode -> tex with beamer class) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; (setq org-export-latex-classes
;;   '(("article"
;;      "\\documentclass[11pt]{article}
;; \\usepackage[AUTO]{inputenc}
;; \\usepackage[T1]{fontenc}
;; \\usepackage{graphicx}
;; \\usepackage{longtable}
;; \\usepackage{float}
;; \\usepackage{wrapfig}
;; \\usepackage{soul}
;; \\usepackage{amssymb}
;; \\usepackage{hyperref}"
;;      ("\\section{%s}" . "\\section*{%s}")
;;      ("\\subsection{%s}" . "\\subsection*{%s}")
;;      ("\\subsubsection{%s}" . "\\subsubsection*{%s}")
;;      ("\\paragraph{%s}" . "\\paragraph*{%s}")
;;      ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))
;;     ("report"
;;      "\\documentclass[11pt]{report}
;; \\usepackage[AUTO]{inputenc}
;; \\usepackage[T1]{fontenc}
;; \\usepackage{graphicx}
;; \\usepackage{longtable}
;; \\usepackage{float}
;; \\usepackage{wrapfig}
;; \\usepackage{soul}
;; \\usepackage{amssymb}
;; \\usepackage{hyperref}"
;;      ("\\part{%s}" . "\\part*{%s}")
;;      ("\\chapter{%s}" . "\\chapter*{%s}")
;;      ("\\section{%s}" . "\\section*{%s}")
;;      ("\\subsection{%s}" . "\\subsection*{%s}")
;;      ("\\subsubsection{%s}" . "\\subsubsection*{%s}"))
;;     ("book"
;;      "\\documentclass[11pt]{book}
;; \\usepackage[AUTO]{inputenc}
;; \\usepackage[T1]{fontenc}
;; \\usepackage{graphicx}
;; \\usepackage{longtable}
;; \\usepackage{float}
;; \\usepackage{wrapfig}
;; \\usepackage{soul}
;; \\usepackage{amssymb}
;; \\usepackage{hyperref}"
;;      ("\\part{%s}" . "\\part*{%s}")
;;      ("\\chapter{%s}" . "\\chapter*{%s}")
;;      ("\\section{%s}" . "\\section*{%s}")
;;      ("\\subsection{%s}" . "\\subsection*{%s}")
;;      ("\\subsubsection{%s}" . "\\subsubsection*{%s}"))
;;     ("beamer"
;;      "\\documentclass{beamer}
;; \\usepackage[AUTO]{inputenc}
;; \\usepackage{graphicx}
;; \\usepackage{longtable}
;; \\usepackage{float}
;; \\usepackage{wrapfig}
;; \\usepackage{amssymb}
;; \\usepackage{hyperref}"
;;      org-beamer-sectioning)))

[org-autolist] ブリッツの入力を簡単に

ブリッツの入力や削除を Microsoft Word 的にします.

(when (eval-after-autoload-if-found
       '(org-autolist-mode)
       "org-autolist" nil t nil nil)
  (add-hook 'org-mode-hook #'(lambda () (org-autolist-mode))))

TODO [org-dashboard] 進捗をプログレスバーで確認

(when (autoload-if-found
       '(org-dashboard-display)
       "org-dashboard" nil t)
  (with-eval-after-load "org"
    (define-key org-mode-map (kbd "C-c f y") 'org-dashboard-display)))

TODO [org-clock-today] 今日の総作業時間をモードラインに表示

(with-eval-after-load "org"
  (when (and (require 'org-clock-today nil t)
             (fboundp 'org-clock-today-mode))
    (add-hook 'org-mode-hook #'(lambda () (org-clock-today-mode 1)))))

TODO [org-recent-headings] 訪問したツリーを記録し簡単に再訪問可能にする

(with-eval-after-load "org"
  (when (require 'org-recent-headings nil t)
    (define-key org-mode-map (kbd "C-c f r") 'org-recent-headings-helm)
    (setq org-recent-headings-save-file "~/.emacs.d/org-recent-headings.dat")
    (if (require 'shut-up nil t)
        (shut-up (org-recent-headings-mode 1))
      (org-recent-headings-mode 1))))

TODO [orgnav] ツリーの検索インタフェース

(when (autoload-if-found
       '(orgnav-search-root)
       "orgnav" nil t)
  (with-eval-after-load "org"
    (define-key org-mode-map (kbd "C-c f n")
      #'(lambda () (interactive)
          (orgnav-search-root 3 'orgnav--goto-action)))))

TODO [org-random-todo] ランダムにタスクを選ぶ

(autoload-if-found
 '(org-random-todo org-random-todo-goto-current)
 "org-random-todo" nil t)

TODO [toc-org] 目次の挿入

  • ツリーに TOC タグを付けて,`toc-org-insert-toc'を実行すればOK
(autoload-if-found
 '(toc-org-insert-toc)
 "toc-org" nil t)

フレーム/ウィンドウ制御

起動時の設定

  (cond
   ((memq window-system '(mac ns)) ;; for Macintosh
    (setq initial-frame-alist
          (append
           `((vertical-scroll-bars . nil)
             (top . 22)  ; Y-pos from (0,0) the height of menu bar is 22pix.
             (left . 0)  ; X-pos from (0,0) ; 420 is the center for MBP
             ;; 26 is the setting for Butler's Docklet
             ;; 837 is the setting for right side for MBP
             (width . 80) ; Width  : character count
             (alpha . (100 90))) initial-frame-alist)))
   ;; for Linux
   ((eq window-system 'x)
    (setq initial-frame-alist
          (append
           '((vertical-scroll-bars . nil)
             (top . 0)
             (left . 0)
             (width . 80)
             (height . 38)
             ) initial-frame-alist)))
   ;; for Windows
   (t (setq initial-frame-alist
            (append
             '((vertical-scroll-bars . nil)
               (top . 0)
               (left . 0)
               (width . 80)
               (height . 26)
               ) initial-frame-alist))))
 
  ;; Apply the initial setting to default
  (setq default-frame-alist initial-frame-alist)
  (set-face-foreground 'vertical-border (face-background 'default))
  (set-face-background 'vertical-border (face-background 'default))
  ;; (set-face-background 'fringe (face-background 'default))
 
  ;; カーソルの色
  (defconst my:cursor-color-ime-on "#FF9300")
  (defconst my:cursor-color-ime-off "#91C3FF") ;; #FF9300, #999999, #749CCC
  (defconst my:cursor-type-ime-on '(bar . 2))
  (defconst my:cursor-type-ime-off '(bar . 2))
 
  (cond
   ((eq window-system 'ns)
    (when (fboundp 'mac-set-input-method-parameter)
      (mac-set-input-method-parameter
       "com.google.inputmethod.Japanese.base" 'title "あ"))
 
    (when (fboundp 'mac-get-current-input-source)
      (defun my:ime-active-p ()
        (not (string-match "\\.Roman$" (mac-get-current-input-source))))
      (defvar my:ime-on-hook nil)
      (defvar my:ime-off-hook nil)
      (defun my:ime-on ()
        (interactive)
        (mac-toggle-input-method t)
        (run-hooks 'my:ime-on-hook))
      (defun my:ime-off ()
        (interactive)
        (mac-toggle-input-method nil)
        (run-hooks 'my:ime-off-hook))
 
      ;; for init setup
      (setq-default cursor-type '(bar . 2))
      (my:ime-off)
      (setq cursor-type my:cursor-type-ime-off)
      (set-cursor-color my:cursor-color-ime-off)
 
      ;; (defun advice:find-file (FILENAME &optional WILDCARDS)
      ;;   "Extension to find-file as before-find-file-hook."
      ;;   (message "--- advice:findfile")
      ;;   (apply FILENAME WILDCARDS))
      ;; (advice-add #'find-file :around #'advice:find-file)
 
      ;; http://tezfm.blogspot.jp/2009/11/cocoa-emacs.html
      ;; バッファ切替時に input method を切り替える
      (with-eval-after-load "helm-config"
        (when (and (fboundp 'mac-handle-input-method-change)
                   (require 'cl-lib nil t))
          (add-hook
           'post-command-hook
           (lexical-let ((previous-buffer nil))
             ;; (message "Change IM %S -> %S" previous-buffer (current-buffer))
             #'(lambda ()
                 (unless (eq (current-buffer) previous-buffer)
                   (if (bufferp previous-buffer)
                       (mac-handle-input-method-change))
                   (setq previous-buffer (current-buffer))))))))))
 
   ((eq window-system 'mac) ;; EMP: Emacs Mac Port
    (when (fboundp 'mac-input-source)
      (defun my:mac-keyboard-input-source ()
        (if (string-match "\\.Roman$" (mac-input-source))
            (progn
              (setq cursor-type my:cursor-type-ime-off)
              (add-to-list 'default-frame-alist
                           `(cursor-type . ,my:cursor-type-ime-off))
              (set-cursor-color my:cursor-color-ime-off))
          (progn
            (setq cursor-type my:cursor-type-ime-on)
            (add-to-list 'default-frame-alist
                         `(cursor-type . ,my:cursor-type-ime-on))
            (set-cursor-color my:cursor-color-ime-on))))
 
      (when (fboundp 'mac-auto-ascii-mode)
        ;; (mac-auto-ascii-mode 1)
        ;; IME ON/OFF でカーソルの種別や色を替える
        (add-hook 'mac-selected-keyboard-input-source-change-hook
                  'my:mac-keyboard-input-source)
        ;; IME ON の英語入力+決定後でもカーソルの種別や色を替える
        ;; (add-hook 'mac-enabled-keyboard-input-sources-change-hook
        ;;           'my:mac-keyboard-input-source)
 
        (declare-function my:mac-keyboard-input-source "init" nil)
        (my:mac-keyboard-input-source))))
 
   (t nil))

[e2wm.el] 二画面表示

  (when (autoload-if-found
         '(my:e2wm:dp-two e2wm:dp-two e2wm:start-management)
         "e2wm" nil t)
    (eval-when-compile
      (require 'e2wm nil t))
    (with-eval-after-load "e2wm"
      (defun my:e2wm:dp-two ()
        (interactive)
        (e2wm:dp-two)
        (setq e2wm:c-two-recipe
              '(- (:lower-size 10)
                  (| left right)
                  sub))
        (setq e2wm:c-two-winfo
              '((:name left )
                (:name right )
                (:name sub :default-hide t)))
 
        ;; left, prev
        (setq e2wm:c-two-right-default 'left))
 
      ;; 高さを画面の最大に矯正
      (when (require 'moom nil t)
        (setq moom-frame-height-tall (moom-max-frame-height))
        (setq moom-frame-height-small moom-frame-height-tall))
 
      ;; 幅を画面の最大に矯正
      (add-hook 'e2wm:pre-start-hook
                #'(lambda ()
                    (set-frame-width
                     (selected-frame)
                     (/ (- (display-pixel-width) 30) (frame-char-width)))))
 
      ;; 幅をデフォルト値に戻す
      (add-hook 'e2wm:post-stop-hook
                #'(lambda ()
                    (set-frame-width (selected-frame) moom--target-frame-width)))
 
      ;; To avoid rebooting issue when using desktop.el and recentf.el
      (add-hook 'kill-emacs-hook
                #'(lambda ()
                    (when (fboundp 'e2wm:stop-management)
                      (e2wm:stop-management))))

[moom.el] キーボードでフレームの場所を移す

(2017-07-30) frame-ctr から moom.el にリネームしました.Moom は,Many Tricks がリリースするソフトウェアで,今後はこのソフトウェアのポートを目指します.

拙作の moom.el を使います.e2wm.el と frame-cmds.el に依存しています.

moom.el は,frame-cmds, frame-fns と e2wm.el を利用したアドホックなフレーム管理ツールです.

# 以下の設定は,標準のフォントサイズが12ptで,日本語フォントに Migu 2M,英字フォントにMonacoを使う場合の設定です.フォントサイズの「増加」「減少」「初期化」「サイズ指定」が可能です.

ビルトインに face-remap があり,アスキーフォントは C-x C--C-x C-= で拡大縮小を制御できます.以下のキーバインドは,face-remap.el が提供する text-scale-adjust のキーバインドを上書きします.text-scale-adjust をそのまま使うと,日本語フォントが制御されないので,オーバーライドしてしまってもOKだと思います.

近しいパッケージに, WindMoveFrameMove がありますが,基本的にカーソルの移動を目的にしています.

moom-autuloads に必要なコマンドを羅列していますが, melpa でインストールする場合は関係ありません.パッケージ内で autoload 指定してあります. with-eval-after-load の中だけを設定すれば十分です.

  (defconst moom-autoloads
    '(moom-move-frame-with-user-specify
      moom-change-frame-width-single moom-change-frame-width-double
      moom-move-frame-to-center moom-move-frame-to-edge-top
      moom-move-frame-right
      moom-move-frame-left moom-move-frame-to-edge-bottom
      moom-open-height-ring moom-fit-frame-to-fullscreen
      moom-set-font-size-input moom-max-frame-height moom-reset-font-size
      moom-increase-font-size moom-decrease-font-size moom-set-font-size))
 
  (when (autoload-if-found
         moom-autoloads
         "moom" nil t)
    (with-eval-after-load "moom"
      (cond
       ((>= (display-pixel-width) 1920) (setq moom-fullscreen-fontsize 38))
       ((>= (display-pixel-width) 1440) (setq moom-fullscreen-fontsize 28))
       ((>= (display-pixel-width) 1366) (setq moom-fullscreen-fontsize 19))
       ((>= (display-pixel-width) 800) (setq moom-fullscreen-fontsize 14))
       (t (setq moom-fullscreen-fontsize 12)))
 
      ;; リングの状態を最新に更新(max-frame-height が変わるため)
      (add-hook 'moom-after-fullscreen-hook
                'moom--make-frame-height-ring)
      (add-hook 'moom-after-fullscreen-hook
                'moom-move-frame-to-center)
      (add-hook 'moom-reset-font-size-hook
                'moom-move-frame-with-user-specify))
 
    ;; Move the frame to somewhere (default: 0,0)
    (global-set-key (kbd "M-0") 'moom-move-frame-with-user-specify)
    ;; Move the frame to left side of the current position (require 'frame-cmds)
    (setq moom-horizontal-shifts '(30 30))
    (global-set-key (kbd "M-1") 'moom-move-frame-left)
    ;; Move the frame to the center of the window display (require 'moom)
    (global-set-key (kbd "M-2") 'moom-move-frame-to-center)
    ;; Move the frame to right side of the current position(require 'frame-cmds)
    (global-set-key (kbd "M-3") 'moom-move-frame-right)
    ;; Move the current frame to the top of the window display
    (global-set-key (kbd "<f1>") 'moom-move-frame-to-edge-top)
    ;; Move the current frame to the bottom of the window display
    (global-set-key (kbd "S-<f1>") 'moom-move-frame-to-edge-bottom)
    ;; Cycle heights
    (global-set-key (kbd "<f2>") 'moom-open-height-ring)
    ;; Full screen with same frame-width
    (global-set-key (kbd "C-x C-9") 'moom-fit-frame-to-fullscreen)
    (global-set-key (kbd "C-x C-0") 'moom-reset-font-size)
    (global-set-key (kbd "C-_") 'text-scale-decrease)
    (global-set-key (kbd "C-+") 'text-scale-increase)
    (global-set-key (kbd "C-c f s") 'moom-change-frame-width-single)
    (global-set-key (kbd "C-c f d") 'moom-change-frame-width-double)
    (global-set-key (kbd "C-=")
                    #'(lambda () (interactive)
                        (moom-increase-font-size 1)
                        (moom-move-frame-to-edge-top)
                        (moom-print-status)))
    (global-set-key (kbd "C--")
                    #'(lambda () (interactive)
                        (moom-decrease-font-size 2)
                        (moom-move-frame-to-edge-top)
                        (moom-print-status))))
 
  ;; setting for e2wm
  (when (autoload-if-found
         '(change-frame-double-window
           change-frame-single-window)
         "frame-ctr-e2wm" nil t)
    ;; Set the frame width single size
    ;;  C-u C-x - => e2wm OFF, single size width and double height, move center
    (global-set-key (kbd "C-x -") 'change-frame-single-window)
    ;; Set the frame width double size
    ;;  C-u C-x = => e2wm ON, double size width and height, move to the center
    (global-set-key (kbd "C-x =") 'change-frame-double-window))

[popwin.el] ポップアップウィンドウの制御

helm-config の後に呼んでいるのは,Emacs起動時の単純な高速化対策です.

  ;; for emacs 24.1
  ;; (setq special-display-function 'popwin:special-display-popup-window)
  ;; (setq display-buffer-function 'popwin:display-buffer)
 
  ;; for emacs 24.3
  ;; (setq special-display-alist 'popwin:special-display-popup-window)
  ;; (setq display-buffer-alist 'popwin:display-buffer)
  ;; (push '("*sdic*" :position top) popwin:special-display-config)
 
  (with-eval-after-load "helm-config"
    (when (require 'popwin nil t)
      (popwin-mode 1)
      ;; Performed
      (push '("*Help*" :height 20 :position bottom :dedicated t)
            popwin:special-display-config)
      (push '("*osx-dictionary*" :height 20 :position bottom)
            popwin:special-display-config)
 
      ;; Checking...
      (push '("CAPTURE-next.org" :height 10 :position bottom :noselect t)
            popwin:special-display-config)
      (push '("CAPTURE-org-ical.org":height 10 :position bottom :noselect t)
            popwin:special-display-config)
      (push '("dict-app-result" :height 20 :position bottom)
            popwin:special-display-config)
      (push '("*timer*" :height 20 :position bottom :dedicated t)
            popwin:special-display-config)
      (push '("Calendar" :position top :dedicated t)
            popwin:special-display-config)
      (push '("*wclock*" :height 10 :position bottom :dedicated t)
            popwin:special-display-config)
      (push '("*Org Dashboard*" :position bottom)
            popwin:special-display-config)
      (push '("*Org Select*" :height 10 :position bottom)
            popwin:special-display-config)
      (push '("*Org Grep*" :height 20 :position bottom :dedicated t)
            popwin:special-display-config)
      (push '("*Occur*" :height 10 :position bottom)
            popwin:special-display-config)
      (push '("*Shell Command Output*" :height 10 :position bottom :dedicated t)
            popwin:special-display-config)
      (push '("*eshell*" :height 10 :position bottom)
            popwin:special-display-config)
  ;;;            (undo-tree-visualizer-buffer-name :height 10 :position top)
  ;;;            (undo-tree-diff-buffer-name :height 20 :position bottom)
 
      ;; Not performed
      (push '("*Org Agenda*" :height 10 :position top)
            popwin:special-display-config)
      ))

TODO [shackle.el] ポップアップウィンドウの制御

  • popwin の後発パッケージ
  • popwin.el にある =dedicated= が使えないので,本当に移行するか検討中.
  • 以下の設定では,パッケージ読み込みのトリガーを =helm-config= にひも付け
(with-eval-after-load "helm-config"
  (when (require 'shackle nil t)
    (setq shackle-rules
          '(("*Help*" :align t :select t :popup t :size 0.3)
            ("*Org Grep*" :align t :select t :popup t :size 0.3)
            ("*wclock*" :align t :select t :popup t :size 0.3)
            ("*Shell Command Output*"
             :align t :select t :popup t :size 0.3)
            ("*osx-dictionary*"
             :align t :select t :popup t :size 0.3)))
    (shackle-mode 1)))

[elscreen.el] Emacs バッファをタブ化

;;; ElScreen (require apel) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Note: change a string in the elscreen.el from "mac" to "ns"
;; 2011-10-26: e2wm's perspective (two) mode is more useful for me.
(load "elscreen" "ElScreen" t)

[tabbar-ruler] バッファをタブ切り替え可能に

(when (require 'tabbar-ruler nil t)
  ;; (when (require 'tabbar-ruler nil t)
  (setq tabbar-ruler-global-tabbar t) ; If you want tabbar
  (setq tabbar-ruler-popup-menu t) ; If you want a popup menu.
  (setq tabbar-ruler-popup-toolbar t) ; If you want a popup toolbar
  ;;  (setq tabbar-ruler-fancy-tab-separator 'round)
  ;;  (setq tabbar-ruler-fancy-current-tab-separator 'round)
  (setq tabbar-ruler-invert-deselected nil)
  (setq tabbar-ruler-modified-symbol t))

フォント/配色関連

正規表現を見やすくする

(set-face-foreground 'font-lock-regexp-grouping-backslash "#66CC99")
(set-face-foreground 'font-lock-regexp-grouping-construct "#9966CC")

Emacs Lisp で正規表現入力をサポートするツールには, M-x re-builderrx マクロがある.

設定ファイルを見やすくする

generic-x を使うと, /etc/hosts/etc/apache2.conf に色を付けられる.

helm-config の後に呼んでいるのは,Emacs起動時の単純な高速化対策です.

(with-eval-after-load "helm-config"
  (require 'generic-x nil t))

カーソル行に色をつける

(when window-system
  (global-hl-line-mode 1))

色の設定は custom-set-faces で.

(custom-set-faces
 '(hl-line
   ((((background dark)) :background "#484c5c")
    (t (:background "#DEEDFF"))))))

カーソル色の切り替え :Mac:

  (when (and (memq window-system '(mac ns))
             (>= emacs-major-version 24))
 
    (add-hook 'input-method-activate-hook
              #'(lambda ()
                  (setq cursor-type my:cursor-type-ime-on)
                  (set-cursor-color my:cursor-color-ime-on)))
 
    (add-hook 'input-method-inactivate-hook
              #'(lambda ()
                  (setq cursor-type my:cursor-type-ime-off)
                  (set-cursor-color my:cursor-color-ime-off))))

カーソルを点滅させない

(blink-cursor-mode -1)

逆にちゃんと設定して点滅させる場合.以下の例では,入力が止まってから16秒後に0.3秒間隔で点滅します.次に入力が始まるまで,点滅が続きます.

helm-config の後に呼んでいるのは,Emacs起動時の単純な高速化対策です.

(with-eval-after-load "helm-config"
  (setq blink-cursor-blinks 0)
  (setq blink-cursor-interval 0.3)
  (setq blink-cursor-delay 16)
  (blink-cursor-mode -1))

カーソル位置のフォントを確認

M-x describe-char すると,カーソル位置のフォントの情報が別バッファに表示されます.

フォント設定

表のような利用環境に対して,個別に設定を施しています.WindowsとLinuxは安定版のEmacs23で,Macは開発版のCocoaEmacs23です.MacではEmacs24でもうまく表示できています.最近は,Migu 2Mを気に入って使っています.

ASCII 日本語
Mac Monaco Migu 2M 又は ヒラギノ丸ゴ
Windows Inconsolata メイリオ
Linux Inconsolata MigMix
  (defconst my:font-size 12)
  (defun my:ja-font-setter (spec)
    (set-fontset-font nil 'japanese-jisx0208 spec)
    (set-fontset-font nil 'katakana-jisx0201 spec)
    (set-fontset-font nil 'japanese-jisx0212 spec)
    (set-fontset-font nil '(#x0080 . #x024F) spec)
    (set-fontset-font nil '(#x0370 . #x03FF) spec)
    (set-fontset-font nil 'mule-unicode-0100-24ff spec))
  (defun my:ascii-font-setter (spec)
    (set-fontset-font nil 'ascii spec))
 
  (cond
   ;; CocoaEmacs
   ((memq window-system '(mac ns))
    (when (>= emacs-major-version 23)
      ;; 1) Monaco, Hiragino/Migu 2M : font-size=12, -apple-hiragino=1.2
      ;; 2) Inconsolata, Migu 2M     : font-size=14,
      ;; 3) Inconsolata, Hiragino    : font-size=14, -apple-hiragino=1.0
      (let
          ;; Fonts
          ((font-size my:font-size)
           ;; ((font-size 28) ; for mirroring presentation (1440x900)
           (ascii-font "Monaco") ;; "Inconsolata"
           (ja-font "Migu 2M")) ;; "Hiragino Maru Gothic Pro"
        (my:ascii-font-setter (font-spec :family ascii-font :size font-size))
        (my:ja-font-setter (font-spec :family ja-font :size font-size)))
 
      ;; Fix ratio provided by set-face-attribute for fonts display
      (setq face-font-rescale-alist
            '(("^-apple-hiragino.*" . 1.0) ; 1.2
              (".*Migu.*" . 1.2)
              (".*Inconsolata.*" 1.0)
              (".*osaka-bold.*" . 1.0)     ; 1.2
              (".*osaka-medium.*" . 1.0)   ; 1.0
              (".*courier-bold-.*-mac-roman" . 1.0) ; 0.9
              ;; (".*monaco cy-bold-.*-mac-cyrillic" . 1.0)
              ;; (".*monaco-bold-.*-mac-roman" . 1.0) ; 0.9
              ("-cdac$" . 1.0)))           ; 1.3
      ))
 
   ((eq window-system 'ns)
    ;; Anti aliasing with Quartz 2D
    (when (boundp 'mac-allow-anti-aliasing)
      (setq mac-allow-anti-aliasing t)))
 
   ((eq window-system 'w32) ; windows7
    (let ((font-size 14)
          (font-height 100)
          (ascii-font "Inconsolata")
          ;; (ja-font "Meiryo UI"))
          (ja-font "メイリオ"))
      (my:ja-font-setter
       (font-spec :family ja-font :size font-size :height font-height))
      (my:ascii-font-setter (font-spec :family ascii-font :size font-size)))
    (setq face-font-rescale-alist '((".*Inconsolata.*" . 1.0))) ; 0.9
    )
   (window-system ; for SuSE Linux 12.1
    (let
        ((font-size 14)
         (font-height 100)
         (ascii-font "Inconsolata")
         ;; (ja-font "MigMix 1M")
         (ja-font "Migu 1M"))
      (my:ja-font-setter
       (font-spec :family ja-font :size font-size :height font-height))
      (my:ascii-font-setter (font-spec :family ascii-font :size font-size)))
    (setq face-font-rescale-alist '((".*MigMix.*" . 2.0)
                                    (".*Inconsolata.*" . 1.0))) ; 0.9
    ))

フォントのインストール方法

Linux では次のように処理するだけでよく,意外と簡単.

  1. ~/.fonts を作成する
  2. フォントを1.のディレクトリに置く
  3. fc-cache -fv を実行
  4. fc-list でインストールされているかを確認.

なお,Windows では,フォントファイルを右クリックして,インストールを選択するだけでOK.

フォントチェック用コード

サンプルの orgファイル を作って,見た目をチェックしています.バッファ内の桁数チェックや,ASCIIが漢字の半分の幅になっているかのチェックが楽になります.

行間を制御する

(set-default 'line-spacing 0.2)

パッチをカラフルに表示する

Built-in の diff-mode.el をカスタマイズします.

  (when (autoload-if-found
         '(diff-mode)
         "diff-mode" nil t)
    (with-eval-after-load "diff-mode"
      (set-face-attribute 'diff-added-face nil
                          :background nil :foreground "green"
                          :weight 'normal)
 
      (set-face-attribute 'diff-removed-face nil
                          :background nil :foreground "firebrick1"
                          :weight 'normal)
 
      (set-face-attribute 'diff-file-header-face nil
                          :background nil :weight 'extra-bold)
 
      (set-face-attribute 'diff-hunk-header-face nil
                          :foreground "chocolate4"
                          :background "white" :weight 'extra-bold
                          :inherit nil)))

背景を黒系色にする

(custom-set-faces
 '(default ((t
             (:background "black" :foreground "#55FF55")
             ))))

時間帯を指定して起動時にテーマを切り替える

次の例では,19時から翌日の朝5時までの間に夜用のテーマを使っています.

  (defun my:night-time-p (begin end)
    (let* ((ch (string-to-number (format-time-string "%H" (current-time))))
           (cm (string-to-number (format-time-string "%M" (current-time))))
           (ct (+ cm (* 60 ch))))
      (if (> begin end)
          (or (<= begin ct) (<= ct end))
        (and (<= begin ct) (<= ct end)))))
 
  (when window-system
    (let ((night-time-in 21)
          (night-time-out 5))
      (if (my:night-time-p (* night-time-in 60) (* night-time-out 60))
          (when (require 'night-theme nil t)
            (load-theme 'night t))
        (when (require 'daylight-theme nil t)
          (load-theme 'daylight t)))))

[rainbow-mode.el] 配色のリアルタイム確認

M-x rainbow-mode とすると,色指定のコードの背景色を,その指定色にリアルタイム変換してくれる.

http://elpa.gnu.org/packages/rainbow-mode.html

(when (autoload-if-found
       '(rainbow-mode)
       "rainbow-mode" nil t)
  (dolist (hook '(emmet-mode-hook emacs-lisp-mode-hook org-mode-hook))
    (add-hook hook 'rainbow-mode)))

色一覧

0,6,9,C,F の組み合わせ

 #000000 #000033 #000066 #000099 #0000CC #0000FF
 #003300 #003333 #003366 #003399 #0033CC #0033FF
 #006600 #006633 #006666 #006699 #0066CC #0066FF
 #009900 #009933 #009966 #009999 #0099CC #0099FF
 #00CC00 #00CC33 #00CC66 #00CC99 #00CCCC #00CCFF
 #00FF00 #00FF33 #00FF66 #00FF99 #00FFCC #00FFFF
 
 #330000 #330033 #330066 #330099 #3300CC #3300FF
 #333300 #333333 #333366 #333399 #3333CC #3333FF
 #336600 #336633 #336666 #336699 #3366CC #3366FF
 #339900 #339933 #339966 #339999 #3399CC #3399FF
 #33CC00 #33CC33 #33CC66 #33CC99 #33CCCC #33CCFF
 #33FF00 #33FF33 #33FF66 #33FF99 #33FFCC #33FFFF
 
 #660000 #660033 #660066 #660099 #6600CC #6600FF
 #663300 #663333 #663366 #663399 #6633CC #6633FF
 #666600 #666633 #666666 #666699 #6666CC #6666FF
 #669900 #669933 #669966 #669999 #6699CC #6699FF
 #66CC00 #66CC33 #66CC66 #66CC99 #66CCCC #66CCFF
 #66FF00 #66FF33 #66FF66 #66FF99 #66FFCC #66FFFF
 
 #990000 #990033 #990066 #990099 #9900CC #9900FF
 #993300 #993333 #993366 #993399 #9933CC #9933FF
 #996600 #996633 #996666 #996699 #9966CC #9966FF
 #999900 #999933 #999966 #999999 #9999CC #9999FF
 #99CC00 #99CC33 #99CC66 #99CC99 #99CCCC #99CCFF
 #99FF00 #99FF33 #99FF66 #99FF99 #99FFCC #99FFFF
 
 #CC0000 #CC0033 #CC0066 #CC0099 #CC00CC #CC00FF
 #CC3300 #CC3333 #CC3366 #CC3399 #CC33CC #CC33FF
 #CC6600 #CC6633 #CC6666 #CC6699 #CC66CC #CC66FF
 #CC9900 #CC9933 #CC9966 #CC9999 #CC99CC #CC99FF
 #CCCC00 #CCCC33 #CCCC66 #CCCC99 #CCCCCC #CCCCFF
 #CCFF00 #CCFF33 #CCFF66 #CCFF99 #CCFFCC #CCFFFF
 
 #FF0000 #FF0033 #FF0066 #FF0099 #FF00CC #FF00FF
 #FF3300 #FF3333 #FF3366 #FF3399 #FF33CC #FF33FF
 #FF6600 #FF6633 #FF6666 #FF6699 #FF66CC #FF66FF
 #FF9900 #FF9933 #FF9966 #FF9999 #FF99CC #FF99FF
 #FFCC00 #FFCC33 #FFCC66 #FFCC99 #FFCCCC #FFCCFF
 #FFFF00 #FFFF33 #FFFF66 #FFFF99 #FFFFCC #FFFFFF

[volatile-highlights] コピペした領域を強調

コピペ直後の数秒に限定して,コピペした領域をハイライトします.さらに,所定の間隔で表示色を変えることで,ハイライト色が徐々に消えていくようなエフェクトにしています.

  (when (autoload-if-found
         '(volatile-highlights-mode)
         "volatile-highlights" nil t)
    (eval-when-compile
      (require 'volatile-highlights nil t))
    (with-eval-after-load "volatile-highlights"
      (set-face-attribute
       'vhl/default-face nil :foreground "#FF3333" :background "#FFCDCD")
      (volatile-highlights-mode t)
 
      ;; ふわっとエフェクトの追加(ペースト時の色 => カーソル色 => 本来色)
      (defun my:vhl-change-color ()
        (let
            ((next 0.2)
             (reset 0.5)
             (colors '("#F8D3D7" "#F2DAE1" "#EBE0EB" "#E5E7F5" "#DEEDFF")))
          (dolist (color colors)
            (run-at-time next nil
                         'set-face-attribute
                         'vhl/default-face
                         nil :foreground "#FF3333" :background color)
            (setq next (+ 0.05 next)))
          (run-at-time reset nil 'vhl/clear-all))
        (set-face-attribute 'vhl/default-face
                            nil :foreground "#FF3333"
                            :background "#FFCDCD"))
 
      (defun my:yank (&optional ARG)
        (interactive)
        (yank ARG)
        (when window-system
          (my:vhl-change-color)))
      (global-set-key (kbd "M-v") 'my:yank)
      (global-set-key (kbd "C-y") 'my:yank)
 
      (with-eval-after-load "org"
        (defun my:org-yank ()
          (interactive)
          (org-yank)
          (when window-system
            (my:vhl-change-color)))
        (define-key org-mode-map (kbd "C-y") 'my:org-yank)))
 
    (dolist (hook '(org-mode-hook emacs-lisp-mode-hook emmet-mode-hook))
      (add-hook hook 'volatile-highlights-mode)))

TODO [edit-color-stamp] Qt経由でカラーピッカーを使う

  • Macintosh でもちゃんと使えます.
(when (executable-find "qt_color_picker")
  (with-eval-after-load "helm-config"
    (require 'edit-color-stamp nil t))
  (global-set-key (kbd "C-c f c p") 'edit-color-stamp))

ユーティリティ関数

[pomodoro.el] ポモドーロの実践

@syohex さん謹製の pomodoro.el に少しカスタマイズしたおれおれ pomodoro.el を使っています.以下のように設定すると,ポモドーロの残り時間は表示せず,アイコンだけをモードラインに表示できます.残り時間は M-x pomodoro:mode-line-time-display-toggle すれば,いつでも表示できます.

pomodoro:finish-work-hookpomodoro:finish-rest-hookpomodoro:long-rest-hook にそれぞれ結びつけてあるのは,Macのスピーチ機能です.この例では,Kyoko さんが指示を出してくれます.

M-x pomodoro:start すると,ポモドーロが始まり,8時間後に pomodoro:stop が呼ばれてポモドーロが終了します.pomodoro は機械的に仕事をしたい人にピッタリです.人によっては GTD よりも取っ付きやすいと思います.

helm-config の後に呼んでいるのは,Emacs起動時の単純な高速化対策です.

  (when (autoload-if-found
         '(pomodoro:start)
         "pomodoro" nil t)
    (eval-when-compile
      (require 'pomodoro nil t))
 
    (with-eval-after-load "helm-config"
      (when (require 'pomodoro nil t)
        (pomodoro:start nil)))
 
    (with-eval-after-load "pomodoro"
      ;; 作業時間終了後に開くファイルを指定しない
      (setq pomodoro:file nil)
      ;; ●だけで表現する(残り時間表示なし)
      (setq pomodoro:mode-line-time-display nil)
      ;; ●の置き換え
      (setq pomodoro:mode-line-work-sign ">>")
      (setq pomodoro:mode-line-rest-sign "<<")
      (setq pomodoro:mode-line-long-rest-sign "<>")
      ;; 長い休憩に入るまでにポモドーロする回数
      (setq pomodoro:iteration-for-long-rest 4)
      ;; 作業時間関連
      (setq pomodoro:work-time 25     ; 作業時間
            pomodoro:rest-time 5      ; 休憩時間
            pomodoro:long-rest-time 30 ; 長い休憩時間
            pomodoro:max-iteration 16) ; ポモドーロする回数
      ;; タイマーの表示をノーマルフェイスにする
      (set-face-bold-p 'pomodoro:timer-face nil)
      ;; 作業中(赤),休憩中(青),長い休憩中(緑)にする
      (custom-set-faces
       '(pomodoro:work-face
         ((((background dark)) :foreground "#DB4C46" :bold t)
          (t (:foreground "#9d64c4" :bold t)))) ;;  #8248c4 , #956dc4, #9d64c4
       '(pomodoro:rest-face
         ((((background dark)) :foreground "#3869FA" :bold t)
          (t (:foreground "#203e6f" :bold t))))
       '(pomodoro:long-rest-face
         ((((background dark)) :foreground "#008890" :bold t)
          (t (:foreground "#1c9b08" :bold t))))) ;; 00B800
 
      (defun my:pomodoro-status ()
        "Show the current `pomodoro' status in minibuffer when focus-in."
        (interactive)
        (message (format "[Pomodoro] Remaining: %s | Count: %d"
                         (pomodoro:time-to-string pomodoro:remainder-seconds)
                         pomodoro:work-count)))
      (add-hook 'focus-in-hook #'my:pomodoro-status)
 
      (defvar my:pomodoro-speak nil)
      (defun my:pomodoro-speak-toggle ()
        (interactive)
        (setq my:pomodoro-speak (not my:pomodoro-speak)))
 
      (when (memq window-system '(mac ns))
        ;; Mac ユーザ向け.Kyokoさんに指示してもらう
        (defvar pomodoro:with-speak nil)
        (when pomodoro:with-speak
          (add-hook 'pomodoro:finish-work-hook
                    #'(lambda ()
                        (let ((script
                               (concat "say -v Kyoko "
                                       (number-to-string
                                        (floor pomodoro:rest-time))
                                       "分間,休憩しろ")))
                          (if my:pomodoro-speak
                              (shell-command-to-string script)
                            (message "%s" script)))))
 
          (add-hook 'pomodoro:finish-rest-hook
                    #'(lambda ()
                        (let ((script
                               (concat "say -v Kyoko "
                                       (number-to-string
                                        (floor pomodoro:work-time))
                                       "分間,作業しろ")))
                          (if my:pomodoro-speak
                              (shell-command-to-string script)
                            (message "%s" script)))))
 
          (add-hook 'pomodoro:long-rest-hook
                    #'(lambda ()
                        (let ((script
                               (concat "say -v Kyoko これから"
                                       (number-to-string
                                        (floor pomodoro:long-rest-time))
                                       "分間の休憩です")))
                          (if my:pomodoro-speak
                              (shell-command-to-string script)
                            (message "%s" script))))))
 
        (defun my:pomodoro-notify ()
          (interactive)
          (shell-command-to-string
           (concat "terminal-notifier -title \"Pomodoro\" -message \""
                   "三三 ヘ(*゚∇゚)ノ\""
                   " -sender org.gnu.Emacs")))
        (add-hook 'pomodoro:finish-work-hook 'my:pomodoro-notify))))

[pomodoro.el] 続・ポモドーロの実践

さらに,モードラインに出すスタータスを表すサインに動きを付けます.ただ頻繁にモードラインを更新して描画するので,環境によっては動作が重くなるかもしれません.

各 interlval の数値を setq で後から変更する場合は,その直後に pomodoro:activate-visual-work-sign もしくは変更する interval に対応する同様の関数を実行してください.モードラインに変更が反映されます.

  (with-eval-after-load "pomodoro"
    ;; 追加実装
    (defvar pomodoro:update-work-sign-interval 0.21) ;; work用表示間隔
    (defvar pomodoro:update-rest-sign-interval 0.21) ;; rest用表示間隔
    (defvar pomodoro:update-long-rest-sign-interval 0.36) ;; long-rest用表示間隔
 
    (setq pomodoro:mode-line-work-sign-list
          '("|  " "|| " "|||" " ||" "  |" "   " "   "
            "  |" " ||" "|||" "|| " "|  " "   " "   "))
    (setq pomodoro:mode-line-rest-sign-list
          '(".  " ".. " "..." " .." "  ." "   " "   "
            "  ." " .." "..." ".. " ".  " "   " "   "))
    (setq pomodoro:mode-line-long-rest-sign-list
          '("   " " | " "|||" "| |" "   "))
 
    ;; Example.1
    ;; (defvar pomodoro:mode-line-work-sign-list
    ;;   '("▁" "▂" "▃" "▄" "▅" "▆" "▇" "▇" "▆" "▅" "▄" "▃" "▂" "▁" "▁" ))
    ;; (defvar pomodoro:mode-line-rest-sign-list
    ;;   pomodoro:mode-line-work-sign-list)
    ;; (defvar pomodoro:mode-line-long-rest-sign-list
    ;;   pomodoro:mode-line-work-sign-list)
 
    ;; Example.2
    ;; (defvar pomodoro:mode-line-work-sign-list
    ;;   '(">   " ">>  " ">>> " ">>>>" " >>>" "  >>" "   >" "    "))
    ;; (defvar pomodoro:mode-line-rest-sign-list
    ;;   '("   <" "  <<" " <<<" "<<<<" "<<< " "<<  " "<   " "    "))
    ;; (defvar pomodoro:mode-line-long-rest-sign-list
    ;;   '("  <>  " " <<>> " "<<<>>>" "<<  >>" "<    >" "      "))
 
    ;; Example.3
    ;; (setq pomodoro:mode-line-work-sign-list
    ;;       '("▂▁  ▁" "▃▂▁  " "▄▃▂▁ " "▅▄▃▂▁" "▆▅▄▃▂" "▇▆▅▄▃" "▇▇▆▅▄" "▆▇▇▆▅"
    ;;         "▅▆▇▇▆" "▄▅▆▇▇" "▃▄▅▆▇" "▂▃▄▅▆" "▁▂▃▄▅" " ▁▂▃▄" "  ▁▂▃" "▁  ▁▂"))
 
    ;; Example.4
    ;; (defvar pomodoro:mode-line-work-sign-list
    ;;   '("◤◢◤ ^-^; ◢◤◢"
    ;;     "◤◢◤ ^-^  ◢◤◢"
    ;;     "◤◢◤ ^-^  ◢◤◢"
    ;;     "◤◢◤ ^-^  ◢◤◢"
    ;;     "◤◢◤ ^-^; ◢◤◢"
    ;;     "◤◢◤ ^-^; ◢◤◢"
    ;;     "◢◤◢◤ ^-^; ◢◤"
    ;;     "◤◢◤◢◤ ^-^; ◢"
    ;;     "◢◤◢◤◢◤ ^-^; "
    ;;     " ◢◤◢◤◢◤ ^-^;"
    ;;     "; ◢◤◢◤◢◤ ^-^"
    ;;     "^; ◢◤◢◤◢◤ ^-"
    ;;     "-^; ◢◤◢◤◢◤ ^"
    ;;     "^-^; ◢◤◢◤◢◤ "
    ;;     " ^-^; ◢◤◢◤◢◤"
    ;;     "◤ ^-^; ◢◤◢◤◢"
    ;;     "◢◤ ^-^; ◢◤◢◤"));
 
    ;; タイマーを記録
    (defvar pomodoro:update-sign-timer
      (run-at-time t pomodoro:update-work-sign-interval
                   'pomodoro:update-work-sign))
 
    ;; 初期状態を登録
    (setq pomodoro:mode-line-work-sign (car pomodoro:mode-line-work-sign-list))
 
    ;; utilities
    (defun pomodoro:list-rotate (sign-list)
      (if (listp sign-list)
          (append (cdr sign-list)
                  (list (car sign-list)))
        sign-list))
 
    (defun pomodoro:activate-visual-sign (sign interval)
      (cancel-timer pomodoro:update-sign-timer)
      (setq pomodoro:update-sign-timer
            (run-at-time t interval sign)))
 
    (defun pomodoro:stop-visualize ()
      (when (timerp pomodoro:update-sign-timer)
        (cancel-timer pomodoro:update-sign-timer))
      (setq pomodoro:mode-line-work-sign nil)
      (setq pomodoro:mode-line-rest-sign nil)
      (setq pomodoro:mode-line-long-rest-sign nil))
 
    (defun advice:pomodoro:stop ()
      "Extensions to stop pomodoro and timers"
      (pomodoro:stop-visualize))
    (advice-add 'pomodoro:stop :after #'advice:pomodoro:stop)
 
    ;; work
    (defun pomodoro:update-work-sign ()
      "Update pomodoro work-sign on modeline."
      (setq pomodoro:mode-line-work-sign
            (car pomodoro:mode-line-work-sign-list))
      (setq pomodoro:mode-line-work-sign-list
            (pomodoro:list-rotate pomodoro:mode-line-work-sign-list))
      (force-mode-line-update t))
 
    (defun pomodoro:activate-visual-work-sign ()
      (pomodoro:activate-visual-sign
       'pomodoro:update-work-sign pomodoro:update-work-sign-interval))
 
    ;; rest
    (defun pomodoro:update-rest-sign ()
      "Update pomodoro rest-sign on modeline."
      (setq pomodoro:mode-line-rest-sign
            (car pomodoro:mode-line-rest-sign-list))
      (setq pomodoro:mode-line-rest-sign-list
            (pomodoro:list-rotate pomodoro:mode-line-rest-sign-list))
      (force-mode-line-update t))
 
    (defun pomodoro:activate-visual-rest-sign ()
      (pomodoro:activate-visual-sign
       'pomodoro:update-rest-sign pomodoro:update-rest-sign-interval))
 
    ;; long rest
    (defun pomodoro:update-long-rest-sign ()
      "Update pomodoro long-rest-sign on modeline."
      (setq pomodoro:mode-line-long-rest-sign
            (car pomodoro:mode-line-long-rest-sign-list))
      (setq pomodoro:mode-line-long-rest-sign-list
            (pomodoro:list-rotate pomodoro:mode-line-long-rest-sign-list))
      (force-mode-line-update t))
 
    (defun pomodoro:activate-visual-long-rest-sign ()
      (pomodoro:activate-visual-sign
       'pomodoro:update-long-rest-sign pomodoro:update-long-rest-sign-interval))
 
    ;; ステータスが切り替わる時に表示を入れ替える
    (add-hook 'pomodoro:finish-rest-hook #'pomodoro:activate-visual-work-sign)
    (add-hook 'pomodoro:finish-work-hook #'pomodoro:activate-visual-rest-sign)
    (add-hook 'pomodoro:long-rest-hook
              #'pomodoro:activate-visual-long-rest-sign))

カレントバッファのあるディレクトリをターミナルで表示

(global-set-key (kbd "C-c f t") 'open-current-directory)

[google-this.el] 単語をグーグル検索

カーソル下の単語を検索して,結果をブラウザで受け取ります. google-this を直接呼ぶと検索確認を聞かれるので,すぐに検索するようにカスタマイズします. M-x google-this-word を使うのも手ですが,ハイフンで連結された文字列を拾えないので好みがわかれます.

  (when (autoload-if-found
         '(my:google-this google-this-word)
         "google-this" nil t)
    (eval-when-compile
      (require 'google-this nil t))
 
    (with-eval-after-load "google-this"
      (defun my:google-this ()
        (interactive)
        (google-this (current-word) t)))
 
    (global-set-key (kbd "C-c f g") 'my:google-this))

[lingr.el] チャットルームに参加

init.el読書会が毎週土曜日の22時に開催されています.作業に集中していると,ついつい忘れてしまうので,その時間が来たら自動的にログインするように設定しています.ユーザ名とパスワードは,セキュリティを考慮して別なファイルに記載しています.

  (when (autoload-if-found
         '(lingr-login my:lingr-login)
         "lingr" nil t)
    (eval-when-compile
      (require 'lingr nil t))
 
    (with-eval-after-load "lingr"
      (setq lingr-icon-mode t)
      (setq lingr-icon-fix-size 24)
      (setq lingr-image-convert-program "/usr/local/bin/convert"))
 
    (with-eval-after-load "helm-config"
      ;; do not use `run-at-time' at booting since diary-lib.el will be loaded. It requires loading cost.
      (defun my:lingr-login ()
        (when (string= "Sat" (format-time-string "%a"))
          (lingr-login)))
      (unless (passed-clock-p "23:00")
        (run-at-time "23:00" nil 'my:lingr-login))))

TODO [password-store.el] パスワード管理

(if (executable-find "pass")
    (when (autoload-if-found
           '(helm-pass)
           "helm-pass" nil t)
      (global-set-key (kbd "C-c f p") 'helm-pass))
  (message "--- pass is NOT installed."))

もしくは, id-manager.el もパスワード管理に利用できる.こちらは特定のコマンドがシステムにインストールされていなくても動く.

(when (eval-after-autoload-if-found
       '(id-manager) "id-manager" nil t nil
       '((setenv "GPG_AGENT_INFO" nil))))

[multi-term.el] ターミナル

たまに使いたくなるので一応.

(eval-after-autoload-if-found '(multi-term) "multi-term" nil t)

[osx-lib.el] OSX用ユーティリティ :Mac:

  • OSXの機能を呼び出すためのツール集
  • =osx-lib-say-region= を呼び出せば,選択領域を機械音で発声させられます.
  • =selected.el= と組み合わせると選択後にシングルキーで実施できるのでさらに便利です.
(when (autoload-if-found
       '(osx-lib-say osx-lib-say-region)
       "osx-lib" nil t)
  (eval-when-compile
    (require 'osx-lib nil t))
  (with-eval-after-load "osx-lib"
    (setq osx-lib-say-ratio 100)
    (setq osx-lib-say-voice "Samantha")))

iterm2 を Emacs から呼び出したい :Mac:

C-M-i を iterm2.app の呼び出しに割り当てます.シェルでの作業はどうも eshell では満足できないので.なお flyspell を使っていると,遅延呼び出しした後にキーバインドを奪われるので,取り返します.

cmd-to-open-iterm2 の実装は,./utility.el にあります.

(when (autoload-if-found
       '(my:cmd-to-open-iterm2)
       "utility" nil t)
  (global-set-key (kbd "C-M-i") #'my:cmd-to-open-iterm2))
;; キーバインドの再設定
(with-eval-after-load "flyspell"
  (define-key flyspell-mode-map (kbd "C-M-i") #'my:cmd-to-open-iterm2))
(with-eval-after-load "org"
  (define-key org-mode-map (kbd "C-M-i") #'my:cmd-to-open-iterm2))

[utility.el] 自作してテスト中の便利関数群

関数定義を別ファイルに分離して,Emacs起動の高速化を図っています.各関数を autoload の管理下において,必要なときにロードするように設定しています.

  (defconst utility-autoloads
    '(takaxp:date
      takaxp:window-resizer takaxp:open-file-ring my:update-alarms-from-file
      my:desktop-notify my:daylight-theme my:night-theme
      eval-org-buffer kyoko-mad-mode-toggle
      org2dokuwiki-cp-kill-ring open-current-directory set-alarms-from-file
      reload-ical-export show-org-buffer get-random-string init-auto-install
      add-itemize-head insert-formatted-current-date
      insert-formatted-current-time insert-formatted-signature
      export-timeline-business export-timeline-private chomp
      my:browse-url-chrome count-words-buffer do-test-applescript
      delete-backup-files recursive-delete-backup-files describe-timer
      my:list-packages my:setup-cask my:lingr-login my:backup))
 
  (when (autoload-if-found
         utility-autoloads
         "utility" nil t)
    (global-set-key (kbd "C-M--") 'add-itemize-head)
    (global-set-key (kbd "<f12>") 'takaxp:open-file-ring)
    (global-set-key (kbd "C-c t") 'takaxp:date)
    (global-set-key (kbd "C-c f 4") 'takaxp:window-resizer))

おわりに

以上が,私の init.el とその説明です.

Comments