DDSKKの日本語入力でC-iをまともに使いたい
DDSKK を使用していて困っていたのが,「かなモード」や「カナモード」のときに transient-mark-mode が有効なときの C-i が indent-resion にならないことだ.TAB キーでは上手くいくのに,C-i だとなぜかリージョン範囲が削除される.
define-key などで調べるとタブが insert 扱いになっているせいだとわかった.アルファベットキーで試せばわかるように,insert は transient-mark-mode 有効時にリージョンを削除して文字を挿入する.ということで,特定のキーに強制的にコマンドを割り当てる方法 - (rubikitch loves (Emacs Ruby CUI Books)) で強制的に割り当てようとしたが,上手くいかない.どうやら skk-j-mode-map の方が overriding-minor-mode より優先度が高いらしい.
そこで .emacs で skk-j-mode-map にキーを定義してみたが,なんと skk-j-mode-on するたびに勝手にキーマップがリセットされる.
仕方無く skk.el を読んでみたところ,関数 skk-setup-j-mode-map-options で skk-try-completion-char (初期設定では "\t") が skk-insert に設定されていることが,C-i が insert となる原因だと突き止めた.TAB キーはその後に skk-comp-wrapper が割り当てられているため,C-i と挙動が異なっているというわけだ.
この問題を解決するには,C-i にも skk-comp-wrapper を割り当てる.以下のコードを .emacs に書けばOK.
(defadvice skk-setup-j-mode-map-options (after c-i-comp-wrapper2 activate) (define-key skk-j-mode-map (kbd "C-i") #'skk-comp-wrapper))
C-i に skk-comp-wrapper を割り当てるコードを,第1引数が after の defadvice によって関数 skk-setup-j-mode-map-options の末尾に追加するコードとなる.
とりあえずこれで DDSKK 使用時の大きな問題が1つ解決した.しかし,DDSKK は様々な重要キーを奪っていくのを本当にどうにかしてほしいものだ.C-j で return-indent できなかったり,ReadOnly ファイルで C-p を入力してもカーソルを移動できなかったり…….DDSKK 常用の道は険しい.
anything-for-filesにrecentfを全て表示したい
recentf-max-saved-items を変更しても,anything-for-files で表示される recentf が増えないのが嫌だったので anything-c-source-recentf を書き換えた.やることは anything-for-filesでlocateを有効にすると表示直後に移動したカーソルが一番上に戻される問題 - 勉強日記 とほぼ同じ.
;;; recentf の表示数を 100 まで拡張 (setq recentf-max-saved-items 100) (setq anything-c-source-recentf `((name . "Recentf") (init . (lambda () (require 'recentf) (or recentf-mode (recentf-mode 1)))) (disable-shortcuts) (candidates . recentf-list) (keymap . ,anything-generic-files-map) (help-message . anything-generic-file-help-message) (candidate-number-limit . ,recentf-max-saved-items) ; 標準定義にこれを追加した (mode-line . anything-generic-file-mode-line-string) (match anything-c-match-on-basename) (type . file)))
注意することは,recentf-max-saved-items への代入を先に行うことと,recentf-max-saved-items の前にカンマを置くこと.クォートの代わりにバッククォートを使用すると,カンマ直後の変数を展開してくれる.
anything-for-filesでlocateを有効にすると表示直後に移動したカーソルが一番上に戻される問題
locate の表示数が多すぎるのがよくないらしい.ということで .emacs に以下のコードを追加して anything-c-locate で表示される項目数を限定.
;;; anything-locate の表示数を50に限定 (setq anything-c-source-locate `((name . "Locate") (candidates . anything-c-locate-init) (type . file) (requires-pattern . 3) (keymap . ,anything-generic-files-map) (help-message . anything-generic-file-help-message) (candidate-number-limit . 50) ; ここで表示数を決定 (mode-line . anything-generic-file-mode-line-string) (delayed)))
できるだけデフォルトの anything-config.el を書き換えたくないので,anything-c-source-locate を上書きして無理矢理解決した.これを書くと anything-locate も 50 個しか表示されなくなってしまう.
もっと良い解決方法があるのかもしれないけど,まあ応急処置ということで.
anything-for-filesでlocateが動かない問題について
anything インストール済み Emacs を起動してすぐに anything-for-files を起動しても,locate が動かない.anything-for-files には anything-c-source-locate が含まれているはずなのに…….
原因は,anything-c-locate-command が初期状態では nil になっているからのようだ.そのため,これに適切な代入を行う anything-locate を実行後は anything-for-files で locate が有効になる.
anything-locate 実行時に anything-c-locate-command には以下のような代入が行われているようだ.
(setq anything-c-locate-command (case system-type ('gnu/linux "locate -i -r %s") ('berkeley-unix "locate -i %s") ('windows-nt "es -i -r %s") (t "locate %s")))
.emacs にこれを書けば解決する.マシンが決まっているのであれば以下で十分(私のUbuntu環境の例).
(setq anything-c-locate-command "locate -i -r %s")
Emacsの単語をブラウザで検索
Emacs でコードとか読んでると Google で検索したくなることはよくあるので,方法をいろいろ調べてみた.
anything-c-source-surfraw
1つが anything-c-source-surfraw.anything をインストールしている Emacs なら,sudo apt-get install surfraw で surfraw をインストールして,M-x anything-surfraw で使える.
試してみたが,複雑な検索を簡単に行うことはできても,検索までにいろいろ入力が必要で,いつも Google で検索する私にはちょい面倒.
あと,別のサーチエンジンを追加するには surfraw 側を弄る必要があるらしいのだが,そこがさっぱりわからなかったので断念.
anything-c-source-surfraw の詳細を知りたければ,以下が詳しいので参考に.
emacs からサーチエンジンの検索結果を呼び出す anything-c-source-surfraw の紹介 - わからん
search-web.el
もう1つ,search-web.el を見つけた.こちらは手軽に検索できて,サーチエンジンの追加も簡単.
Emacs ですぐに単語の検索をしたい欲望を叶える Elisp。 - 日々、とんは語る。
search-web.el ではリージョン検索と付近の単語検索で関数を分けているが,transient-mark-mode 時にはリージョンを,そうでないときは付近の単語を検索する方が便利.
あと,現在のバージョンの search-web.el では,キーバインド一発検索が設定できない.
ということで,.emacsに以下を追加.
(require 'search-web) (define-prefix-command 'search-web-map) (global-set-key (kbd "M-i") 'search-web-map) (global-set-key (kbd "M-i g") (lambda () (interactive) (search-web-dwim "google"))) (global-set-key (kbd "M-i M-i") (lambda () (interactive) (search-web-dwim))) (defun search-web-dwim (&optional arg-engine) "transient-mark-mode がオンの時はリージョンを, オフの時はカーソル位置の単語を検索する." (interactive) (cond ((transient-region-active-p) (search-web-region arg-engine)) (t (search-web-at-point arg-engine))))
さらに,search-web.el の search-web-at-point と search-web-region を以下に書き換え.
(defun search-web-at-point (&optional arg-engine) (interactive) (message "sw: %s" arg-engine) (let* ((completion-ignore-case t) (search-word (substring-no-properties (thing-at-point 'word))) (engine (or arg-engine (completing-read (format "[%s] Search Engine: " search-word) (make-search-engine-name-list) nil t)))) (search-web engine search-word))) (defun search-web-region (&optional arg-engine) (interactive) (let* ((completion-ignore-case t) (beg (mark)) (end (point)) (search-word (buffer-substring-no-properties beg end)) (engine (or arg-engine (completing-read (format "[%s] Search Engine: " search-word) (make-search-engine-name-list) nil t)))) (search-web engine search-word)))
O'ReillyのiPhoneアプリからepubを作成するRubyプログラム
404 Blog Not Found:perl - O'ReillyのiPhoneアプリ本からepubをぶっこぬく をRubyで書いた.ziprubyが必要.Ubuntuで使用したが,ziprubyがあればたぶんWindowsでも動く.
# -*- coding: utf-8 -*- #/usr/bin/env ruby # # O'Reilly の iPhone App を epub ファイルに変換し, # 入力と同じディレクトリに出力する. # ziprubyが必要 (gem install zipruby). # # $ ruby epub_extractor.rb {iPhone App} require "fileutils" require 'zipruby' require 'pathname' require 'tmpdir' require 'find' require 'readline' class Ipa2Epub def self.create_epub(ipa) # 作成予定ファイルが既に存在していないかチェック output_path = Pathname(ipa).sub_ext(".epub") if File.exist?(output_path) while buf = Readline.readline("Overwrite #{output_path}? (y/n): ") if (buf == "y") break elsif (buf == "n") puts "exit." exit end end end Dir.mktmpdir {|tmpdir| # ipaをtmpdir下に解凍 Zip::Archive.open(ipa) {|archives| archives.each do |a| d = File.dirname(a.name) FileUtils.mkdir_p("#{tmpdir}/#{d}") unless a.directory? open("#{tmpdir}/#{a.name}", "w") {|f| f.puts a.read } end end } # epubに必要なファイルをepubに追加 puts "#{ipa} -> #{output_path.to_s} " Zip::Archive.open(output_path.to_s, Zip::CREATE | Zip::TRUNC) {|output| book_path = Pathname(Dir.glob("#{tmpdir}/Payload/*.app/book")[0]) Find.find(book_path) do |f| next if f == book_path relative_path = Pathname.new(f).relative_path_from(book_path) if File.directory?(f) output.add_dir(relative_path.to_s) else output.add_file(relative_path.to_s, f) end end } } end end if __FILE__ == $0 ARGV.each do |ipa| Ipa2Epub.create_epub(ipa) end puts "complete." end
elispでprintデバッグ
こんな関数を定義してみるのはどうだろう.
;;; printデバッグ用関数 (defun p (FORMAT-STRING &rest ARGS) (prog1 (apply 'message FORMAT-STRING ARGS) (sit-for 3))) ;;; 例 (setq num 10) (p "num: %d" num) ; => "num: 10" (message "num: %d" num) ; => "num: 10"
message関数と使い方は同じ.messageと違って表示後に一時停止するので,関数の途中に挟んでも変数の値を見る時間がある.
一文字の関数で入力しやすいというのも利点.もちろんRubyのパクり.グローバルなelispでこんな名前の関数を定義するのは危険すぎる気もするが…….