26 Mar 2018, 20:38

Emacsでデータサイエンス用環境構築(Python)

はじめに

肥大化してデブになった emacs設定を一旦捨て去り、一から作り直すことにした。

デブは自分のお腹だけで十分だ!(名言)

Motivation

以前は、こんな感じの設定ファイルを作っていたのだけれども、複雑になりすぎた。

また、データサイエンスをやるにつれて、以下のようなことがあり、Emacsを使いたくなってきた。

  • 自宅サーバにsshで自習室からつないで作業することが多いので、Pycharm使えない。
  • Jupyter Notebookを使うことが多いが、Jupyter Notebookでは、スクリプトかけない。
  • 今まで素の Emacsでしのいできたのだけれども、辛くなってきた。
  • ターミナルかっこいい\(o)/

目指す姿

  • データサイエンス、もっと言えばPythonに特化した環境を作りたい
  • 軽い環境を作りたい
  • できるだけシンプルにしたい

Environment

  • Ubuntu 16.04
  • Python 3.6(Anaconda)
  • Emacs 25.x

最新版Emacsを投入

まずは、Ubuntuに25系のversionをインストールする。

sudo add-apt-repository ppa:kelleyk/emacs
sudo apt-get update
sudo apt-get install emacs25
sudo update-alternatives --config emacs

リポジトリ & 設定ファイルを作成

.emacs.dを gitで世代管理して、githubにバックアップしたい。まずは、emacs用のリポジトリを作成。

init.elも作成。ここを参考にして、カスタムディレクトリを起点に起動できるように記述。

(when load-file-name
  (setq user-emacs-directory (file-name-directory load-file-name)))

続いて、このリポジトリを利用して起動するためのスクリプトを作成して、パスの通ったところに置く。

#!/bin/bash                                                                                                                                                                                                          
emacs -nw -q -l /home/tsu-nera/dotemacs-for-data-science/init.el $1

パッケージ管理をどうするか?

以前はuse-packageを使っていた。しかし、今回はシンプルにしたいので、デフォルトで搭載されているパッケージ管理ツール package.elを使うことにする。以下の記事によると、25.1からはインストールされたパッケージが package-selected-package 変数に保持されるようになったらしい。

以下の設定を inti.elに書くことで、custom.elに設定を吐き出すようにする。

(setq custom-file (expand-file-name "custom.el" user-emacs-directory))
(when (file-exists-p custom-file)
  (load custom-file))

package-installでインストールできるパッケージを増やすために、リポジトリを追加する。

