の使い方O'Reilly読んでやっとわかった。
まぁhttpd.confの書き方が分からなかったって話しなんだけど。
#CGIプログラミング第二版p145よりOptions +includes AddHandler server-parsed .htm
と書けばいいだけでした。ググっても全然分からなかったのに、本見たら数分かからず出来たw
- 作者: スコットグーリッジ,ガンザーバージニックス,シシャガンダヴァラム,Scott Guelich,Gunther Birznieks,Shishir Gundavaram,田辺茂也,大川佳織
- 出版社/メーカー: オライリー・ジャパン
- 発売日: 2001/06
- メディア: 単行本
- 購入: 2人 クリック: 69回
- この商品を含むブログ (42件) を見る
文字列検索、コピペ、カーソル移動はI/Fなので持ち歩きたい。
1.文字列検索
普段Emacsを使っている僕ですが、もちろんそれ以外のアプリを使うこともあります。で、別のアプリを使っていて「この時がきたか…」と思う瞬間があります。目当ての文字列が見つけるため、検索機能を使うときです。そして大抵自分の求めるように動いてくれず、目を皿のようにして目を頼りに探す事になるのです(そして、この部分を、Emacsに置き換えられないかなーと思ってしまうのです。まぁ自分が使っているのはMeadow(Windows版)なのですが、可能であれば Meadowにファイルを渡す事のできる gnuclientw などを使うことになります)。
まず検索で嫌な例ですが、自分の探したい文字列が、ただGUI上の表示で、検索対象になっていなければどうしようもありません。なぜ検索対象にしてくれないのか、いつも悩むのですがどうしようもありません。EmacsのDired(DIRectory EDitor)などでは全ての文字列が、検索対称なのでエクスプローラーとは使い勝手は比べ物になりません(エクスプローラーのフォルダ表示のような物がほしければ Alt+x speedbarを使いましょう)
また、Ctrl+f、Ctrl+f、Ctrl+f…と押し続けて、大抵自分は目当ての物を通り過ぎてしまうのですが、「一個前の検索に戻る」が出来るかどうかが重要です。これは「進むボタン」と「戻るボタン」が別になっている場合、またプルダウンで進行方向を「下へ」「上へ」と選んで「次を検索」を押して戻る方法などがあるでしょう。どちらかがあればいいのですが、本当にない場合もあります。
Emacsではここは「Back space」を押せば(検索文字列は変化せず)戻るという事になっています。押した回数だけ戻っていき、検索で進んできたのの逆をやってくれます。最後には検索開始位置に戻り、検索文字列も消えています。これは慣れればいいのですが、こういう実装になっている物はあまり見ませんし、実装してくれとも思いませんが。
またEmacsの文字列検索で便利なのはCtrl+s(Meadowの検索はCtrl+sです。嫌な人には嫌でしょうけど)を押した後にCtrl+wを押すと、カーソルの下の文字列を英語ならword単位で検索対処に追加していく事です。日本語だと「漢字おくりがな」でwordとみなされてしまうので、これは少し使い勝手が、よくないです。「漢字」までで止める方法を探したのですが、結局わからずあきらめました。
2.コピペ
これもEmacsにはいいシステムがあります、マウスで文字列を選択しようとしたときに、選択開始位置が1,2文字ずれていたなど気づくときがあります。このときEmacsではCtrl-x Ctrl-xと押すと、選択開始位置(マークといいます)、とカーソル(ポイントといいます)を入れ替える事ができます。これで選択終了位置を確定してから、マークとポイントを入れ替えて、ずれていた選択開始位置を動かす事が出来ます。
またプログラムなどは行単位で削除したい事がよくあります。これもCtrl+kでカーソル位置以降の行をカット可能です。カーソル移動などもせず、Ctrl+kを押し付けていると、それらの行はすべてクリップボードに入っていきますので、ペーストも出来ます。
3.カーソル移動
カーソル移動は色々とあるでしょうけど、Emacsの場合、
Ctrl+a 行頭に移動 Ctrl+e 行末に移動 Ctrl+v ページスクロールダウン Alt+v ページスクロールアップ Alt+< ファイル先頭に移動 Alt+> ファイル末尾に移動 Ctrl+d Delete
が殆どホームポジションから指を移動せずに入力できます。たとえば改行のたくさんある、文章をHTMLにするため1行にしたければ、Ctrl+e,Ctrl+d,Ctrl+e,Ctrl+d,…と繰り返せば一行になります。Home、End、PgUp、PgDnに手を伸ばすのは僕にはめんどくさいです。
またEmacsにはカーソルの下の単語を対称にする操作がいくつかあります。w3m-search, sdic-describe-word, lookup-word, などです。単語単位の移動(Ctrl+→)などを使いながら、読んでいる単語の近くにカーソルがあるように、移動させておくと以上の関数がすぐに呼び出せます。
そしてMeadowにはファイラーや、MUAや、テキストブラウザや、2ch専用ブラウザがありますが、殆ど全部の範囲に文字列検索や、カーソル移動が出来ます。
そこで以下のようにしてMeadowは持ち歩いてます。
USBメモリでMeadow[LifeHack][Meadow]
http://www23.atpages.jp/changelog/2010-12-07-1.html
まぁとにかく、テキストを目の前にしたとき、うえの1.文字列検索, 2.コピペ, 3.カーソル移動、はインターフェースだと思っているので、出来るだけ持ち歩きたいですね。
navi2chのnavi2ch-search-webのスレ検索を2ken.netに変えるpatch公開します。
find.2ch.netはどうもdat落ちしたスレとかまで引っかかるのが多い気がして気に入らなかったので、2ken.netに変えてみました。関数名とか変数名とか全部別にすればよかったんでしょうけど、navi2chの全体像を把握してないので必要なところのみ書き換えました。
ちなみに
と~/.navi2ch/init.elに書いておけば、100件表示で検索できますが(大体は100件で事足りると思うのですが100件超えた場合も)、M-x navi2ch-search-web-next で 次の100 件を表示させる事は出来ませんでしたorz
だれか、うまい解決法を教えていただけないかなぁチラッチラッ
--- navi2ch-search.el.orig 2012-07-11 08:45:59.359375000 +0900 +++ navi2ch-search.el 2012-09-06 12:27:01.140625000 +0900 @@ -381,7 +381,7 @@ (defun navi2ch-search-web-make-list (url title num) "((board) (subject)) のような navi2ch 内部のスレ情報を擬似的に作成。" (when (string-match - "\\(http://[-a-zA-Z0-9_.!~*';/?:@&=+$,%#]+/\\)test/read.cgi/\\(.+\\)/\\([0-9]+\\)/.*" + "\\(http://[-a-zA-Z0-9_.!~*';/?:@&=+$,%#]+/\\)test/read.cgi/\\(.+\\)/\\([0-9]+\\).*" url) (let ((subject (cons 'subject title)) (response (cons 'response num)) @@ -399,10 +399,16 @@ find.2ch.net の仕様上、最大は50件") (defvar navi2ch-search-find-2ch-coding 'euc-japan-dos "find.2ch.net で使われるコーディング") -(defconst navi2ch-search-find-2ch-thread-regexp - "<dt><a href=\"\\(http://[-a-zA-Z0-9_.!~*';/?:@&=+$,%#]+\\)\">\\(.*\\)</a> (\\([0-9]+\\)) - <font size=[-0-9]+><a href=.+/>\\(.+\\)板</a>.+</font></dt><dd>" - "find.2ch.net で検索する regexp") +(setq navi2ch-search-find-2ch-thread-regexp +;;(defconst navi2ch-search-find-2ch-thread-regexp + (concat "<dt>[0-9]+\\. *<strong><a href=\"\\(http://[0-9a-zA-Z-]+\\.2ch\\.net/test/read\.cgi/[a-zA-Z0-9-]+/[0-9]+\\)\">\\(.*\\)</a></strong> (スコア: *[0-9]+)[^<]*" + "<dd>.*</font>[^<]*" + "<dd>[^<]*" + "<dd><a .*br>")) +;; "2ken.2ch.net で検索する regexp") + +;;; 変更 (defun navi2ch-search-find-2ch-subject-list (query offset) "find.2ch.net に文字列 `query' でリクエスト。 `offset' は「次の10件」とか表示させたいときに使う。" @@ -415,7 +421,7 @@ navi2ch-search-find-2ch-coding t)) ;; 意味も分からず使ってるパラメータ多し。内部仕様が分かり次第改善予定 (url (format - "http://find.2ch.net/?STR=%s&SCEND=A&SORT=MODIFIED&COUNT=%s&TYPE=TITLE&BBS=ALL&OFFSET=%s" + "http://2ken.net/cgi-bin/namazu.cgi?key=%s&submit=search+%21%21&whence=0&dbname=all&max=%s&whence=%s" query navi2ch-search-find-2ch-search-num offset)) (proc (navi2ch-net-download-file url)) (cont (decode-coding-string (navi2ch-net-get-content proc) @@ -425,7 +431,7 @@ (insert cont) (goto-char (point-min)) ;; まず総ヒット件数を探す - (if (re-search-forward "<font color=white size=-1>\\([0-9]+\\)スレ中.*秒</font>" nil t) + (if (re-search-forward "<strong> Total <!-- HIT -->\\([0-9]+\\)<!-- HIT --> documents matching your query.</strong>" nil t) (progn (setq navi2ch-search-web-total-hit (string-to-number (match-string 1))) (while (re-search-forward @@ -433,7 +439,7 @@ nil t) (let ((url (match-string 1)) (title (navi2ch-replace-html-tag (match-string 2))) - (num (match-string 3))) + (num "レス数不明")) ;;2ken.netでは取得不可能 (push (navi2ch-search-web-make-list url title num) subject-list)))) (setq navi2ch-search-web-total-hit 0) @@ -443,17 +449,17 @@ navi2ch-search-web-total-hit) navi2ch-search-web-current-end (min (+ navi2ch-search-find-2ch-last-search-num - (min navi2ch-search-find-2ch-search-num 50)) + (min navi2ch-search-find-2ch-search-num 100)) navi2ch-search-web-total-hit)) (nreverse subject-list))) ;; 次のページ (defun navi2ch-search-find-2ch-next () - (min navi2ch-search-find-2ch-search-num 50)) + (min navi2ch-search-find-2ch-search-num 100)) ;; 前のページ (defun navi2ch-search-find-2ch-previous () - (- (min navi2ch-search-find-2ch-search-num 50))) + (- (min navi2ch-search-find-2ch-search-num 100))) ;;; navi2ch h.ula.cc (defvar navi2ch-search-hula-method
FirefoxのIt's all text ではてなダイアリーを書くモード作った。
hatena-diary-modeは http://d.hatena.ne.jp/lightcyan/20120715/1342329627 で使ってみたと書きましたが、確認してから公開する事ができないようで、いきなり公開されてしまうので、FirefoxのIt's all textを試してみましたが、選択範囲をboldにするとかそれくらいの機能は欲しかったので、自分で作りました。
ブラウザ上でやった方がよさそうな操作は、一回ファイルを保存すると、ブラウザ上のテキストエリアが変更されてますので、そちらで操作して、もう一回テキストエリア右下にある編集ボタン
を押すとEmacsのミニバッファに、
Revert buffer from file c:/Documents and Settings/navi/Application Data/Mozilla/Firefox/Profiles/********.default/itsalltext/d.hatena.ne.jp.**********.txt? (yes or no)
とか出るので、yesを選んでバッファにファイルを再読み込みさせてから、Emacsでの編集を再開してください。
;;; my-hatena-mode.el - major mode for Hatena::Diary with It's All Text!(add-on of Firefox) ;; Author: lightcyan ;; URL: http://d.hatena.ne.jp/lightcyan/ ;; This file is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 2, or (at your option) ;; any later version. ;; This file is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; Add these lines to your .emacs file. ;; (setq auto-mode-alist ;; (append '(("d\\.hatena\\.ne\\.jp\\..*\\.txt" . my-hatena-mode))auto-mode-alist)) ;; (modify-coding-system-alist 'file "d\\.hatena\\.ne\\.jp\\..*\\.txt" 'utf-8) ;;; Commands: ;; `my-hatena-bold' ;; put tag like "B" button pushed. ;; `my-hatena-italic' ;; put tag like "I" button pushed. ;; `my-hatena-red' ;; put tag like "#FF0000" button pushed. ;; `my-hatena-green' ;; put tag like "#00FF00" button pushed. ;; `my-hatena-blue' ;; put tag like "#0000FF" button pushed. (require 'skeleton) (defvar my-hatena-mode-map nil "Keymap for my hatena mode.") (unless my-hatena-mode-map (setq my-hatena-mode-map (make-keymap)) (define-key my-hatena-mode-map "\C-ctf" 'my-hatena-bold) (define-key my-hatena-mode-map "\C-cti" 'my-hatena-italic) (define-key my-hatena-mode-map "\C-ctr" 'my-hatena-red) (define-key my-hatena-mode-map "\C-ctg" 'my-hatena-green) (define-key my-hatena-mode-map "\C-cta" 'my-hatena-blue)) (defun my-hatena-mode () (interactive) (setq major-mode 'my-hatena-mode mode-name "my-hatena") (use-local-map my-hatena-mode-map)) (define-skeleton my-hatena-bold "hatena futoji tag." nil "<span class=\"deco\" style=\"font-weight:bold\;\">" _ "</span>") (define-skeleton my-hatena-italic "hatena futoji tag." nil "<span class=\"deco\" style=\"font-weight:italic\;\">" _ "</span>") (define-skeleton my-hatena-red "hatena futoji tag." nil "<span class=\"deco\" style=\"color:#FF0000\;\">" _ "</span>") (define-skeleton my-hatena-green "hatena futoji tag." nil "<span class=\"deco\" style=\"color:#00FF00\;\">" _ "</span>") (define-skeleton my-hatena-blue "hatena futoji tag." nil "<span class=\"deco\" style=\"color:#0000FF\;\">" _ "</span>")
他にも簡単に出来てあった方がいい物ありますかねー。
emacs-w3m shimbunでopmlを読み込めるrssアグリゲーター作った
mew用です。まぁ以下の通りです。Dateが読み込めず、yearが"0000"になってしまったり、Fromが読み込めず "opml-rss (3)"とかなったりするのをなんとかしたいところですが、自力では出来ませんorz
;;; sb-opml-rss.el --- shimbun backend for american-rss ;; Modified from sb-reuters-rss.el by lightcyan <lightcyan.area51@gmail.com> ;; URL: http://d.hatena.ne.jp/lightcyan/ ;; Below is the original copyright notice of sb-reuters-rss.el. ;; ;; Modified from sb-cnet-rss.el by Hiroyuki KUROSAKI <noir@st.rim.or.jp> ;; Below is the original copyright notice of sb-cnet-rss.el. ;; ;; Copyright (C) 2003 NAKAJIMA Mikio <minakaji@namazu.org> ;; Author: NAKAJIMA Mikio <minakaji@namazu.org> ;; Keywords: news ;; Created: Jun 14, 2003 ;; This file is a part of shimbun. ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 2, or (at your option) ;; any later version. ;; This program is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with this program; if not, you can either send email to this ;; program's maintainer or write to: The Free Software Foundation, ;; Inc.; 59 Temple Place, Suite 330; Boston, MA 02111-1307, USA. ;;; How to use with Mew.: ;; 1. Save google-reader-subscriptions.xml to `shimbun-opml-rss-file', ;; 2. Add ("opml-rss" ("opml-rss.0" . last)) to your `mew-shimbun-folder-groups', ;; 3. Make "~/Mail/shimbun/opml-rss" folder. ;; 4. M-x `mew-summary-visit-folder'[RET]"+shimbun/opml-rss", then M-x `mew-shimbun-retrieve'. ;; 5. Valid value of `mew-shimbun-folder-groups' for the opml-rss generated in a new buffer. ;; 6. Save it to ~/.mew.opml.el or somewhere you like, and load it from somewhre. ;; 7. Reboot Emacsen, And do M-x `mew-shimbun-retrieve-all'. ;;; Code: (require 'shimbun) (require 'sb-rss) (require 'xml) (luna-define-class shimbun-opml-rss (shimbun-rss) ()) (defvar shimbun-opml-rss-file "~/.w3m/google-reader-subscriptions.xml" "A opml file from Google reader") (defvar shimbun-opml-rss-mew-file ".mew-opml.el" "A file to set `shimbun-opml-rss-groups-max' and to append `mew-shimbun-folder-groups' Save `sb-opml-rss-initialize' Resulet in this file") (defvar shimbun-opml-rss-mew-path (expand-file-name (format "~/%s" shimbun-opml-rss-mew-file)) "Path to a file `shimbun-opml-rss-mew-file'.") (defvar shimbun-opml-rss-buffer " *w3m opml*" "temporary buffer to be used readind opml file.") (defvar shimbun-opml-rss-groups-max 0 "Number of how many feed you want to retrieve. This is set in `shimbun-opml-rss-mew-file'.") (defvar shimbun-opml-rss-from-address "foo@baa.baz") (defvar shimbun-opml-rss-content-start nil) (defvar shimbun-opml-rss-content-end nil) (defvar shimbun-opml-rss-groups nil "A list of the row such as \"1\" \"2\" \"3\"... up to shimbun-opml-rss-groups-max. nil means set automatically when sb-opml-rss is loaded.") (if (not shimbun-opml-rss-groups) ;; Initialize shimbun-opml-rss-groups (progn (setq shimbun-opml-rss-groups ()) (let ((i shimbun-opml-rss-groups-max)) (while (< -1 i) (setq shimbun-opml-rss-groups (cons (format "%s" i) shimbun-opml-rss-groups)) (setq i (1- i)))))) (defun sb-opml-rss-initialize () "Generate value of `mew-shimbun-folder-groups' according to `shimbun-opml-rss-file'" (interactive) (let* ((root (xml-parse-file (expand-file-name "~/.w3m/google-reader-subscriptions.xml"))) (posts (car root)) (post (xml-node-children posts)) (i 1) folder-groups-for-opml opml-rss-group) (setq outlines (cdr (cdr (assoc 'body post)))) (while outlines (setq folder (pop outlines)) (if (listp folder) (progn (pop folder) (setq folder-title (cdr (assoc 'title (car folder)) )) (pop folder) (if (listp folder) (progn (setq opml-rss-group (list)) (while folder (setq site (pop folder)) (if (listp site) (progn (pop site) (setq site-title (cdr (assoc 'title (car site)) )) (if (not opml-rss-group) (setq opml-rss-group (list (cons (format "\"opml-rss.%d\"" i) 'all))) (setq opml-rss-group (append opml-rss-group (list (cons (format "\"opml-rss.%d\"" i) 'all))))) (setq i (1+ i))))) (if (not folder-groups-for-opml) (setq folder-groups-for-opml (list (cons (format "\"opml-rss/%s\"" folder-title) opml-rss-group))) (setq folder-groups-for-opml (append folder-groups-for-opml (list (cons (format "\"opml-rss/%s\"" folder-title) opml-rss-group)))))))))) (sb-opml-rss-initialize-display i folder-groups-for-opml))) (defun sb-opml-rss-initialize-display (max result) "Display `sb-opml-rss-initialize' result" (if (file-exists-p shimbun-opml-rss-mew-path) (if (not (yes-or-no-p (format "%s is already exist. continue anyway?" shimbun-opml-rss-mew-path))) (error "User abort."))) (find-file shimbun-opml-rss-mew-path) (setq opml-buffer (get-buffer shimbun-opml-rss-mew-path)) (if (string= shimbun-opml-rss-mew-file (buffer-name)) (progn ;; print (insert ";;; Save this buffer and load that file from your .mew file.\n") (insert (format ";;; e.g. Save in %s. (load \"%s\"). Then reboot Emacsen.\n" shimbun-opml-rss-mew-path shimbun-opml-rss-mew-path)) (insert (format "(setq shimbun-opml-rss-groups-max %d)\n" max)) (insert "(setq mew-shimbun-folder-groups (append mew-shimbun-folder-groups\n") (insert (format "'%s" result)) (insert "))") ;; format output (goto-char (point-min)) (replace-string "all) (" "all) (") (goto-char (point-min)) (replace-string "\" (" "\" (") (goto-char (point-min)) (replace-string ")) (" ")) (") (lisp-mode) (goto-char (point-min)) (switch-to-buffer shimbun-opml-rss-mew-file)) (message "Something is wrong. Load sb-opml-rss.el then type M-x sb-opml-rss-initialize, and see shimbun-opml-rss-mew-file") )) (luna-define-method shimbun-index-url ((shimbun shimbun-opml-rss)) ;;;<DEBUG> ;; (shimbun-index-url-1 shimbun)) ;; (defun shimbun-index-url-1 (shimbun) ;;;</DEBUG> (if (and (string= "opml-rss.0" (car (nth 1 (assoc-string "opml-rss" mew-shimbun-folder-groups)))) (not(file-exists-p shimbun-opml-rss-mew-path)));; I wanna check if `mew-shimbun-folder-groups' changed but how? (progn (sb-opml-rss-initialize) (error (format "Please edit .mew file according to %s" shimbun-opml-rss-mew-path))) (let ((num (shimbun-current-group-internal shimbun)) opml-buffer) (save-excursion (setq opml-buffer (get-buffer shimbun-opml-rss-buffer)) (if (not opml-buffer) (progn (set-buffer (get-buffer-create shimbun-opml-rss-buffer)) (insert-file-contents shimbun-opml-rss-file)) (progn (set-buffer shimbun-opml-rss-buffer))) (goto-char (point-min)) (let ((i 0)) (while (and (< i (string-to-number num)) (re-search-forward "xmlUrl=\"\\(http://[^\"]+\\)\"" nil t) (setq i (1+ i)))) ;;(message "opml-rss:[%d/%s]%s" i num (match-string 1)) (match-string 1)))))) (luna-define-method shimbun-rss-build-message-id ((shimbun shimbun-opml-rss) url date) (unless (string-match "http://\\(.+\\)" url) (error "Cannot find message-id base")) (concat (match-string-no-properties 1 url) "")) (provide 'sb-opml-rss) ;;; sb-opml-rss.el ends here
mimizunのhtmlをdatに変換するperl書いた。
htmltodatをいじってる間に正規表現書くならこう書いたほうが早いと思ってしまいました。相変わらず需要があるのかよく分かりませんが
#!/usr/bin/perl while(<>){ if(m#<DIV[^>]*>(?:<A[^>]*>)?([0-9]+).+?<span class="handle">(?:<A HREF="mailto:(.+?)">)(.*?)(?:</A>)</span>:(.*?)</DIV><DIV CLASS=\"RES\">(.*)</DIV>#i){ #メール欄あり print "$3<>$2<>$4<>$5<>\n"; next; } if(m#<DIV[^>]*>(?:<A[^>]*>)?([0-9]+).+?<span class="handle">(.*?)</span>:(.*?)</DIV><DIV CLASS=\"RES\">(.*)</DIV>#i){ #メール欄なし print "$2<><>$3<>$4<>\n"; next; } }
メール欄が無いときに$2に空文字列いれる事ができれば$3以降がずれなくて、場合わけしなくてもいけたのですが、やり方わかりませんでしたorz あ、あとみみずんのhtmlで書き込みの途中で改行(<br>でなくて\n)が入ってる事があって、その場合にはその書き込みはdatに出力されません。htmlの方を編集して改行をなくしたほうが早いと思って何もしませんでしたw