最近閉じたファイル
silog - memo/xyzzy/file #最後に閉じたファイルを開く にインスパイヤされました。
今回の改造にあたって加えられた新たなオリジナリティは以下。
- add-history でヒストリに登録するようにしました。
- ダイアログを追加しました。
以下の環境で動作確認しました。
- Windows XP Home Edition SP2
- xyzzy 0.2.2.235
recent-closed-file-open-last-one で最後に閉じたファイルを開きます。
recent-closed-file-open-dialog で最近閉じたファイルをダイアログ表示します。ファイルを選択して『OK』を押すと、選択したファイルを開きます。
開いたファイルはヒストリから消されます。
ヒストリの最大個数は *minibuffer-maximum-history-count* です。
コード
;; 最近閉じたファイル ; * silog - memo/xyzzy/file #最後に閉じたファイルを開く ; <http://white.s151.xrea.com/wiki/index.php?memo%2Fxyzzy%2Ffile#k96261fd> ; から朴りました。 (defvar *recent-closed-file-history* nil) ; ヒストリ変数をファイルに保存する ; 削除するときは ; > (unregister-history-variable '*recent-closed-file-history*) ; するのを忘れるな ;(define-history-variable *recent-closed-file-history* nil) (defun recent-closed-file-add-history () (let ((file (get-buffer-file-name))) (if file (if (file-exist-p file) (add-history file '*recent-closed-file-history*) (or (delete file *recent-closed-file-history* :test #'path-equal) (setq *recent-closed-file-history* nil))))) t) #| ; 保存するヒストリの個数を別に設定する ; 負の値を指定すると無制限 (defvar *recent-closed-file-maximum-history-count* *minibuffer-maximum-history-count*) (defun recent-closed-file-add-history () (let ((file (get-buffer-file-name))) (when file (or (delete file *recent-closed-file-history* :test #'path-equal) (setq *recent-closed-file-history* nil)) (if (file-exist-p file) (push file *recent-closed-file-history*)))) (let (n) (and (<= 0 *recent-closed-file-maximum-history-count*) (setq n (- (list-length *recent-closed-file-history*) *recent-closed-file-maximum-history-count*)) (> n 0) (or (nbutlast *recent-closed-file-history* n) (setq *recent-closed-file-history* nil)))) t) |# (add-hook '*query-kill-buffer-hook* 'recent-closed-file-add-history) ; 最後に閉じたファイルを開く (defun recent-closed-file-open-last-one () (interactive) (unless *recent-closed-file-history* (plain-error "ヒストリは空です")) (let ((file (pop *recent-closed-file-history*))) (unless (file-exist-p file) (plain-error "~A: そんなファイルはありません" file)) (find-file file))) ; ダイアログ (defvar *recent-closed-file-open-dialog-template* `(dialog 0 0 298 117 (:caption "最近閉じたファイル") (:font 9 "MS UI Gothic") (:control (:listbox IDC_LIST nil #x50b10119 5 6 288 84) (:button IDOK "&OK" #x50010001 6 96 50 14) (:button IDCANCEL "&Cancel" #x50010000 60 96 50 14)))) (defun recent-closed-file-open-dialog () (interactive) (let ((hlist (mapcar #'(lambda (x) (list (abbreviate-display-string x 96 t) x)) *recent-closed-file-history*))) (multiple-value-bind (result data) (let ((omode (get-ime-mode))) (toggle-ime nil) (unwind-protect (dialog-box *recent-closed-file-open-dialog-template* `((IDC_LIST . ,hlist)) `((IDC_LIST :column (1) :must-match t :enable (IDOK)))) (toggle-ime omode))) (if result (let ((lst (cdr (assoc 'IDC_LIST data))) dlst) (dolist (var lst t) (let ((filename (nth 1 var))) (or (delete filename *recent-closed-file-history*) (setq *recent-closed-file-history* nil)) (if (file-exist-p filename) (progn (find-file filename) (add-history filename '*minibuffer-file-name-history*)) (push filename dlst)))) (if dlst (let ((lstlen (list-length lst)) (dlstlen (list-length dlst))) (if (= lstlen dlstlen 1) (message "~A: そんなファイルはありません" (car dlst)) (msgbox (format nil "~D 個中 ~D 個のファイルが見つかりませんでした~%~{~%~A~}" lstlen dlstlen dlst))) nil) t)))))) ; 『ファイル』メニューに追加 (add-hook '*post-startup-hook* #'(lambda () (let* ((file (get-menu *app-menu* 'ed::file)) (pos (get-menu-position file :above-kill-xyzzy))) (insert-menu-item file pos nil "最近閉じたファイル(&L)..." 'recent-closed-file-open-dialog #'(lambda () (or *recent-closed-file-history* :disable))))))
最近使ったファイル
xyzzy の音 - ファイル操作 #最近使ったファイル一覧 にインスパイヤされました。
今回の改造にあたって加えられた新たなオリジナリティは以下。
- ダイアログで複数選択できるようにしました。
- 存在しないファイルを開こうとした時に、ヒストリから削除するようにしました。
以下の環境で動作確認しました。
- Windows XP Home Edition SP2
- xyzzy 0.2.2.235
最近使ったファイルをダイアログ表示します。
ダイアログでファイルを選択して『OK』を押すと、選択したファイルを開きます。
コード
;; 最近使ったファイル ; * xyzzy の音 - ファイル操作 #最近使ったファイル一覧 ; <http://hie.s64.xrea.com/xyzzy/note/file-handling.html#list-recents> ; から朴りました。 (defvar *recent-file-open-dialog-template* `(dialog 0 0 298 117 (:caption "最近使ったファイル") (:font 9 "MS UI Gothic") (:control (:listbox IDC_LIST nil #x50b10119 5 6 288 84) (:button IDOK "&OK" #x50010001 6 96 50 14) (:button IDCANCEL "&Cancel" #x50010000 60 96 50 14)))) (defun recent-file-open-dialog () (interactive) (let ((hlist (mapcar #'(lambda (x) (list (abbreviate-display-string x 96 t) x)) *minibuffer-file-name-history*))) (multiple-value-bind (result data) (let ((omode (get-ime-mode))) (toggle-ime nil) (unwind-protect (dialog-box *recent-file-open-dialog-template* (list (cons 'IDC_LIST hlist)) '(list (IDC_LIST :column (1) :must-match t :enable (IDOK)))) (toggle-ime omode))) (if result (let ((lst (cdr (assoc 'IDC_LIST data))) dlst) (dolist (var lst t) (let ((filename (nth 1 var))) (cond ((file-exist-p filename) (find-file filename) (add-history filename '*minibuffer-file-name-history*)) (t (push filename dlst) (or (delete filename *minibuffer-file-name-history*) (setq *minibuffer-file-name-history* nil)))))) (if dlst (let ((lstlen (list-length lst)) (dlstlen (list-length dlst))) (if (= lstlen dlstlen 1) (message "~A: そんなファイルはありません" (car dlst)) (msgbox (format nil "~D 個中 ~D 個のファイルが見つかりませんでした~%~{~%~A~}" lstlen dlstlen dlst))) nil) t)))))) ; メニューの『ファイル』->『最近使ったファイル...』と入れ替える (add-hook '*post-startup-hook* #'(lambda () (let* ((file (get-menu *app-menu* 'ed::file)) (pos (1+ (get-menu-position file :above-recent)))) (delete-menu file pos t) (insert-menu-item file pos nil "最近使ったファイル(&F)..." 'recent-file-open-dialog #'(lambda () (or *minibuffer-file-name-history* :disable))))))
url ファイルが D&D されたら URL を挿入する
http://xyzzy.s53.xrea.com/wiki/index.php?cmd=read&page=tips%2FURL%A5%B7%A5%E7%A1%BC%A5%C8%A5%AB%A5%C3%A5%C8%A4%F2D%A1%F5D%A4%B5%A4%EC%A4%BF%A4%E9URL%A4%F2%C1%DE%C6%FE%A4%B9%A4%EB にインスパイヤされました。
今回の改造にあたって加えられた新たなオリジナリティは以下。
- *insert-url-string-func-alist* で挿入する文字列を生成するようにしました。
- *before-find-file-hook* にフックすると url ファイルが xyzzy で開けなくなるので、*drag-and-drop-hook* にセットするようにしました。
以下の環境で動作確認しました。
- Windows XP Home Edition SP2
- xyzzy 0.2.2.235
『応用例』を追加しました。
url ファイルを D&D すると、カレントバッファのカーソル位置に内容を挿入します。
*insert-url-string-func-alist* は、挿入文字列を生成する関数の連想リストで、要素に関数のペアをセットします。先頭の要素から car 部の関数を実行していき、関数が non-nil を返した要素の cdr 部の関数を使用して挿入文字列を生成します。
*insert-url-string-default-func* には、デフォルトの挿入文字列生成関数をセットします。*insert-url-string-func-alist* で生成関数を決定できなかった場合に使用されます。
以下のものが定義済みです。
- html-mode,
- //www1.odn.ne.jp/ymtz/html_plus-mode.html">html+-mode, xml-mode のマイナーモード XHTML1.0/1.1:『<a href="URL">ファイル名</a>\n』という文字列を挿入する
- lisp-mode, lisp-interaction-mode
- 『* ファイル名\n <URL>\n』という文字列を挿入する
- text-mode
- 『* ファイル名\n URL\n』という文字列を挿入する
- デフォルト
- 『ファイル名\nURL\n』という文字列を挿入する
コード
;; url ファイルが D&D されたら URL を挿入する ; * tips/URLショートカットをD&DされたらURLを挿入する - XyzzyWiki ; <http://xyzzy.s53.xrea.com/wiki/index.php?cmd=read&page=tips%2FURL%A5%B7%A5%E7%A1%BC%A5%C8%A5%AB%A5%C3%A5%C8%A4%F2D%A1%F5D%A4%B5%A4%EC%A4%BF%A4%E9URL%A4%F2%C1%DE%C6%FE%A4%B9%A4%EB> ; から朴りました。 ; url ファイルが D&D されたら URL を挿入するか否か (defvar *insert-url-string-enable* t) ; デフォルトの挿入文字列生成関数 ; 引数 : name - 文字列 - url ファイルのファイル名 ; 引数 : url - 文字列 - url ファイルの InternetShortcut セクション->URL キーの値 ; 戻り値: 挿入する文字列 (defvar *insert-url-string-default-func* #'(lambda (name url) (format nil "~A~%~A~%" name url))) ; 関数の連想リスト ; car の関数が non-nil を返すとき cdr の関数で挿入文字列を生成する ; car の関数の引数はドロップされた url ファイルのパス (defvar *insert-url-string-func-alist* (list (cons #'(lambda (&optional f) (or (member buffer-mode '("html-mode" "html+-mode") :test #'string=) (and (string= buffer-mode "xml-mode") (string-match "^xml:XHTML1\\.\\(?:0-\\(?:Strict\\|Frameset\\|Transitional\\)\\|1\\)$" mode-name)))) (let* ((rs #'(lambda (str alst) (dolist (var alst str) (setq str (substitute-string str (car var) (cdr var)))))) (getu #'(lambda (url) (funcall rs url '(("&" . "&") ("<" . "<") (">" . ">") ("\"" . """))))) (getn #'(lambda (name) (funcall rs name '(("&" . "&") ("<" . "<") (">" . ">")))))) #'(lambda (name url) (format nil "<a href=\"~A\">~A</a>~%" (funcall getu url) (funcall getn name))))) (cons #'(lambda (&optional f) (member buffer-mode '("lisp-mode" "lisp-interaction-mode") :test #'string=)) #'(lambda (name url) (format nil "* ~A~% <~A>~%" name url))) (cons #'(lambda (&optional f) (string= buffer-mode "text-mode")) #'(lambda (name url) (format nil "* ~A~% ~A~%" name url))) )) ; ドロップされた url ファイルをごみ箱へ移動するか否か (defvar *insert-url-string-kill-shortcut-file* nil) (defun insert-url-string-get-func (&optional f) (or (some #'(lambda (x) (if (funcall (car x) f) (cdr x))) *insert-url-string-func-alist*) *insert-url-string-default-func*)) ;(require "api") (unless (fboundp 'GetPrivateProfileString) (require "wip/winapi") (c:define-dll-entry winapi:DWORD GetPrivateProfileString (winapi:LPCSTR winapi:LPCSTR winapi:LPCSTR winapi:LPCSTR winapi:DWORD winapi:LPCSTR) "kernel32" "GetPrivateProfileStringA")) (defun insert-url-string (f) (let* ((name (pathname-name f)) (sec (si:make-string-chunk "InternetShortcut")) (key (si:make-string-chunk "URL")) (non (si:make-string-chunk "")) (sz 508) (url (si:make-chunk nil sz)) (file (si:make-string-chunk (map-slash-to-backslash f))) (func (insert-url-string-get-func f))) ;(win-user::GetPrivateProfileString sec key non url sz file) (GetPrivateProfileString sec key non url sz file) (setq url (si:unpack-string url 0)) (insert (funcall func name url)) (if *insert-url-string-kill-shortcut-file* (delete-file f :recycle t)) (selected-buffer))) (setq *drag-and-drop-hook* #'(lambda (window files) (and *insert-url-string-enable* (not (minibuffer-window-p window)) (let ((i 0) (n (list-length files))) (while (< i n) (let ((f (nth i files))) (when (string-equal "url" (pathname-type f)) (insert-url-string f) (or (delete f files) (setq files nil) (return)) (decf i) (decf n))) (incf i)))) (if files (ed::default-drag-and-drop-hook window files) t)))
応用例
以下の関数は、unDonut で現在のタブの URL とタイトルを、カレントバッファのカーソル位置に挿入します。
DonutP.API を使用するので、COM サーバの登録が行われていなければ動作しません。DonutP にもあるメソッドとプロパティしか使用していないので、DonutP でも使えると思います。
引数には、対象のタブの数を指定します。
例えば 3 と指定すると、現在のタブから右方向に 3 個のタブが対象となります。また、負の値を指定すると、左方向になります。
0 を指定すると、すべてのタブが対象となります。
省略時は、1 を指定したときと同じく現在のタブのみが対象となります。
戻り値は、挿入した URL とタイトルの数です。
M-x などでインタラクティブに呼び出すときには、C-u に続けて数字を入力すれば、関数に引数が渡せます。つまり、『C-u 3 M-x insert-url-string-undonut-current-tab』で 『(insert-url-string-undonut-current-tab 3)』を評価したときと同様になります。
インタラクティブに前置引数のみで呼び出したときには、すべてのタブが対象となります。つまり、『C-u M-x insert-url-string-undonut-current-tab』で、『(insert-url-string-undonut-current-tab 0)』を評価したときと同様になります。
(defun insert-url-string-undonut-current-tab (&optional (arg 1)) (interactive "*p") (let ((dntp (ole-create-object "DonutP.API"))) (if dntp (let ((cnt #{dntp.GetTabCount[]})) (if (> cnt 0) (let* ((all (or (zerop arg) (eq *prefix-args* 'universal-argument))) (idx (if all 0 #{dntp.TabIndex})) (inc (if (or all (plusp arg)) #'1+ #'1-)) (ins #'(lambda () (let ((doc #{dntp.GetDocumentObject[idx]})) (if doc (let ((url #{doc.URL}) (title #{doc.title})) (if (string= title "") (setq title url)) (insert (funcall (insert-url-string-get-func) title url)) (< -1 (setq idx (funcall inc idx)) cnt))))))) (dotimes (i (cond (all (- cnt idx)) ((minusp arg) (- arg)) (t arg)) i) (unless (funcall ins) (return (1+ i))))))))))
はてなダイアリーへようこそ!
このページはあなた専用の日記(ブログ)です。*1
さっそく「日記を書く」をクリックして最初の記事を書いてみましょう。
はてなダイアリーの一番簡単な使い方を知りたい方は、以下の動画をご覧ください。
(再生ボタンをクリックすると、はてなダイアリーの使い方を音声と動画で見ることができます。)
はてなダイアリーのヘルプでは、このような動画を交えた使い方の説明や、文字の色の付け方、本やDVDを紹介する「はてな記法」の使い方を解説しています。
より詳しいはてなダイアリーの使い方を知りたい方は、以下のヘルプをご覧ください。
それでは、日々の出来事やテレビ番組の感想、普段考えていることなど、あなたならではの日記を書いて楽しんでください!
*1:この文章はサンプルです。実際に自分の記事を書くときには削除しても大丈夫です。