(require 'package)
(add-to-list 'package-archives '("melpa" . "http://melpa.milkbox.net/packages/"))
(add-to-list 'package-archives '("marmalade" . "http://marmalade-repo.org/packages/"))
(fset 'package-desc-vers 'package--ac-desc-version)
(package-initialize)

Python開発環境

ここからが本番! データサイエンスのために Python開発環境を整える。過去記事を参考に(古くてあまり参考にならないですが)、設定を書いていく。

python-mode - メジャーモード

メジャーモードはデフォルトの pythonパッケージではなく、python-modeをつかう。なんとなく。

(require 'python-mode)
(add-to-list 'auto-mode-alist '("\\\.py\\\'" . python-mode))
(add-to-list 'interpreter-mode-alist '("python" . python-mode))

flycheck, flake8 – 静的解析

Pythonの静的解析ツールとして flake8, それをつかうためのインタフェース flycheckを入れる。

pip install flake8

python-modeのときだけ有効。

(defun tnoda/turn-on-flycheck-mode ()
  (flycheck-mode 1))
(add-hook 'python-mode-hook 'tnoda/turn-on-flycheck-mode)

jedi – 自動補完

jedi は pythonのための 自動補完ツール。

pip install jedi


(add-hook 'python-mode-hook 'jedi:setup)
(setq jedi:complete-on-dot t)

jedi は Emacsの補完ツール , auto-completeを使っているので、その設定もしておく。

(require 'auto-complete-config)
(ac-config-default)
(global-auto-complete-mode t)

yapf – 自動フォーマット

自動でいい感じに整形してくれるツールを入れる。autopep8という古参なツールもあるけれども、新しい方を採用。

pip install yapf


;; py-yapf - auto format                                                                                                                                                                                             
(require 'py-yapf)
(add-hook 'python-mode-hook 'py-yapf-enable-on-save)

ひとまず完成した init.el

18 Jun 2017, 16:51

MathJax を使って WordPress に org2blog で数式ありの投稿をする

このブログは、org2blog というライブラリを使って、 Emacs org-mode でかかれた文章を HTML に変換して投稿している。

今回、org-mode から HTML へ変換した文章中で 数式を扱う方法を調べてみた。

MathJax をつかう

MathJax とは、javascript でかかれた 数式を表示するためのライブラリ。 Latex なみの数式表現が扱えるようになる。

すべてのブラウザで動作し、表示するクライアント側での設定はいらない。

さらに、MathJax のファイル群のインストールは必要ない。

MathJax は、コンテンツデリバリネットワーク(Contents Delivery Network、CDN)で公開・配信されているので、 JavaScript ライブラリをダウンロードして、サーバーにアップロードといった作業は必要はないのである。

MathJax を使用するには、<html>…</html> タグの中に以下を書く。

<script type="text/javascript" async
  src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-MML-AM_CHTML">
</script>

<body>…</body> の中で、MathJax の記法(MathML、LaTeX、ASCIIMathML)を使って数式を書くと、 数式がレンダリングされる。

org-mode で MathJax をつかう

org-mode は MathJax にデフォルトで対応しているようだ(version. 9.0.5)

なので、org-mode の文章中に 数式を 書いて、org-export で HTML 形式で export すればよい。

これに今まで気づかなかったのは、自分の環境では、#+OPTIONS: TeX:nil を指定していたから。 ここは、Tex t でなければいけない。

Default の設定だと参照する MathJax の version が古いらしく、以下の設定で最新が使える。

(setf org-html-mathjax-options
      '((path "https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML")
        (scale "100") 
        (align "center") 
        (indent "2em")
        (mathml nil))
      )
(setf org-html-mathjax-template
      "<script type=\"text/javascript\" src=\"%PATH\"></script>")

org2blog は、html 形式に org-mode の文章を変換してから、WordPress にアップロードする。 org2blog で WordPress に投稿すれば、WordPress 上でも数式が表示される。

Example

\[〜\] で囲んで数式を表示

\[f(a)= \frac{1}{2\pi i}\oint_{\Gamma} \frac{f(z)}{z-a}dz\]

$$f(a)= \frac{1}{2\pi i}\oint_{\Gamma} \frac{f(z)}{z-a}dz$$

\(〜\) で囲んで本文中に表示

\(〜\) で囲んで、本文中に$a$を表示。

参考

あとは、Latex 記法を覚えるだけだ。(これが一番大変)

26 May 2017, 16:28

Emacs で conda.el をつかって環境が切り替えられない時の対処方法

Emacs で、anaconda 環境を切り替える便利な eLisp に conda.el というものがある。

しかし、これがどうもうまく動かなかったので調査してみた。

環境

  • fish shell 2.5.0
  • Emacs 25.1.2

事象

conda-env-activate を使うと、切り替わったよというメッセージはでるが、 実際は Anaconda の root を使っている。指定した環境を使ってくれない。

原因

PATH に何が設定されてるか調べてみると。 (getenv "PATH")

"/home/tsu-nera/anaconda3/envs/kaggles/bin:/home/tsu-nera/.rbenv/shims:/home/tsu-nera/anaconda3/bin:/home/tsu-nera/.cask/bin:/home/tsu-nera/bin:/home/tsu-nera/go/bin:/home/tsu-nera/.rbenv/bin:/home/tsu-nera/script/scala:/home/tsu-nera/script/ruby:/home/tsu-nera/script/sh:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/usr/lib/jvm/java-8-oracle/bin:/usr/lib/jvm/java-8-oracle/db/bin:/usr/lib/jvm/java-8-oracle/jre/bin"

つまり、二つのパスが登録されている。

  1. /home/tsu-nera/anaconda3/envs/kaggle/bin
  2. /home/tsu-nera/anaconda3/bin

使いたいのは、1 のほうで2はいらない。

なぜかわからないが、Emacs を起動すると、PATH を自動で読み込んでくれるようなのだ。

こんな機能しらないぞ!exec-path-from-shell をつかって実現する機能ではなかったか? デフォルトで PATH を引き継ぐように仕様変更されたのか??

解決方法

fish shell の環境設定ファイル(自分の場合は env.fish に分けている)、 から、anaconda のパスを削除すると、Emacs で conda-activate をつかった切り替えができる。

しかし、これでは、ふだん conda コマンドが使えない。

そこで、fish shell にこんな関数を定義した。まず Emacs を立ち上げた上で、conda を有効にする。

# anaconda
function conda-activate
    set fish_user_paths $HOME/anaconda3/bin $fish_user_paths
end

一時しのぎだけれども、これで Emacs から conda で環境を切り替えることができるようになった。

07 Jan 2017, 09:40

babel-loader:org-mode で init.el を管理する方法

私の現時点での.emacs 管理方法を紹介します。リポジトリは以下です。

org ファイルがならんでます。そうです!

emacs の設定ファイルを org-mode で管理しています。

org-mode で書いた設定ファイルを hoge.org -> hoge.el に変換しています。

それを可能にするパッケージが、babel-loader です。

org-mode で init.el を管理することで得られる 7 つの恩恵

benel-loader は init-loder と組み合わせることによって、効果を発揮します。 hoge.org -> hoge.el に変換したファイルを init-loader によって、 一つずつロードしていくからです。

rubikitch さんが以下のような記事を年末に書きました。

それにならって、org-mode で init.el を管理することの恩恵を考えて見たいと思います。

  1. 説明をコメントとして書かないですむ。… ;; で説明をコメントアウトする見苦しさとはおさらば。
  2. 説明とコードを一緒に 一元管理できる。… Run Book Automation です。
  3. org-mode に慣れていれば説明を書きやすい。… I love org-mode!!
  4. org-mode の折りたたみ機能によって、階層的に設定を管理できる。
  5. 設定ファイルがブログ記事になる … こんな感じです。Emacs プログラミング言語開発環境 | Futurismo
  6. 読みやすい。他人に見せやすい。… とくに github にあげるといい感じにシンタックスハイライトしてくれる。
  7. 書いていて楽しい!!

私の Emacs 起動方法

以下、自分き Emacs の起動順序について抜粋しながら書く。

フォルダ構成

フォルダ構成はこんな感じ。

.emacs.d
  |- init.el ... 一番初めに起動されるファイル
  |- inits ... org ファイルが入っているディレクトリ
       |- 00_init.org
       |- ....
       |- 90_color.org
  |- el-get
      |- repo 
          |- el-get 
          |- el-get で取得したパッケージ群
      |- user-recipes ... el-get 用の自分のレシピ

init.el: el-get

まずは、el-get を一番初めにダウンロードする。

;; el-get ロードパス設定
(add-to-list 'load-path (locate-user-emacs-file "el-get/repo/el-get"))

;; ダウンロードした elisp 置き場
(setq el-get-dir "~/.emacs.d/el-get/repo")

;; ダウンロードしていないときはダウンロード
(unless (require 'el-get nil 'noerror)
  (with-current-buffer
      (url-retrieve-synchronously
       "http://raw.github.com/dimitri/el-get/master/el-get-install.el")
    (let (el-get-master-branch)
      (goto-char (point-max))
      (eval-print-last-sexp))))

;; 初期化処理用
(setq el-get-user-package-directory "~/.emacs.d/el-get/init-files")

;; レシピ置き場
;; 追加のレシピ置き場
(add-to-list 'el-get-recipe-path "~/.emacs.d/el-get/user-recipes")

init.el: org-mode

org-mode を読み込む。load-path に

;; org-mode/lisp, org-mode/contribe/lisp をロードパスに追加する
(let* ((org-dir (expand-file-name
                 "lisp" (expand-file-name
                         "org-mode" el-get-dir)))
       (org-contrib-dir (expand-file-name
                         "lisp" (expand-file-name
                                 "contrib" (expand-file-name
                                            ".." org-dir)))))
  (setq load-path (append (list org-dir org-contrib-dir)
                          (or load-path nil))))
(require 'org)

init.el: init-loader

(el-get-bundle emacs-jp/init-loader)

;; バイトコンパイルする
;; 初めのバイトコンパイルは手動で実施する必要がある
(setq init-loader-byte-compile t)

;; エラー発生時にだけ log を開く
;; (setq init-loader-show-log-after-init t)
(setq init-loader-show-log-after-init 'error-only)

init.el: babel-loader

el-get で babel-loader をインストール

(el-get-bundle takaishi/babel-loader.el)
(add-to-list 'load-path (locate-user-emacs-file "el-get/repo/babel-loader.el"))
(require 'babel-loader)

;; インデント保持
;; これをしないと 変換された elisp ファイルのインデントがずれる.
(setq org-src-preserve-indentation t)

;; inits 配下の org ファイルを elc に変換して読み込み.
(bl:load-dir "~/.emacs.d/inits/")

inits:00_init.org フォルダを再帰的にロードパスに追加

;; @ load-path
;; for Emacs 23 under
(defvar user-emacs-directory "~/.emacs.d")

;; load-path の追加関数
(defun add-to-load-path (&rest paths)
  (let (path)
    (dolist (path paths paths)
      (let ((default-directory (expand-file-name (concat user-emacs-directory path))))
    (add-to-list 'load-path default-directory)
    (if (fboundp 'normal-top-level-add-subdirs-to-load-path)
        (normal-top-level-add-subdirs-to-load-path))))))

;; load-path に追加するフォルダ
;; 2 つ以上フォルダを指定する場合の引数 => (add-to-load-path "elisp" "xxx" "xxx")
(add-to-load-path "elisp" "inits" "el-get" "local" "mylisp")

inits:00_init.org: use-package

パッケージ管理のパッケージ

(package-initialize nil)
(el-get-bundle use-package)

;; use-package が存在しないときはなにもしない
(add-to-list 'load-path "~/.emacs.d/el-get/repo/use-package")
(unless (require 'use-package nil t)
  (defmacro use-package (&rest args)))

inits:00_init.org: el-get 同期 Package

el-get で自動にインストールするパッケージをひたすら列挙。

(defvar my/el-get-packages-all
  '(
    ;; 03_display
    popwin
    switch-window
    isearch-dabbrev
    ;; open-junk-file
    iy-go-to-char
    key-chord
    jump-char
    recentf-ext
    stripe-buffer

    ;; 20_text
    hydra
    swiper
    yasnippet
    dired-k
    migemo
    undo-tree
    define-word
    auto-complete
    anzu
    auto-highlight-symbol
    highlight-symbol
    multiple-cursors
    bm
    emacs-async
    pcre2el
    ht
    iedit
    codic
    search-web
    wgrep
    expand-region
    ag
    auto-capitalize
    omni-kill

    ;; 以下省略
    )
  "A list of packages to install from el-get at launch.")

inits: 00_init.org el-get config

;; 通知は minibuffer のみ
(setq el-get-notify-type 'message)

;; パッケージをインストール
(el-get 'sync my/el-get-packages-all)

inits: 01_global.org … 90_color.org

babel-loader によって、次々と org ファイルを el に変換して読み込んでいく。

Special Thanks

01 Jan 2017, 18:23

タグ管理が徹底した爆速メールシステム!Emacs の notmuch で Gmail を読む

motmuch というメールシステムを導入したので、導入手順をまとめます。

notmuch とは

notmuch とは、タグベースの高速検索メールシステムだ。

タグベースというところが気にいって、今回試してみた。

日本語情報が皆無なので、先駆者になれるかと思って使ってみる。

前回、同じコンセプトのタグ管理メールシステム mu4e について調べた。

今回は、ライバルの notmuch ということだ。

環境

<div id="text-orge333d36" class="outline-text-3">
  <ul class="org-ul">
    <li>
      Ubuntu 16.04 LTS
    </li>
    <li>
      notmuch 0.23.4… タグづけツール
    </li>
    <li>
      Offlineimap 6.6.1 … ローカルディレクトリとリモートフォルダを同期するツール
    </li>
    <li>
      msmtp 1.6.6… smtpmail を軽量化したメール送信用ツール
    </li>
  </ul>
</div>

インストール方法

Ubuntu にインストールする。

[sourcecode language=”bash” title=””]
sudo apt-get install notmuch
[/sourcecode]

端末上で notmuch setup を入力すると、簡単なガイダンスが始まる。

質問に答えていく。mkdir ~/mail で notmuch 用のフォルダを作成。

そのあと、notmuch new と入力する。.~/mail/.notmuch という DB フォルダが作成される。

Emacs Frontend Interface の導入

notmuch は Emacs 専用ソフトではない。いろんなフロントエンド I/F が用意されている。 (cli, vim, emacs, mutt)

しかし、Emacs でメールを閲覧することが目的なので、Emacs I/F をインストールする。

git repository からインストールすることが推奨されている。

[sourcecode language=”bash” title=””]
sudo apt-get install libxapian-dev libgmime-2.6-dev libtalloc-dev zlib1g-dev python-sphinx
git clone git://notmuchmail.org/git/notmuch
./configure
make
make install
[/sourcecode]

notmuch の Emacs 設定

[sourcecode language=”emacs-lisp” title=””]
(require ‘notmuch)
[/sourcecode]

メールを受信する

Offlineimap

<div id="text-org5a40e6d" class="outline-text-3">
  <p>
    IMAP サーバーからメールを同期する Python ユーティリティ.
  </p>

  <ul class="org-ul">
    <li>
      <a href="https://wiki.archlinuxjp.org/index.php/OfflineIMAP">OfflineIMAP &#8211; ArchWiki</a>
    </li>
  </ul>

  <p>
    [sourcecode language=&#8221;bash&#8221; title=&#8221;&#8221;]<br /> sudo apt-get -y install offlineimap<br /> [/sourcecode]
  </p>

  <p>
    ~/.offlineimaprc を作成する。ここでは、Inbox と Notes と Drafts を同期するように設定している。
  </p>

  <p>
    [sourcecode language=&#8221;text&#8221; title=&#8221;&#8221;]<br /> [general]<br /> accounts = main
  </p>

  <p>
    [Account main]<br /> localrepository = main-local<br /> remoterepository = main-remote
  </p>

  <p>
    [Repository main-local]<br /> type = Maildir<br /> localfolders = ~/mail/Gmail
  </p>

  <p>
    [Repository main-remote]<br /> type = Gmail<br /> # maxconnections=1<br /> remoteuser = fox10225fox@gmail.com<br /> remotepass =<br /> # realdelete=no<br /> folderfilter = lambda foldername: foldername in ["INBOX", "Notes", "[Gmail]/Drafts"]<br /> sslcacertfile = /etc/ssl/certs/ca-certificates.crt<br /> [/sourcecode]
  </p>

  <p>
    ターミナルより、offlineimap を入力することで、メールボックスを同期できる。
  </p>
</div>

<div id="outline-container-orga70d1d5" class="outline-4">
  <h4 id="orga70d1d5">
    パスワードをかくす
  </h4>

  <div id="text-orga70d1d5" class="outline-text-4">
    <p>
      設定ファイルは github で管理したいのだが、パスワードを晒すわけにはいかない。 netrc が使える。
    </p>

    <p>
      [sourcecode language=&#8221;bash&#8221; title=&#8221;&#8221;]<br /> touch ~/.netrc<br /> chmod 600 ~/.netrc<br /> [/sourcecode]
    </p>

    <p>
      .netrc の中身は次の通り。
    </p>

    <p>
      [sourcecode language=&#8221;text&#8221; title=&#8221;&#8221;]<br /> machine imap.gmail.com<br /> login fox10225fox@gmail.com<br /> password<br /> machine smtp.gmail.com<br /> login fox10225fox@gmail.com<br /> password<br /> [/sourcecode]
    </p>
  </div>
</div>

<div id="outline-container-org4f75ad7" class="outline-4">
  <h4 id="org4f75ad7">
    デーモン化
  </h4>

  <div id="text-org4f75ad7" class="outline-text-4">
    <p>
      offlineimap を定期的に動作させるためには、systemd サービスに登録する必要がある。 以下の wiki に手順が載っている。
    </p>

    <ul class="org-ul">
      <li>
        <a href="https://wiki.archlinuxjp.org/index.php/OfflineIMAP#.E3.83.90.E3.83.83.E3.82.AF.E3.82.B0.E3.83.A9.E3.82.A6.E3.83.B3.E3.83.89.E3.81.A7_offlineimap_.E3.82.92.E5.AE.9F.E8.A1.8C">OfflineIMAP &#8211; ArchWiki</a>
      </li>
    </ul>

    <p>
      または、.offlineimaprc の[Account]欄に以下を書く。
    </p>

    <p>
      [sourcecode language=&#8221;bash&#8221; title=&#8221;&#8221;]<br /> autorefresh = 1<br /> [/sourcecode]
    </p>

    <p>
      cron に登録してもよい。
    </p>
  </div>
</div>

<div id="outline-container-org1304050" class="outline-4">
  <h4 id="org1304050">
    Post-sync hook
  </h4>

  <div id="text-org1304050" class="outline-text-4">
    <p>
      メールを受信したら、notmuch new を動作させて、インデックスを作成する。
    </p>

    <p>
      .offlineimaprc の[Account]欄に以下を書く。
    </p>

    <p>
      [sourcecode language=&#8221;bash&#8221; title=&#8221;&#8221;]<br /> postsynchook = /usr/bin/offlineimap-postsync<br /> [/sourcecode]
    </p>

    <p>
      offlineimap-postsync というスクリプトを作成する。そのなかに notmuch new と書く。
    </p>

    <p>
      以下のファイルが参考になる。 この例では、notify-send で通知を表示したりログしたりしている。
    </p>

    <ul class="org-ul">
      <li>
        <a href="https://github.com/cbancroft/config/blob/master/mail/lib/offlineimap-postsync.sh">https://github.com/cbancroft/config/blob/master/mail/lib/offlineimap-postsync.sh</a>
      </li>
    </ul>
  </div>
</div>

メールを検索する

基本は、search 欄にキーワードを入れて検索する。

helm-i/f がある。

メールを送信する

msmtp を使う。

[sourcecode language=”emacs-lisp” title=””]
$ git clone git://git.code.sf.net/p/msmtp/code msmtp
$ cd msmtp
$ autoreconf -i
$ ./configure; make; make install
[/sourcecode]

.emacs の設定は以下の通り。

[sourcecode language=”emacs-lisp” title=””]
;; use msmtp
(setq message-send-mail-function ‘message-send-mail-with-sendmail)
(setq sendmail-program "msmtp")
;; tell msmtp to choose the SMTP server according to the from field in the outgoing email
(setq message-sendmail-extra-arguments ‘("–read-envelope-from"))
(setq message-sendmail-f-is-evil ‘t)

;; don’t keep message buffers around
(setq message-kill-buffer-on-exit t)
[/sourcecode]

Tips

ショートカット

<div id="text-org2fea8e0" class="outline-text-3">
  <p>
    [sourcecode language=&#8221;emacs-lisp&#8221; title=&#8221;&#8221;]<br /> (define-key notmuch-show-mode-map "\C-c\C-o" &#8216;browse-url-at-point)
  </p>

  <p>
    (define-key notmuch-search-mode-map "g"<br /> &#8216;notmuch-poll-and-refresh-this-buffer)<br /> (define-key notmuch-hello-mode-map "g"<br /> &#8216;notmuch-poll-and-refresh-this-buffer)
  </p>

  <p>
    (define-key notmuch-search-mode-map "d"<br /> (lambda ()<br /> "toggle deleted tag for thread"<br /> (interactive)<br /> (if (member "deleted" (notmuch-search-get-tags))<br /> (notmuch-search-tag &#8216;("-deleted"))<br /> (notmuch-search-tag &#8216;("+deleted" "-inbox" "-unread")))))
  </p>

  <p>
    (define-key notmuch-search-mode-map "!"<br /> (lambda ()<br /> "toggle unread tag for thread"<br /> (interactive)<br /> (if (member "unread" (notmuch-search-get-tags))<br /> (notmuch-search-tag &#8216;("-unread"))<br /> (notmuch-search-tag &#8216;("+unread")))))
  </p>

  <p>
    (define-key notmuch-show-mode-map "d"<br /> (lambda ()<br /> "toggle deleted tag for message"<br /> (interactive)<br /> (if (member "deleted" (notmuch-show-get-tags))<br /> (notmuch-show-tag &#8216;("-deleted"))<br /> (notmuch-show-tag &#8216;("+deleted" "-inbox" "-unread")))))
  </p>

  <p>
    (define-key notmuch-search-mode-map "a"<br /> (lambda ()<br /> "toggle archive"<br /> (interactive)<br /> (if (member "archive" (notmuch-search-get-tags))<br /> (notmuch-search-tag &#8216;("-archive"))<br /> (notmuch-search-tag &#8216;("+archive" "-inbox" "-unread")))))
  </p>

  <p>
    (define-key notmuch-show-mode-map "a"<br /> (lambda ()<br /> "toggle archive"<br /> (interactive)<br /> (if (member "archive" (notmuch-show-get-tags))<br /> (notmuch-show-tag &#8216;("-archive"))<br /> (notmuch-show-tag &#8216;("+archive" "-inbox" "-unread")))))
  </p>

  <p>
    (define-key notmuch-hello-mode-map "i"<br /> (lambda ()<br /> (interactive)<br /> (notmuch-hello-search "tag:inbox")))
  </p>

  <p>
    (define-key notmuch-hello-mode-map "u"<br /> (lambda ()<br /> (interactive)<br /> (notmuch-hello-search "tag:unread")))
  </p>

  <p>
    (define-key notmuch-hello-mode-map "a"<br /> (lambda ()<br /> (interactive)<br /> (notmuch-hello-search "tag:archive")))<br /> [/sourcecode]
  </p>
</div>

org-mode 連携

<div id="text-org56c985d" class="outline-text-3">
  <p>
    org-store-link が使える。
  </p>

  <p>
    [sourcecode language=&#8221;emacs-lisp&#8221; title=&#8221;&#8221;]<br /> (require &#8216;org-notmuch)<br /> (define-key global-map "\C-cl" &#8216;org-store-link)<br /> [/sourcecode]
  </p>
</div>

日本語ワードが検索で引っかからないときの対応

<div id="text-org7b11419" class="outline-text-3">
  <p>
    日本語ワードが検索でうまく引っかかってない。 いろいろ調べた結果、以下の記事にたどり着いた。 この方法で検索がうまく動くようになった。
  </p>

  <ul class="org-ul">
    <li>
      <a href="http://u7fa9.org/memo/HEAD/archives/2012-06/2012-06-01.rst">notmuch で日本語検索をいい感じにする &#8211; memo</a>
    </li>
  </ul>

  <p>
    [sourcecode language=&#8221;bash&#8221; title=&#8221;&#8221;]<br /> $ export XAPIAN_CJK_NGRAM=1<br /> $ notmuch dump > ~/Maildir/.notmuch/dump-$(date +%Y%m%d)<br /> $ mv ~/Maildir/.notmuch/xapian{,.old}<br /> $ notmuch new<br /> $ notmuch restore &#8211;input~/Maildir/.notmuch/dump-$(date +%Y%m%d)<br /> [/sourcecode]
  </p>
</div>

mu4e と notmuch との比較

mu4e の方が使いやすい。なぜなら、

  • notmuch には、メールの削除の方法がない(わからない)
  • Gmail との同機の方法が面倒。

notmuch が mu4e より優れている点は、

  • タグ管理が より mu4e に比べて徹底している

削除の機能がないというところを考えると、 notmuch はそもそも膨大なデータを検索するためのソフトウェアで タグによる検索に徹底していて、 削除など必要ないという設計思想なのかもしれない。

この記事によると、mu4e よりも、notmuch のほうが圧倒的に高速のようだ。

purely tag and search based mail client

mu4e のほうが一見使いやすくみえるが、 上の記事を読むと最終的には notmuch に軍配が上がるのではないか?

よし、決めたぞ。notmuch を使うことにしよう。迷ったときは、マイナーな方を選ぶのだ!

01 Jan 2017, 13:26

タグ管理という新たな世界観!!Emacs の mu4e で Gmail を読む

mu というタグメールシステムを導入したので、導入手順をまとめます。

mu4e とは

notmuch とは、タグベースの高速検索メールシステムだ。

タグベースというところが気にいって、今回試してみた。

これまで、ファイルベースのメーラが世を席巻してきた。

しかし、21 世紀はタグでデータを管理する時代なのだ!

そのことは、この本にかかれていた。

ファイラだと、FenrirFS というファイラが気に入っている。

メールだと、Gmail がある。じゃあ Gmail でいいじゃないかということになるが、 Gmail は Web ベースだ。 Emacs 好きとしては、Emacs から、メールを操作したい、というのが主な動機だ。

ちなみに、Mutt と Wanderlust は経験している。

環境と各ツールの役割

<div class="outline-text-3" id="text-org324f80a">
  <ul class="org-ul">
    <li>
      Ubuntu 16.04 LTS
    </li>
    <li>
      mu 0.9.18&#x2026; タグづけ検索メールシステム
    </li>
    <li>
      mu4e 0.9.18&#x2026; mu の フロントエンド I/F
    </li>
    <li>
      Offlineimap 6.6.1 &#x2026; ローカルディレクトリとリモートフォルダを同期するツール
    </li>
    <li>
      msmtp 1.6.6&#x2026; smtpmail を軽量化したメール送信用ツール
    </li>
  </ul>
</div>

インストール方法

事前の依存ライブラリのインストール

[sourcecode language=”bash” title=”” ]
# must
$ sudo apt-get install libgmime-2.6-dev libxapian-dev gnutls-bin

# optional
$ sudo apt-get install guile-2.0-dev html2text xdg-utils
[/sourcecode]

mu のインストール

<div class="outline-text-3" id="text-orga0fbd05">
  <p>
    github から最新版の mu ををインストール。
  </p>

  <ul class="org-ul">
    <li>
      <a href="https://github.com/djcb/mu/releases">https://github.com/djcb/mu/releases</a>
    </li>
  </ul>

  <p>
    [sourcecode language=&#8221;bash&#8221; title=&#8221;&#8221; ]<br /> ./configure && make<br /> sudo make install<br /> [/sourcecode]
  </p>
</div>

mu4e(Emacs Frontend Interface) の導入

<div class="outline-text-3" id="text-orga936df7">
  <p>
    mu をインストールすると、サブディレクトリに mu4e というものがあり その中に elisp が入っている。
  </p>

  <p>
    [sourcecode language=&#8221;emacs-lisp&#8221; title=&#8221;&#8221; ]<br /> (require &#8216;mu4e)<br /> (setq user-mail-address &#8220;fox10225fox@gmail.com&#8221;<br /> user-full-name &#8220;Tsunemichi Harada&#8221;)
  </p>

  <p>
    (setq mu4e-maildir &#8220;~/Maildir&#8221;)<br /> (setq mu4e-drafts-folder &#8220;/[Gmail].Drafts&#8221;)<br /> (setq mu4e-sent-folder &#8220;/[Gmail].Sent Mail&#8221;)<br /> (setq mu4e-trash-folder &#8220;/[Gmail].Trash&#8221;)<br /> ;; U で 更新するときに使うプログラム<br /> (setq mu4e-get-mail-command &#8220;offlineimap&#8221;)<br /> [/sourcecode]
  </p>
</div>

メールを受信する

2つのツールがある。

mbsync のほうがいい??

今回は、日本語情報の多い Offlineimap を使う。

Offlineimap

<div class="outline-text-3" id="text-org410064b">
  <p>
    IMAP サーバーからメールを同期する Python ユーティリティ.
  </p>

  <ul class="org-ul">
    <li>
      <a href="https://wiki.archlinuxjp.org/index.php/OfflineIMAP">OfflineIMAP &#8211; ArchWiki</a>
    </li>
  </ul>

  <p>
    [sourcecode language=&#8221;bash&#8221; title=&#8221;&#8221; ]<br /> sudo apt-get -y install offlineimap<br /> [/sourcecode]
  </p>

  <p>
    ~/.offlineimaprc を作成する。 ここでは、Inbox と Notes と Drafts を同期するように設定している。
  </p>

  <p>
    [sourcecode language=&#8221;text&#8221; title=&#8221;&#8221; ]<br /> [general]<br /> accounts = Gmail
  </p>

  <p>
    [Account Gmail]<br /> localrepository = Local<br /> remoterepository = Remote
  </p>

  <p>
    [Repository Local]<br /> type = Maildir<br /> localfolders = ~/Maildir
  </p>

  <p>
    [Repository Remote]<br /> type = Gmail<br /> folderfilter = lambda foldername: foldername in [&#8220;INBOX&#8221;, &#8220;Notes&#8221;, &#8220;[Gmail]/Drafts&#8221;]<br /> sslcacertfile = /etc/ssl/certs/ca-certificates.crt<br /> maxconnections = 1<br /> realdelete = no<br /> [/sourcecode]
  </p>

  <p>
    ターミナルより、offlineimap を入力することで、メールボックスを同期できる。
  </p>
</div>

パスワードをかくす

<div class="outline-text-3" id="text-org60c8fd9">
  <p>
    設定ファイルは github で管理したいのだが、パスワードを晒すわけにはいかない。 netrc が使える。
  </p>

  <p>
    [sourcecode language=&#8221;bash&#8221; title=&#8221;&#8221; ]<br /> touch ~/.netrc<br /> chmod 600 ~/.netrc<br /> [/sourcecode]
  </p>

  <p>
    .netrc の中身は次の通り。
  </p>

  <p>
    [sourcecode language=&#8221;text&#8221; title=&#8221;&#8221; ]<br /> machine imap.gmail.com<br /> login fox10225fox@gmail.com<br /> password <your password here><br /> machine smtp.gmail.com<br /> login fox10225fox@gmail.com<br /> password <your password here><br /> [/sourcecode] </div> </div> 

    <div id="outline-container-orgb2c067a" class="outline-3">
      <h3 id="orgb2c067a">
        定期的に動作させる
      </h3>

      <div class="outline-text-3" id="text-orgb2c067a">
        <p>
          できれば定期的に動作させたい。 以下で、5 分ごとにバックグラウンドでポーリングできる。
        </p>

        <p>
          [sourcecode language=&#8221;emacs-lisp&#8221; title=&#8221;&#8221; ]<br /> (setq mu4e-update-interval 300)<br /> [/sourcecode]
        </p>
      </div>
    </div>

    <div id="outline-container-org201a44a" class="outline-3">
      <h3 id="org201a44a">
        メール受信通知を受けたい
      </h3>

      <div class="outline-text-3" id="text-org201a44a">
        <p>
          mu4e-alert という elisp がある。
        </p>

        <ul class="org-ul">
          <li>
            <a href="https://github.com/iqbalansari/mu4e-alert">https://github.com/iqbalansari/mu4e-alert</a>
          </li>
        </ul>

        <p>
          [sourcecode language=&#8221;emacs-lisp&#8221; title=&#8221;&#8221; ]<br /> (require &#8216;mu4e-alert)<br /> ;; デスクトップ通知<br /> (when linux-p<br /> ;; デスクトップ通知<br /> (mu4e-alert-set-default-style &#8216;libnotify))<br /> (add-hook &#8216;after-init-hook #&#8217;mu4e-alert-enable-notifications)<br /> ;; モードライン通知<br /> (add-hook &#8216;after-init-hook #&#8217;mu4e-alert-enable-mode-line-display)<br /> [/sourcecode]
        </p>
      </div>
    </div></div> 

    <div id="outline-container-org28257c7" class="outline-2">
      <h2 id="org28257c7">
        メールを検索する
      </h2>

      <div class="outline-text-2" id="text-org28257c7">
        <p>
          mu4e を開いて、更新 U を押すと、Offlineimap が走ってメールを受信し、 mu が走ってタグ付けされる。
        </p>
      </div>

      <div id="outline-container-org9214a97" class="outline-3">
        <h3 id="org9214a97">
          helm-mu
        </h3>

        <div class="outline-text-3" id="text-org9214a97">
          <p>
            helm I/F で検索できる。
          </p>

          <ul class="org-ul">
            <li>
              <a href="https://github.com/emacs-helm/helm-mu">https://github.com/emacs-helm/helm-mu</a>
            </li>
          </ul>

          <p>
            [sourcecode language=&#8221;emacs-lisp&#8221; title=&#8221;&#8221; ]<br /> (require &#8216;helm-mu)<br /> (setq helm-mu-default-search-string &#8220;(maildir:/INBOX OR maildir:/Sent)&#8221;)<br /> (define-key mu4e-main-mode-map &#8220;s&#8221; &#8216;helm-mu)<br /> (define-key mu4e-headers-mode-map &#8220;s&#8221; &#8216;helm-mu)<br /> (define-key mu4e-view-mode-map &#8220;s&#8221; &#8216;helm-mu)<br /> [/sourcecode]
          </p>
        </div>
      </div>
    </div>

    <div id="outline-container-org6d9c03d" class="outline-2">
      <h2 id="org6d9c03d">
        メールを送信する
      </h2>

      <div class="outline-text-2" id="text-org6d9c03d">
        <p>
          sendmail ライブラリが Emacs にデフォルトで搭載されていたけれども、 動かなかった。。。 msmtp を使う。
        </p>

        <p>
          [sourcecode language=&#8221;emacs-lisp&#8221; title=&#8221;&#8221; ]<br /> $ git clone git://git.code.sf.net/p/msmtp/code msmtp<br /> $ cd msmtp<br /> $ autoreconf -i<br /> $ ./configure; make; make install<br /> [/sourcecode]
        </p>

        <p>
          .emacs の設定は以下の通り。
        </p>

        <p>
          [sourcecode language=&#8221;emacs-lisp&#8221; title=&#8221;&#8221; ]<br /> ;; use msmtp<br /> (setq message-send-mail-function &#8216;message-send-mail-with-sendmail)<br /> (setq sendmail-program &#8220;msmtp&#8221;)<br /> ;; tell msmtp to choose the SMTP server according to the from field in the outgoing email<br /> (setq message-sendmail-extra-arguments &#8216;(&#8220;&#8211;read-envelope-from&#8221;))<br /> (setq message-sendmail-f-is-evil &#8216;t)
        </p>

        <p>
          ;; don&#8217;t keep message buffers around<br /> (setq message-kill-buffer-on-exit t)<br /> [/sourcecode]
        </p>
      </div>
    </div>

    <div id="outline-container-org9ac4b3e" class="outline-2">
      <h2 id="org9ac4b3e">
        参考
      </h2>

      <div class="outline-text-2" id="text-org9ac4b3e">
        <ul class="org-ul">
          <li>
            <a href="http://wenshanren.org/archives/=111#Message-complete">mu4e: an E-mail Client for Emacs | 肉山博客 (Wenshan&#8217;s Blog)</a>
          </li>
          <li>
            <a href="http://qiita.com/kaz-yos/items/164f03c7bba401646783">mu4e でメール &#8211; Qiita</a>
          </li>
        </ul>
      </div>
    </div>

01 Jan 2017, 07:00

GNU Emacs 25.1 を Ubuntu16.04 LTS にソースからビルドしてインストールする

2016 年 917 に Emacs25.1 がリリースされたのですが、Ubuntu16.04 LTS で apt-get で Emacs を インストールすると、Emacs24.5 がインストールされてしまう。

なので、ソースコードから Emacs25.1 をインストールすることにした。

事前準備

以下のモジュールを入れておく。

[sourcecode language=”bash” title=”” ]
sudo apt-get install build-essential checkinstall
[/sourcecode]

Emacs24 に依存するライブラリをインストールする。 Emacs 24 と 25 は、同じ依存関係を持っている。

なお、デフォルトでは、build-dep ができないので、 以下を参考に設定を有効にする。

[sourcecode language=”bash” title=”” ]
sudo su -c “grep ‘^deb ‘ /etc/apt/sources.list | \
sed ‘s/^deb/deb-src/g’ > /etc/apt/sources.list.d/deb-src.list”

sudo apt-get build-dep emacs24
[/sourcecode]

Emacs のインストール

ダウンロード

<div class="outline-text-3" id="text-orge86a210">
  <p>
    GNU のページから Emacs のアーカイブをダウンロードして、解凍する。
  </p>

  <ul class="org-ul">
    <li>
      <a href="http://ftp.gnu.org/gnu/emacs/">http://ftp.gnu.org/gnu/emacs/</a>
    </li>
  </ul>

  <p>
    [sourcecode language=&#8221;bash&#8221; title=&#8221;&#8221; ]<br /> wget https://ftp.gnu.org/gnu/emacs/emacs-25.1.tar.gz<br /> tar xf emacs-25.1.tar.gz<br /> cd emacs-25.1<br /> [/sourcecode]
  </p>
</div>

ビルド

<div class="outline-text-3" id="text-org74540f1">
  [sourcecode language=&#8221;bash&#8221; title=&#8221;&#8221; ]<br /> ./configure</p> 

  <p>
    # エラーしたので以下を追加で入れた。<br /> sudo apt-get install libxpm-dev libjpeg-dev libgif-dev libtiff5-dev
  </p>

  <p>
    ./configure<br /> make<br /> [/sourcecode]
  </p>
</div>

インストール

<div class="outline-text-3" id="text-org8aa474e">
  <p>
    sudo make install ではなくて、sudo checkinstall を使う。
  </p>

  <p>
    [sourcecode language=&#8221;bash&#8221; title=&#8221;&#8221; ]<br /> sudo checkinstall<br /> [/sourcecode]
  </p>

  <p>
    deb パッケージが作成されて、インストールされる。emacs_25.1-1_amd64.deb
  </p>
</div>

アンインストール

<div class="outline-text-3" id="text-orgc20b1d8">
  [sourcecode language=&#8221;bash&#8221; title=&#8221;&#8221; ]<br /> # sudo dpkg -r emacs-25<br /> [/sourcecode]
</div>

追記: 170102 もっとお手軽な方法

deb パッケージが配布されていた。

[sourcecode language=”bash” title=”” ]
sudo add-apt-repository ppa:kelleyk/emacs
sudo apt-get update
sudo apt-get install emacs25
[/sourcecode]

29 Dec 2016, 07:52

fish で Emacs とターミナルのディレクトリを行ったり来たり。dired と cde を移植した。

zsh で大変お世話になっていたコマンド、dired と cde を fish に移植した。

dired

ターミナル上の fish で dired とタイプすると、 現在のディレクトリを Emacs の dired で開いてくれる。

function dired 
        emacsclient -e "(dired \"$PWD\")"
end

cde

ターミナル上で cde とタイプすると、 Emacs の現在のバッファに対応するディレクトリをターミナル上の fish で開いてくれる。

function cde
        emacsclient -e "(return-current-working-directory-to-shell)" | sed 's/^"\(.*\)"$/\1/' | read EMACS_CWD
        echo "chdir to $EMACS_CWD"
        cd "$EMACS_CWD"        
end

以下は、init.el に定義。

(defun return-current-working-directory-to-shell ()
  (expand-file-name
   (with-current-buffer
       (if (featurep 'elscreen)
           (let* ((frame-confs (elscreen-get-frame-confs (selected-frame)))
                  (num (nth 1 (assoc 'screen-history frame-confs)))
                  (cur-window-conf
                   (assoc 'window-configuration
                          (assoc num (assoc 'screen-property frame-confs))))
                  (marker (nth 2 cur-window-conf)))
             (marker-buffer marker))
         (nth 1
              (assoc 'buffer-list
                     (nth 1 (nth 1 (current-frame-configuration))))))
     default-directory)))

21 Dec 2016, 13:27

Emacs で Racket 開発環境を構築

coursera で Programming Languages , PartB を受講し始めた。

開発環境で DrRacket(Racket をインストールするとついてくる開発環境)が指定される のだけれども、Emacs Love な自分はどうしても Emacs からやりたかったので、 Emacs で Racket 開発環境を構築した。

環境

  • Ubuntu 16.04 LTS
  • Racket v6.3

Racket のインストール

sudo apt-get install racket

これで /usr/bin/配下に racket がインストールされる。

優れた IDE の条件

優れた IDE が備えるべき機能は以下.

  • シンタックスハイライト/ インデント
    • racket-mode, aggressive-indent
  • 検索・置換 iedit, multiple-cursors, helm-ag, helm-swoop
  • タグジャンプ racket-visit-definition
  • コード補間
    • auto-complete
    • tab で complete
  • エラーチェック
    • flycheck
  • インタープリタ・デバッカ racket-repl

racket-mode

Racket の開発環境は、24.2 Emacs によると

  • racket-mode
  • Quack
  • Geiser

などがある。

今回は、新しめの racket-mode を利用することにした。 インストールは M-x el-get-install でした。

(require 'racket-mode)
;; tab で補間
(setq tab-always-indent 'complete)

aggressive-indent

賢い indent-mode

names package に依存しているので, require ‘names してからインストールしないとおかしくなる.

(add-hook 'racket-mode-hook #'aggressive-indent-mode)

smartparens

smart + parens カッコ移動を楽々。

(require 'smartparens-config)

auto-complete-mode

補間

(require 'auto-complete)
(add-to-list 'ac-modes 'racket-mode)

RainbowDelimiters

かっこの深さに応じて色付けしてくれる.

(add-hook 'prog-mode-hook #'rainbow-delimiters-mode)

flycheck

エラーチェック

(require 'flycheck)
(add-hook 'after-init-hook #'global-flycheck-mode)

quickrun

ファイルを実行できる。

quickrun は最近 Racket に対応したようだ。

(require 'quickrun)

参考 URL

19 Dec 2016, 01:11

Windows 環境で Emacs で 自動スペルチェック(aspell, flyspell)

Windows 環境で、Emacs で英文を書くとき、Word のようなスペルチェックをしたい。

そんなときのための、Tips を紹介。ちょっと設定ではまったのて、メモ。

環境

  • NTEmacs 25.1.1

aspell をインストール

aspell というツールをつかうと、スペルチェックが可能になる。 ダウンロードは以下から。

ダウンロードしたファイルを開くとインストールがはじまるので、インストール。

aspell の設定

Emacs の設定ファイルに以下を書く。

;; aspell のインストールパス
(add-to-list 'exec-path "C:/Program Files (x86)/Aspell/bin/")
(require 'ispell)
;; スペルチェックに aspell を使う
(setq ispell-program-name "aspell")
;; 日本語と英語の共存設定
(eval-after-load "ispell"
  '(add-to-list 'ispell-skip-region-alist '("[^\000-\377]+")))

 ホームディレクトリに .aspell.conf というファイルを作成して、以下を記入。

lang en_US

そうしないと、以下のようなエラーがでる。

Error: No word lists can be found for the language "ja_JP".

flyspell-mode

自動で英文チェックしてくれるパッケージ。M-x flyspell-mode で有効にする。

または、以下のように自動で有効にしてもよい。

(mapc
 (lambda (hook)
   (add-hook hook 'flyspell-mode))
 '(text-mode-hook
   org-mode-hook
   wl-draft-mode-hook
   twittering-edit-mode))

参考