term+のセッションをhelmで選択

第6回関西emacs勉強会(http://peccu.sytes.net/ke/)で紹介されたterm+.el(taraoさん作Emacs上のターミナルを最強に: term+.el - 貳佰伍拾陸夜日記)。
めちゃくちゃ便利で日頃から使わせてもらってる。
helmで表示されるbuffer-listからいつもセッションを選択していたのだが...sessionリストだけから、helmで選択したいなと思い、作ってみました。
popwinを内部で使ってるのでpopwinを入れてないとhelm-source-term+-new-sessionは動かないです...
ふぅ~これでさらに便利になった。taraoさんには感謝です。

sessionを新たに開いた場合にother-windowやpopupで開くのに苦労した...
"open session in popup window"と"open session in other window"はうまく動かない環境があるかもしれません...

誰かもっとうまい実装法があれば...教えてください...教えてエロい人!

2013/3/24追記 term+mux-new-other-windowって関数がいつのまにか追加されてたらしい。それを使うように変更。

必要elisp

1. term+
2. helm
3. popwin


(defun helm-term+-sessions ()
  (interactive)
  (helm-other-buffer '(helm-source-term+-sessions
                       helm-source-term+-new-session
                       )
                     "*helm-term+-sessions*"))


(defvar helm-source-term+-new-session
      '((name . "Create new session")
        (dummy)
        (action . (("open session" . (lambda (name)
                                       (when (eq name "")
                                         (setq name system-name))
                                       (term+mux-new (term+mux-new-session name))))
                   ("open session in popup window" . (lambda (name)
                                                       (popwin:popup-buffer (current-buffer))
                                                       (when (eq name "")
                                                         (setq name system-name))
                                                       (term+mux-new (term+mux-new-session name))
                                                       ))
                   ("open session in other window" . (lambda (name)
                                                       (when (eq name "")
                                                         (setq name system-name))
                                                       (term+mux-new-other-window (term+mux-new-session name))
                                                       ))))))


