ワード、エクセル、PDFなどのファイルをテキスト形式として書き出す

経緯

Microsoft Wordのファイル(doc/docx)やopendocument(odt)、 PDFファイルの内容を確認する際に、これらのアプリケーションを開かなくてもすむようにテキスト形式に変換してくれるアプリケーションがあります(antiword, pandoc, pdftotext)。

ただし、

  • doc形式のファイルはantiword
  • docx形式のファイルはpandoc
  • pdfファイルはpdftotext

のようにすべてアプリケーションが異なり、しかも使用オプションも異なります。

そこでこれらのコマンドを1つにまとめてみました。

同時にMicrosoft Excelのファイル(xls/xlsx)やopendocument(ods)もテキスト形式に変更できるようにしてみました。

内容

必要なアプリケーション

  • antiword (doc)
  • pandoc (docx, odt, html)
  • pdftotext (pdf)
  • gnumeric (xls, xlsx, ods => html)
  • w3m (xls, xlsx, ods)

上2つのアプリケーションについては Vine Linux用のrpmパッケージを自分自身で作成してアップロードしています。

シェルスクリプト

GitHub で公開しています。

基本的にファイルの拡張子で分岐し、標準出力に出力するようにしているだけです。

新たなファイルに保存するのは使い勝手が悪いと感じたため標準出力に表示するようにしています。

#!/bin/sh
# require pdftotext (pdf)
# require antiword (doc)
# require pandoc (docx/odt/html/tex)
# require gnumeric and w3m (xls/xlsx)

set -e

if [ $# -eq 0 ]; then
  echo "Need argument(s): pdf, doc(x), xls(x) or ... file(s)" 1>&2
  exit 1
fi

for i in $*
do
    if [ -f ${i} ]
    then
       ext="${i##*.}"
       case $ext in
           pdf) pdftotext -raw ${i} - ;;
           doc) LANG=ja_JP.utf8 antiword -w 0 ${i} ;;
           docx|odt|html|htm|tex) pandoc -t plain ${i} ;;
           xls|xlsx|ods) tmpfile=$(mktemp).html ;
                         ssconvert -T Gnumeric_html:xhtml ${i} ${tmpfile} 2> /dev/null ;
                         w3m -dump ${tmpfile} ;
                         rm -f ${tmpfile} ;;
           *)    ;;
       esac
    fi
done

doc

Emacs上で antiword を使用したときに”LANG=ja_JP.utf8″ をつけないと文字化けしたため、環境変数を一時的に設定しています。

docx/odt/html/htm/tex

pandoc の機能をそのまま使用しているだけなので、必要に応じて対応している形式を追加すればいいです。

xls/xlsx/ods

今回苦労したのがこれらのスプレッドシートです。

調べていると gnumeric に含まれる ssconvert というコマンドで html形式に変換できることが分かったため、それを使用しました。 html形式に変換した後に w3m の-dumpオプションでテキスト形式に変換しています。

pandocでhtmlをテキスト形式に変換すると表のレイアウトが崩れてしまったため、今回はw3mを使用しています。

使用法

実行権限をつけて

convertdoc file1 file2 ...

のようにすると、全てのファイルがつながって標準出力に表示されます。

存在しないファイルおよび対応していないファイルは無視されます。エラーも出ないようにしています。

応用

以下のようなelispスクリプトを書き、 M-x my-convertdoc の後に開きたいファイルを選択するとファイルの内容を確認することができます。

Emacs上でMewを使用しており、添付ファイルの内容を確認したかったというのがそもそもの始まりです。

添付ファイルを保存してから M-x my-convertdoc コマンドを実行しなければならないため手間はかかりますが、それでも楽になりました。

elispスクリプト

(defvar my-convertdoc-command "convertdoc")
(defvar my-convertdoc-defaultdir "~/ramdisk/") ;; デフォルトのフォルダ(任意の場所)