(defvar helm-source-term+-sessions
      `((name . "term+-session")
        (candidates . (lambda () (helm-term+-session-list)))
        (type . buffer)
        (match . helm-buffer-match-major-mode)
        (persistent-action . helm-buffers-list-persistent-action)
        (keymap . ,helm-buffer-map)
        (volatile)
        (mode-line . helm-buffer-mode-line-string)
        (persistent-help
         . "Show this buffer / C-u \\[helm-execute-persistent-action]: Kill this buffer")))

(defun helm-term+-session-list ()
  "Return the current list of term+ sessions.
Currently visible buffers are put at the end of the list.
See `ido-make-buffer-list' for more infos."
  (require 'ido)
  (let ((ido-process-ignore-lists t)
        ido-ignored-list
        ido-use-virtual-buffers
        term-lists)
    (dolist (buffer (ido-make-buffer-list nil) term-lists)
      (when (string-match "^term:" buffer)
        (setq term-lists (append term-lists (list buffer)))))))

mu4e(emacsのメールクライアント)

emacsでメールと言えば、wanderlust, mew等が有名だが、最近mu4e(mu4e: an e-mail client for emacs)ってのがあって割とよいらしい!
というのを、一ヶ月程以上前の@さん主催の関西emacs勉強会で聞いたので重い腰を上げて導入してみた。


仕組みざっくり言うと、offlineimap等でローカルにMaildir形式のメールディレクトリを作成し、muでそのデータベースを作成する。
そして、mu4eでmuをemacsから使ってメールを読んだり表示するようだ。

入れ方はマニュアルに書いてあるので、省略して...
普段メールアカウント(Gmail, work)を二つ使ってるのでその設定を記しておきます。


まず、offlineimapの設定として、以下の~/.offlineimaprcと~/.offlineimap.pyを準備する。
私用のメールサーバーは色々適当に設定してあるので、適宜読み変えてください!

[general]
accounts = Gmail, work
maxsyncaccounts = 4
socktimeout = 60
pythonfile = ~/.offlineimap.py

[Account Gmail]
localrepository = LocalGmail
remoterepository = RemoteGmail

[Account work]
localrepository = Localwork
remoterepository = Remotework

[Repository LocalGmail]
type = Maildir
localfolders = ~/Maildir/Gmail

[Repository Localwork]
type = Maildir
localfolders = ~/Maildir/work


[Repository RemoteGmail]
type = IMAP
remotehost = imap.gmail.com
remoteuser = mygmail-address
remotepasseval = get_password_emacs("imap.gmail.com", "993")
ssl = yes
maxconnections = 1
realdelete = no
#同期しないメールディレクトリの設定
folderfilter = lambda foldername: foldername not in ["[Gmail]/Spam", "[Gmail]/Important"]

[Repository Remotework]
type = IMAP
remotehost = mywork-imap-server
remoteuser = mywork-user
remotepasseval = get_password_emacs("mywork-imap-server", "secret")
ssl = yes
maxconnections = 1
realdelete = no
#!/usr/bin/python
#encoding:utf-8
import subprocess


def get_output(cmd):
    # Bunch of boilerplate to catch the output of a command:
    pipe = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    (output, errout) = pipe.communicate()
    assert pipe.returncode == 0 and not errout
    return output

def get_password_emacs(host, port):
    cmd = "emacsclient --eval '(offlineimap-get-password \"%s\" \"%s\")'" % (host,port)
    return get_output(cmd).strip().lstrip('"').rstrip('"')



そして以下を.emacsに追加。

(when (require 'mu4e nil t)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;                         For Switching setting                      ;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  (setq mu4e-maildir "~/Maildir"
        mu4e-sent-folder "/work/INBOX.Sent"
        mu4e-drafts-folder "/work/INBOX.Drafts")

;; trashの自動選択
  (setq mu4e-trash-folder
        (lambda (msg)
          (cond
           ((string-match "/work/"
                          (or (mu4e-message-field msg :maildir) ""))
            "/work/INBOX.Trash")
           ((string-match "/Gmail/"
                          (or (mu4e-message-field msg :maildir) ""))
            "/Gmail/[Gmail].Trash")
           ))
        )

  (require 'smtpmail)

;; stmp serverの自動選択
  (setq my-mu4e-account-alist
        '(
          ("Gmail"
           (mu4e-sent-folder "/Gmail/[Gmail].Sent Mail")
           (mu4e-drafts-folder "/Gmail/[Gmail].Drafts")
           (user-mail-address "mygmail-address")
           (mu4e-sent-messages-behavior delete)
           (starttls-use-gnutls t)
           (smtpmail-starttls-credentials '(("smtp.gmail.com" 587 nil nil)))
           (smtpmail-auth-credentials '(("smtp.gmail.com" 587 "mygmail-address" nil)))
           (smtpmail-smtp-user "mygmail-address")
           (smtpmail-default-smtp-server "smtp.gmail.com")
           (smtpmail-smtp-server "smtp.gmail.com")
           (smtpmail-smtp-service 587)
           (message-signature nil)
           ;; add other variables here
           )
          ))
  (add-to-list 'jk-mu4e-account-alist
                 '("work"
                   (mu4e-sent-folder "/work/INBOX.Sent")
                   (mu4e-drafts-folder "/work/INBOX.Drafts")
                   (smtpmail-smtp-user "work-username")
                   (user-mail-address "work-address")
                   (mu4e-sent-messages-behavior sent)
                   (starttls-use-gnutls nil)
                   (smtpmail-default-smtp-server "work-smtpserver")
                   (smtpmail-smtp-server "worksmtpserver")
                   (smtpmail-smtp-service secret)
                   (message-signature (shell-command-to-string "cat ~/Mail/signature.txt"))
                   ;; add other variables here
                   ))

  (defun jk-mu4e-set-account ()
    "Set the account for composing a message."
    (let* ((account
            (if mu4e-compose-parent-message
                (let ((maildir (mu4e-msg-field mu4e-compose-parent-message :maildir)))
                  (string-match "/\\(.*?\\)/" maildir)
                  (match-string 1 maildir))
              (completing-read (format "Compose with account: (%s) "
                                       (mapconcat #'(lambda (var) (car var)) jk-mu4e-account-alist "/"))
                               (mapcar #'(lambda (var) (car var)) jk-mu4e-account-alist)
                               nil t nil nil (caar jk-mu4e-account-alist))))
           (account-vars (cdr (assoc account jk-mu4e-account-alist))))
      (if account-vars
          (mapc #'(lambda (var)
                    (set (car var) (cadr var)))
                account-vars))))
  (add-hook 'mu4e-compose-pre-hook 'jk-mu4e-set-account)

  (setq mu4e-maildir-shortcuts
        '(
          ("/work/INBOX"             . ?i)
          ("/work/INBOX.Sent" . ?s)
          ("/Gmail/Gmail" . ?g)
          ("/Gmail/INBOX" . ?n)
          ("/Gmail/[Gmail].Sent Mail" . ?e)
          ("/Gmail/[Gmail].All Mail" . ?a)
          ))





;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;                         For Default setting                        ;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;




  (require 'org-mu4e)
  (setq mu4e-headers-fields
        '((:date .  25)
          (:flags . 6)
          (:from . 22)
          (:subject . nil)))
  (setq mu4e-user-mail-address-regexp "mywork-addres\\|mygmail-address")
  (setq message-kill-buffer-on-exit t)
  (setq mu4e-html2text-command "html2text -utf8 -width 72")
  ;; (setq mu4e-html2text-command nil)
  (setq mail-user-agent 'mu4e-user-agent)
  (setq message-send-mail-function 'smtpmail-send-it)
  (setq mu4e-get-mail-command "offlineimap"
        mu4e-update-interval 300)
  (setq mu4e-use-fancy-chars nil)
  (setq mu4e-attachment-dir "~/Downloads")
  (setq mu4e-view-show-images t
        mu4e-view-image-max-width 800)
  (set-language-environment "UTF-8")
  ;; For encrypting password
  (require 'epa-file)
  (epa-file-enable)
  (setq auth-sources '("~/.authinfo.gpg" "~/.authinfo" "~/.netrc"))

  (require 'netrc)
  (defun offlineimap-get-password (host port)
    (let* ((netrc (netrc-parse (expand-file-name "~/.authinfo.gpg")))
           (hostentry (netrc-machine netrc host port port)))
      (when hostentry (netrc-get hostentry "password"))))
  )

後は
~/.authinfo.gpgに以下のように、
メールサーバーのpasswardやらを書いてやればOK!

machine imap.gmail.com login gmail-address port 993 password secret
machine mywork-imap-server login mywork-address port secret password secret


これらの設定で使うと...
~/Maildir/workと~/Maildir/Gmailのディレクトリにそれぞれのアカウントのメールが同期されます。
まぁ細かいことが色々と抜けてる気がしますが、こんな感じで設定しました!
ほとんどは、マニュアルとmu-discuss(Google グループ)に書いてある設定です。

使ってみた感想は、悪くない!
ただ、wanderlustに比べると機能はまだまだ少ないって感じですね...
まぁmu-discussを見てるとそれなりに議論が行なわているようなのでまだまだ機能の追加は今後あると思います。

gnuplotのコマンドまとめ(ループとかeveryとか)

gnuplotスクリプトを書いてたら、忘れてるのが一杯あって(主にループとeveryの構文)過去のスクリプトをあさったりしたので、まとめてみた。

gnuplotのループ文。

ループのための下準備

繰り返し構文以外に、以下のようなコマンドを使います

hoge = system("/bin/ls hoge*") lsした結果をhogeの変数の中に代入. (要するにsystemでshellコマンドの結果を受けとれる)
sprintf("%s_%d", string, 10) formatを設定した文字列を作成する。
hoge = string1 . string2 string1とstring2の文字列を連結

この3つを組み合わせてdo for文や、plot for文を使うと楽できまっせ!!!

plot for文
plot for [i=1:10] spritf("hoge%02d", i) t spritf("hoge%02d", i)

とやると、hoge01, hoge02,...hoge10をすべてplotしてくれます。

do for 文
dirnames = system("/bin/ls -d hoge*")
do for [dir in dirnames] {
  file = dir . "/dat"
  p file t file
  }

とかすると、hoge*/datにマッチするファイルを順番にプロットしてくれるよ!!
大量に画像化するときや、簡易animationを作るときに便利だね!!

ちなみにdo for文はgnuplot4.6からしか、使えないので注意!!



every 文

     every 行刻み:ブロック刻み:初期行:初期ブロック:終了行:終了ブロック
行刻み 何行ごとに読みこむか(デフォルト値=1, すべて読み込む)
ブロック刻み 何ブロックごとに読みこむか(デフォルト値=1, すべて読み込む)
初期行 何行目から始めるか
初期ブロック 何ブロック目から始めるか
終了行 何行目で終わるか
終了ブロック 何ブロック目で終わるか
plot for [i=0:10] 'hoge' every :::i::i

とすれば、各ブロックごとにプロットできるぞ!

ちなみに、gnuplotではブロックは、空白行があるとこまでを1ブロックとして認識するぞ!!

yasnippet0.8.0に更新し、動かなくなったyasnippet-config.elとanything-c-yasnippet.elを修正

なんかyasnippetリポジトリを見にいったら、0.8.0がリリースされてるじゃないか!ということでアップデートした。
そしたら... yasnippet-config.elとanything-c-yasnippet.elが動かない...

とりあえず、ソースコードを読んでみたら関数や変数の命名規則が変更されてた。
どうやら接頭語がyas/からprivateっぽい関数や変数にはyas--、publicっぽいのにはyas-に変更されているみたいだ。

取り敢えず動くように修正してgistに上げといたので、リンクを貼っとく。

anything-c-yasnippet.el

yasnippet-config.el

gdbを練習したのでメモ

  • tui オプションをつけるとDDDっぽくなる。Ctrl-x aで切り替え
コマンド 略称 効果
print p 引数の情報表示する
break b 引数の場所にbreakpointを設定する。
condition cond 引数の番号を持つbreakpointにif文追加
clear 引数のbreakpointを消去。引数の指定は設定のときと同じ。引数なしの場合は次のbreakpointを消去
list 引数の場所にフォーカス
info breakpoints breakpointの情報表示
tbreak tb 一回だけのbreakpoint設定
delete del 引数にbreakpointの番号。引数なしの場合はbreakpointの全消去
enable breakpoint有効
disable breakpoint無効
step s 逐次実行関数の中に入る。
next n 逐次実行、関数の中に入らない。
until u ループから抜ける。引数を指定するとtbと同じような動作
continue c 次のbreakpointまで実行。引数に数字をとれる。数字の文だけbreakpoint無視
finish fin 関数の末尾まで実行
commands 引数にbreakpoint番号。そのbreakpointでとまったときに実行するコマンド設定。
watch 引数の変数が変更されたときにとまる。
display disp 引数にprintと同じもの。とまるたびにprintするようになる。
call プログラムの関数呼び出しtuimodeではうまく動作してない?
set 引数の値をセットする$hogegdbの新しい変数
info locals 現在のスコープにある変数一覧

breakpointの引数の指定方法

引数には(ファイル名:)数字,(ファイル名:)関数名が設定できる。つまり

break 3
break function
break filename:3
break filename:function

1行目は3行目にbreakpoint設定。
2行目はfunctionが呼ばれる場所に設定。
3行目はfilenameの3行目にbreakpointを設定。
4行目はfilename中のfunctionが呼ばれている場所に設定。

if hogehogeとすることでhogeという条件ときだけbreakするように設定できる。

break 3 if hoge

commandsの使い方

commands breakpoink 3
....コマンド....
end

と入力することによってbreakpoint3で常に...コマンド...に記入したコマンドを実行する。

関西Emacs勉強会

今更ながら関西Emacs勉強会に参加して、気になったelispを導入してみたので、その感想でも書こうかな。

quickrun

正直この@さん作のelispは知っていたんだけど、Fortranがないし、まぁいっかと思ってた。
しかし、話を聞いてみると拡張が簡単らしい。
で、Fortranに対応させて、他の言語でも使ってみたら便利だった!
特にちょっとした試し書きにはめっちゃ便利!!
以下Fortranへの拡張

(require 'quickrun)
(quickrun-add-command "Fortran"
		      '((:command . "gfortran")
			(:exec . ("%c -o %o %n %s"
				  "%n %a"))
			(:remove . ("%n"))
			))
(add-to-list 'quickrun-file-alist '("\\.f90$" . "Fortran"))

auto-highlight-symbol

聞いた事なかったので、すぐ知らべて導入した。
これはどうやら同じ名前のシンボルをハイライトするみたいだ。
しかも、ハイライトしたシンボルを一括で編集できる。
かなり便利かも。

org-mode

日本語のドキュメントをまとまって作っているのは知らなかった。
これからは利用しようかな。
個別に@さんにorg-mobileとの連携についてアドバイスを頂いてしまった。

これまではorg-mobileにpushするのは保存時に行ていたのだが、orgファイルが大きくなるにつれてpushにかなり時間がかかるようになってしまった。
その解決方法としてEmacsのidle-timerでしばらく放置されたら自動でpushするといいよというアドバイスをいただいた。
なので、mobile用のファイルと更新時間を比較して自動でpushするようにした。
これでイラっとすることが減った。



最後に主催@さん、会場の手配などをしていただいた@さん、発表者、参加者の皆さま、お疲れ様でした。

emacsのアクティブウィンドウと非アクティブウィンドウの色を変える。

emacsを画面分割しまくってると、どのウィンドウがアクティブかどうかわからなくなりますよね?
そこでどのウィンドウがアクティブか分かりやすくするモードを導入します。
その名もhiwin-mode。
gnupackの開発メモ(http://d.hatena.ne.jp/ksugita0510/20111223/p1)に書いてあるとおりやれば使えます。
軽く説明すると、上記のサイトからhiwin-2.00.tar.gzをとってくる。
解凍した後、elispのpathが通っているとこにhiwin.elを置いて..

   (require 'hiwin)
   (hiwin-activate)                           ;; hiwin-modeを有効化
   (set-face-background 'hiwin-face "gray80") ;; 非アクティブウィンドウの背景色を設定

.emacsに書くだけ。