(require 'f)

(defun my-convertdoc (file)
  (interactive
   (list (read-file-name "Input file name: "
                         my-convertdoc-defaultdir nil t)))
  (my-convertdoc-file file))

(defun my-convertdoc-file (file)
  (let ((filename (shell-quote-argument (f-expand file)))
        (buf "*ConvertDoc*")
        (resize-mini-windows nil))
      (shell-command
       (format "%s %s" my-convertdoc-command filename) buf)
      (with-current-buffer buf
        (view-mode))))

ファイルを自動でバイトコンパイルさせないための設定

普段は auto-async-byte-compile.el を使用して Emacsの設定ファイルを保存時に自動コンパイルするように設定しています。

(require 'auto-async-byte-compile)
(add-hook 'emacs-lisp-mode-hook 'enable-auto-async-byte-compile-mode)

ただし、るびきちさんのTwitterか何かで「変数を設定しただけのファイルはバイトコンパイルしない」というコメントを見たような記憶があります(記憶が非常にあいまいのためもし違っていたら申し訳ありません)。

そこでどのように設定するのかを調べてみました。

検索方法が悪いのかなかなか見つかりませんでしたが、最終的に Emacsのマニュアル に載っているのを見つけました。

ファイルの先頭に

;; -*-no-byte-compile: t; -*-

のようにしてローカル変数を設定すればいいようです。

これで自動でバイトコンパイルさせることはなくなりました。

Emacsのパッケージ管理のレポジトリにMELPA-stableを追加する

経緯

Emacs-24.5を使用しており、パッケージ管理のレポジトリとして ELPA(gnu)の他に MELPAとMarmalade、orgを追加しています。

しかし、 MELPAに登録されているパッケージの中には亢進頻度が高いものもあり、時々アップグレードによって不具合が生じる場合もあります。

そのため、 MELPAに登録されているパッケージでも安定版で使用したい場合がありました。

そのような時に検索していると このページ にMELPA-stableのことが載っていました。

そこでMELPA-stableを導入したのでその時のメモを残しておきます。ただし、日本語の情報があまりなかったため少し大変でした。

MELPA-stableの導入

レポジトリの登録

このページ の内容に従って.emacs.elに

(add-to-list 'package-archives
             '("melpa-stable" . "https://stable.melpa.org/packages/") t)

を追加します。 Emacs-24以降を使用する場合にはそれ以外の設定は不要です。

パッケージの移行

M-x package-list-packages

を実行し、下の方にある installed となっているパッケージを選択します。 (バージョン番号)(melpa-stable) という箇所を選択すると インストール画面に移行します。

この時、既にMELPAからインストールされているパッケージのフォルダは削除せずに別な場所に保存しておいた方がいいかもしれません。

また、場合によっては MELPA-stableではなくMarmaladeからインストールすることもあるため、どちらからインストールしたのかをメモしておいた方がいいです。

始めはメモしておかなかったため、後でもう一度調べ直すことになりました。結構大変でした。

package-pinned-packages変数の設定

この状態でパッケージのアップグレードを行うと、 MELPAのパッケージが候補に上がってきました。

これでは安定版をインストールした意味がないので、 MELPA-stable版の場合にはMELPA版をインストールしないようにするための設定を調べたところ、 このページ が見つかりました。

package-pinned-packages という変数に パッケージ名とレポジトリを登録すればいいようです。

少し長いですが、現時点での私の設定を載せておきます。

(setq package-pinned-packages
      '(
        (ac-R                  . "marmalade")
        (ace-isearch           . "melpa-stable")
        (ace-jump-buffer       . "melpa-stable")
        (ace-jump-mode         . "melpa-stable")
        (ace-link              . "melpa-stable")
        (ace-pinyin            . "melpa-stable")
        (ace-window            . "melpa-stable")
        (ag                    . "melpa-stable")
        (alert                 . "melpa-stable")
        (async                 . "melpa-stable")
        (auto-complete         . "melpa-stable")
        (avy                   . "melpa-stable")
        (bind-key              . "melpa-stable")
        (bm                    . "marmalade")
        (button-lock           . "melpa-stable")
        (calfw                 . "melpa-stable")
        (color-theme           . "marmalade")
        (ctable                . "melpa-stable")
        (dash                  . "melpa-stable")
        (deferred              . "melpa-stable")
        (descbinds-anything    . "marmalade")
        (diffview              . "melpa-stable")
        (diminish              . "melpa-stable")
        (dired-details         . "marmalade")
        (el-mock               . "melpa-stable")
        (el-x                  . "melpa-stable")
        (elscreen              . "melpa-stable")
        (elscreen-mew          . "melpa-stable")
        (epl                   . "melpa-stable")
        (ess                   . "melpa-stable")
        (ess-R-data-view       . "melpa-stable")
        (ess-R-object-popup    . "melpa-stable")
        (ess-smart-underscore  . "melpa-stable")
        (f                     . "melpa-stable")
        (flycheck              . "melpa-stable")
        (flyspell-lazy         . "melpa-stable")
        (fuzzy                 . "melpa-stable")
        (git-commit            . "melpa-stable")
        (gntp                  . "melpa-stable")
        (guide-key             . "melpa-stable")
        (helm                  . "melpa-stable")
        (helm-ag               . "melpa-stable")
        (helm-core             . "melpa-stable")
        (helm-swoop            . "melpa-stable")
        (highlight-defined     . "melpa-stable")
        (ht                    . "melpa-stable")
        (htmlize               . "marmalade")
        (hydra                 . "melpa-stable")
        (ibuffer-vc            . "melpa-stable")
        (ido-completing-read+  . "melpa-stable")
        (ido-vertical-mode     . "melpa-stable")
        (imenus                . "melpa-stable")
        (julia-mode            . "melpa-stable")
        (kill-or-bury-alive    . "melpa-stable")
        (letcheck              . "melpa-stable")
        (log4e                 . "melpa-stable")
        (m-buffer              . "melpa-stable")
        (magit                 . "melpa-stable")
        (magit-popup           . "melpa-stable")
        (metaweblog            . "melpa-stable")
        (mew                   . "melpa-stable")
        (migemo                . "melpa-stable")
        (morlock               . "melpa-stable")
        (mykie                 . "melpa-stable")
        (noflet                . "marmalade")
        (oauth                 . "marmalade")
        (org                   . "org")
        (org-gcal              . "melpa-stable")
        (org2blog              . "melpa-stable")
        (ox-pandoc             . "melpa-stable")
        (pandoc-mode           . "melpa-stable")
        (paredit               . "melpa-stable")
        (parsebib              . "melpa-stable")
        (passthword            . "melpa-stable")
        (pcre2el               . "marmalade")
        (pcsv                  . "melpa-stable")
        (php-mode              . "melpa-stable")
        (pkg-info              . "melpa-stable")
        (popup                 . "melpa-stable")
        (popwin                . "melpa-stable")
        (rainbow-delimiters    . "melpa-stable")
        (request               . "melpa-stable")
        (request-deferred      . "melpa-stable")
        (revive                . "marmalade")
        (s                     . "melpa-stable")
        (sexp-move             . "melpa-stable")
        (smartrep              . "melpa-stable")
        (smex                  . "melpa-stable")
        (stan-mode             . "melpa-stable")
        (stripe-buffer         . "melpa-stable")
        (unkillable-scratch    . "melpa-stable")
        (use-package           . "melpa-stable")
        (vline                 . "marmalade")
        (with-editor           . "melpa-stable")
        (ml-rpc                . "melpa-stable")
        (xml-rpc               . "marmalade")
        ))

これでMELPAではなく、MELPA-stableやMarmaladeを参照するようになりました。

Emacsで使用するSKKの辞書の文字コードをutf-8にする

経緯

Emacs上で日本語入力をする際に SKK(現時点ではddskk-15.2)を使用しています。ただし文字コードがEUC-JPのため機種依存性文字(丸文字や全角ローマ字など)を登録することができませんでした。

そこでSKKで使用する辞書をutf-8化したので、その際の内容をメモしておきます。

設定

.emacs.elの設定

職場および自宅で同じ環境になるようにするために、辞書 ~/Dropbox/emacs/SKK に置いています。

(require 'skk-autoloads)
(global-set-key "\C-x\C-j" 'skk-mode)
;; (global-set-key "\C-xj" 'skk-auto-fill-mode)
;; (global-set-key "\C-xt" 'skk-tutorial)

(defvar skk-user-directory)
(setq skk-user-directory "~/Dropbox/emacs/SKK")

(require 'sticky)
(use-sticky-key 'henkan sticky-alist:ja)

ちなみに下2行は「変換」キーをsticky keyに割り当てるための設定です。 stickyパッケージをあらかじめインストールしておく必要があります。

initファイルの設定

辞書フォルダの作成(移動)

~/Dropbox/emacs/SKKに辞書ファイルやinitファイル(設定ファイル)を移動させます(すでにその場所にフォルダがある場合には省略)。

cd ~/Dropbox/emacs/SKK
nkf -w -Lu /usr/local/share/skk/SKK-JISYO.L > SKK-JISYO.L.utf8
nkf -w -Lu .skk-jisyo > skk-jisyo.utf8

で文字コードをutf-8に変換して先程のフォルダに配置します。実際に使用する辞書ファイルすべてをこのように utf-8に変更します。

辞書ファイル名の設定

initファイルの内容を以下のように変更します。

(setq skk-jisyo-code 'utf-8)

;; 使用する辞書の設定
(setq skk-cdb-large-jisyo "/usr/local/share/skk/SKK-JISYO.L.cdb")
(setq skk-large-jisyo "~/Dropbox/emacs/SKK/SKK-JISYO.L.utf8")

(setq skk-jisyo "~/Dropbox/emacs/SKK/skk-jisyo.utf8")
(setq skk-backup-jisyo "~/Dropbox/emacs/SKK/skk-jisyo.utf8.bak")

cdb形式の辞書を使用していない場合には skk-cdb-large-jisyo の設定はコメントアウトします。

また今回は、隠しファイルにする必要がないため個人辞書のファイル名の先頭のピリオドを削除しています。

辞書ファイルの設定

辞書ファイルへの単語の追加

以下のように個人辞書ファイルに単語を追加します(途中省略)。

1 /①/1/Ⅰ/
2 /②/2/Ⅱ/
3 /③/3/Ⅲ/
4 /④/4/Ⅳ/
5 /⑤/5/Ⅴ/

この場合にはSKKを使用できないため、 mozc で変換して個人辞書ファイルにコピーしました。

参考にした内容

今回の内容は、 http://openlab.ring.gr.jp/skk/skk/main/etc/dot.skk

;; 個人辞書の文字コードを指定する
;; (setq skk-jisyo-code 'utf-8)
;; 注) この設定は気をつけないと辞書の検索ができなくなりますので十分理
;;   解してから行ってください。 `skk-jisyo-code' は個人辞書の読み書きの
;;   他、L 辞書などの読み込みコードも決めている影響力の強い変数です。
;;   この設定をした場合は、まず個人辞書を上記のコードに変換しなければ
;;   いけません。その上で、さらに以下のいずれかの対処をする必要があり
;;   ます。
;;
;; 方針 1) Emacs のバッファに読み込む辞書を全て `skk-jisyo-code' と同じ
;;         文字コードに変換する

の部分を参考にしました。

org-modeのBeamerクラスのフレームの縦位置を中間ではなく上に固定する

経緯

org-modeのBeamerクラスの欠点

先の記事 でorg-modeのBeamerクラスでスライドを作成するための設定を行いましたが、実は不満が残っていました。それは

  • フレームの縦位置が中央にきてしまう

ことでした。

サンプルファイルとして

#+TITLE: Sample
#+AUTHOR: Toshiaki Ara
#+OPTIONS: H:1 toc:nil
#+LATEX_CLASS: beamer
#+BEAMER_THEME: Madrid

* Frame
** block
+ contents 1
+ contents 2

を用意し、PDFファイルに変換するとこのような感じになります。

test_nul.png

これではスライドを進めていくたびにフレームの始まる位置が異なるため、見る方としては非常につらいです(個人の感想です)。

これを何とか上に固定したいと思い、 ox-beamer のソースコードを調べました。

結論

init.elに

(setq org-beamer-frame-default-options "t")

を追加することでフレームの縦位置が上に固定されるようになりました。

test_t.png

ただし、これでは各ファイルごとの設定ができません。 orgファイルのオプションで設定できる方法があればいいのですが。

それでも、 org-modeによる簡単な記述でこれほど見栄えのよいスライドが作成できるので、積極的に使用したいと思います。 org-modeは見出しレベルで折り畳みできるのが気に入ってます。

ox-beamer.elの解析

先に結論だけを書いたので、次にこの結論に至った経緯を簡単に書きます。

org-beamer–format-frame関数の発見

まずox-beamer.elの中でフレームを定義している関数を探しました。するとすぐにorg-beamer–format-frameが見つかりました。

少し長いですが、ox-beamer.elに書かれている org-beamer–format-frameの関数定義を下に示します。

見やすくするためにタブを空白に変換し、さらに C-M-q でコードを整形しています。

すると26行目に

(org-split-string org-beamer-frame-default-options ",")

という記述がありました。これは org-beamer-frame-default-options という変数に含まれているリストを,で区切った文字列として返す関数であると予想しました。

M-: org-beamer-frame-default-options

で変数の中身を調べると””でした(何も定義されていない)。

そこでフレームを上に固定するためのオプションである”t”を設定したところ希望通りの結果が得られました。

org-beamer–format-frameの関数定義

(defun org-beamer--format-frame (headline contents info)
  "Format HEADLINE as a frame.
CONTENTS holds the contents of the headline.  INFO is a plist
used as a communication channel."
  (let ((fragilep
         ;; FRAGILEP is non-nil when HEADLINE contains an element
         ;; among `org-beamer-verbatim-elements'.
         (org-element-map headline org-beamer-verbatim-elements 'identity
                          info 'first-match)))
    (concat "\\begin{frame}"
            ;; Overlay specification, if any. When surrounded by
            ;; square brackets, consider it as a default
            ;; specification.
            (let ((action (org-element-property :BEAMER_ACT headline)))
              (cond
               ((not action) "")
               ((string-match "\\`\\[.*\\]\\'" action )
                (org-beamer--normalize-argument action 'defaction))
               (t (org-beamer--normalize-argument action 'action))))
            ;; Options, if any.
            (let* ((beamer-opt (org-element-property :BEAMER_OPT headline))
                   (options
                    ;; Collect options from default value and headline's
                    ;; properties.  Also add a label for links.
                    (append
                     (org-split-string org-beamer-frame-default-options ",") ;; <= ココ
                     (and beamer-opt
                          (org-split-string
                           ;; Remove square brackets if user provided
                           ;; them.
                           (and (string-match "^\\[?\\(.*\\)\\]?$" beamer-opt)
                                (match-string 1 beamer-opt))
                           ","))
                     ;; Provide an automatic label for the frame
                     ;; unless the user specified one.
                     (unless (and beamer-opt
                                  (string-match "\\(^\\|,\\)label=" beamer-opt))
                       (list
                        (format "label=%s"
                                (org-beamer--get-label headline info)))))))
              ;; Change options list into a string.
              (org-beamer--normalize-argument
               (mapconcat
                'identity
                (if (or (not fragilep) (member "fragile" options)) options
                  (cons "fragile" options))
                ",")
               'option))
            ;; Title.
            (let ((env (org-element-property :BEAMER_ENV headline)))
              (format "{%s}"
                      (if (and env (equal (downcase env) "fullframe")) ""
                        (org-export-data
                         (org-element-property :title headline) info))))
            "\n"
            ;; The following workaround is required in fragile frames
            ;; as Beamer will append "\par" to the beginning of the
            ;; contents.  So we need to make sure the command is
            ;; separated from the contents by at least one space.  If
            ;; it isn't, it will create "\parfirst-word" command and
            ;; remove the first word from the contents in the PDF
            ;; output.
            (if (not fragilep) contents
              (replace-regexp-in-string "\\`\n*" "\\& " (or contents "")))
            "\\end{frame}")))

このコードはGNU Emacsの一部であるため GNU General Public Licenseが適用されています。

flycheckの設定(RとRuby)

Emacsで文法チェックをするために flycheckおよび関連パッケージを導入したので、その時のメモです。

flycheckを使用するためのEmacsの設定

パッケージのインストール

  • flycheck
  • flycheck-pos-tip
    • エラー内容をその場にツールチップで表示するためのパッケージ
  • helm-flycheck
    • helmインターフェースからエラーを選択するためのパッケージ

init.elの設定

(require 'flycheck)
(require 'flycheck-pos-tip)

(eval-after-load 'flycheck
  '(custom-set-variables
   '(flycheck-display-errors-function #'flycheck-pos-tip-error-messages)))

(add-hook 'R-mode-hook 'flycheck-mode)
(add-hook 'ruby-mode-hook 'flycheck-mode)


(require 'helm-flycheck) ;; Not necessary if using ELPA package
(eval-after-load 'flycheck
  '(define-key flycheck-mode-map (kbd "C-+") 'helm-flycheck))

ここではRとRubyでflycheckを行うように設定しています。

helm-flycheckで修正候補を選択するためのキーに C-+ を割り当てています。

Rの設定

R-modeでycheckを使用するためには、 Rのlintrパッケージが必要なのでインストールしておきます。

install.package("lintr")

ox-pukiwikiの(私的)設定変更

org-modeの原稿をpukiwiki形式に変換するためのパッケージとして ox-pukiwiki があります。

非常に便利なのですが #+BEGIN_SRC#+END_SRC で囲んだ ソースコードを出力しようとしても #+BEGIN_SRC#+END_SRC そのものが出力されてしまいます。

#+BEGIN_EXAMPLE#+END_EXAMPLE で囲んだ部分は整形済みテキストとして出力されます。

そこでox-pukiwiki.elのソースコードを調べたところ

(org-export-define-backend 'pukiwiki
  '((babel-call . org-pukiwiki-identity)
          中略
    (example-block . org-pukiwiki-example-block)
          中略
    (src-block . org-pukiwiki-identity)
          中略
    (verse-block . org-pukiwiki-identity))
  :menu-entry
  '(?p "Export to Pukiwiki"
       ((?p "As Pukiwiki buffer"
      (lambda (a s v b) (org-pukiwiki-export-as-pukiwiki a s v)))
  (?P "As Pukiwiki file"
      (lambda (a s v b) (org-pukiwiki-export-to-pukiwiki a s v)))
  (?o "As Pukiwiki file and open"
      (lambda (a s v b)
        (if a (org-pukiwiki-export-to-pukiwiki t s v)
    (org-open-file (org-pukiwiki-export-to-pukiwiki nil s v))))))))

のように定義されていました。

したがって、

(src-block . org-pukiwiki-identity)

(src-block . org-pukiwiki-example-block)

に変更したところ、 #+BEGIN_SRC#+END_SRC で囲んだ部分も整形済みテキストとして出力されるようになりました。

以下、設定です。

(require 'ox-pukiwiki)

(org-export-define-backend 'pukiwiki
  '((babel-call . org-pukiwiki-identity)
    (bold . org-pukiwiki-bold)
    (center-block . org-pukiwiki-identity)
    (clock . org-pukiwiki-identity)
    (code . org-pukiwiki-code)
    (comment . org-pukiwiki-comment)
    (comment-block . (lambda (&rest args) ""))
    (diary-sexp . org-pukiwiki-identity)
    (drawer . (lambda (&rest args) ""))
    (dynamic-block . org-pukiwiki-identity)
    (entity . org-pukiwiki-identity)
    (example-block . org-pukiwiki-example-block)
    (fixed-width . org-pukiwiki-identity)
    (footnote-definition . org-pukiwiki-identity)
    (footnote-reference . org-pukiwiki-identity)
    (headline . org-pukiwiki-headline)
    (horizontal-rule . org-pukiwiki-identity)
    (inline-babel-call . org-pukiwiki-identity)
    (inline-src-block . org-pukiwiki-identity)
    (inlinetask . org-pukiwiki-identity)
    (italic . org-pukiwiki-italic)
    (item . org-pukiwiki-item)
    (keyword . org-pukiwiki-keyword)
    (latex-environment . org-pukiwiki-identity)
    (latex-fragment . org-pukiwiki-identity)
    (line-break . org-pukiwiki-identity)
    (link . org-pukiwiki-link)
    (node-property . org-pukiwiki-identity)
    (paragraph . org-pukiwiki-identity)
    (plain-list . org-pukiwiki-plain-list)
    (planning . org-pukiwiki-identity)
    (property-drawer . (lambda (&rest args) ""))
    (quote-block . org-pukiwiki-identity)
    (quote-section . org-pukiwiki-identity)
    (radio-target . org-pukiwiki-identity)
    (section . org-pukiwiki-identity)
    (special-block . org-pukiwiki-identity)
    (src-block . org-pukiwiki-example-block)
    (statistics-cookie . org-pukiwiki-identity)
    (strike-through . org-pukiwiki-strike-through)
    (subscript . org-pukiwiki-identity)
    (superscript . org-pukiwiki-identity)
    (table . org-pukiwiki-table)
    (table-cell . org-pukiwiki-table-cell)
    (table-row . org-pukiwiki-table-row)
    (target . org-pukiwiki-identity)
    (timestamp . org-pukiwiki-identity)
    (underline . org-pukiwiki-underline)
    (verbatim . org-pukiwiki-verbatim)
    (verse-block . org-pukiwiki-identity))
  :menu-entry
  '(?p "Export to Pukiwiki"
       ((?p "As Pukiwiki buffer"
      (lambda (a s v b) (org-pukiwiki-export-as-pukiwiki a s v)))
  (?P "As Pukiwiki file"
      (lambda (a s v b) (org-pukiwiki-export-to-pukiwiki a s v)))
  (?o "As Pukiwiki file and open"
      (lambda (a s v b)
        (if a (org-pukiwiki-export-to-pukiwiki t s v)
    (org-open-file (org-pukiwiki-export-to-pukiwiki nil s v))))))))

anythingで絞り込み選択をする際に全ての候補を選択する方法

最近、helmからanythingに戻せるものは戻しています。

そうした所、 helm(helm-miniなど)で絞り込み選択をする際に M-a で全ての候補を選択することができていましたが、 anythingではできないことに気付きました。

以下、解決法です。

そのため、 helmのソースコードで M-a を使用している箇所を検索したところ helm-mark-all という関数が見つかりました。

anythingでも同じような関数が定義されているかを調べたところ anything-mark-all が見つかりました。

そこで

(define-key anything-map (kbd "M-a") 'anything-mark-all)

としてM-aにanything-mark-allを割り当てたところ、 anythingでも全ての候補を選択できるようになりました。

【追記】

anythingのコードを見ると anything-mark-allがM-aに割り当てられているようです。

ただ、M-aが効いたり効かなかったりするので自分自身では上記の設定をしておきます。

また、 M-m (anything-toggle-all-marks)で全てを選択したり選択を解除することができるので、こちらでもいいかもしれません。

f.elに関するメモ

Emacsのモダンなライブラリ4+1選 で紹介されていたf.elパッケージについて、少し勉強したのでその内容をメモ的に残しておきます。

このページの存在は少し前に知っていましたが、 るびきち様 にパッケージと関数を教えて頂いたので自分でも調べてみました。

ファイルに関する関数

f-で始まる関数がf.elパッケージで提供されている関数です。

関数名が短かくて分かりやすくなるとともに ~を自動で展開 (expand-file-name)してくれるものが多いため プログラムが簡潔になりそうです。

また、ファイルの拡張子を変更するf-swap-ext関数は非常に便利かもしれません。

(require 'f)
(setq file "~/.emacs.d/init.el")

;;; ファイル
;; 絶対パス(フルパス)
(expand-file-name file)          ; => "/home/ara/.emacs.d/init.el"
(f-expand file)                  ; => "/home/ara/.emacs.d/init.el"
;; ファイル名(ディレクトリ以外)
(file-name-nondirectory file)    ; => "init.el"
(file-name-nondirectory
 (directory-file-name file))     ; => "init.el"
(f-filename file)                ; => "init.el"
;; ファイルのベースネーム
(f-base file)                    ; => "init"
;; 拡張子
(file-name-extension file)       ; => "el"
(f-ext file)                     ; => "el"
;; 拡張子なしのパス
(file-name-sans-extension file)  ; => "~/.emacs.d/init"
(f-no-ext file)                  ; => "~/.emacs.d/init"

;;; ファイル => ディレクトリ(末尾の/なし)
(directory-file-name
 (file-name-directory file))     ; => "~/.emacs.d"
(f-dirname file)                 ; => "/home/ara/.emacs.d"
;;; ファイル => ディレクトリ(末尾の/あり)
(file-name-directory file)       ; => "~/.emacs.d/"
(f-slash (f-dirname file))       ; => "/home/ara/.emacs.d/"

;; パスの結合(/の有無は自動で処理される)
(f-join "~/.emacs.d" "init.el")  ; => "/home/ara/.emacs.d/init.el"
(f-join "~/.emacs.d/" "init.el") ; => "/home/ara/.emacs.d/init.el"

;; 拡張子の変更
(f-swap-ext file "elc")          ; => "~/.emacs.d/init.elc"

ディレクトリに関する関数

  • 末尾の/を外すのがf-long
    • 内部でf-expandを呼び出しているだけ(f-expandで十分かも)
  • 末尾の/をつけるのがf-full
    • f-longの後にf-slashを適用している
(require 'f)
(setq dir1 "~/.emacs.d")
(setq dir2 "~/.emacs.d/")

;;; 絶対パス(フルパス)
(expand-file-name dir1)          ; => "/home/ara/.emacs.d"
(expand-file-name dir2)          ; => "/home/ara/.emacs.d/"
(f-expand dir1)                  ; => "/home/ara/.emacs.d"
(f-expand dir2)                  ; => "/home/ara/.emacs.d"

;;; ディレクトリ
;; ディレクトリ(末尾の/なし)
(directory-file-name dir1)       ; => "~/.emacs.d"
(directory-file-name dir2)       ; => "~/.emacs.d"
(f-long dir1)                    ; => "/home/ara/.emacs.d"
(f-long dir2)                    ; => "/home/ara/.emacs.d"
;; ディレクトリ(末尾の/あり)
(file-name-as-directory dir1)    ; => "~/.emacs.d/"
(file-name-as-directory dir2)    ; => "~/.emacs.d/"
(f-slash dir1)                   ; => "~/.emacs.d/"
(f-slash dir2)                   ; => "~/.emacs.d/"
(f-full dir1)                    ; => "/home/ara/.emacs.d/"
(f-full dir2)                    ; => "/home/ara/.emacs.d/"

その他の関数

f-readあるいはf-read-textは非常に便利そうです。

with-temp-buffer => insert-file-contents のような作業を内部で行ってくれます。結果がバッファへの挿入ではなく文字列として返ってくるのだけが異なりますが、それでもプログラムが非常に簡潔になりそうです。

;; ファイルを文字列として読み込む(codingは省略可能:デフォルトは'utf-8)
(f-read path coding)
(f-read-text path coding)

;; 文字列をファイルに保存(codingは省略可能:デフォルトは'utf-8)
(f-write text coding path)
(f-write-text text coding path)

;; このファイルのフルパスを得る
(f-this-file)