2013-08-20 15 views
8

szukam jakieś pomysły, proszę, dotyczące sposobu przechwycenia pliku, zanim otworzy się i podjąć decyzję, która ramka, aby otworzyć go w.Jak przechwycić plik, zanim otworzy się i zdecydować, które rama

mam zmodyfikowana wersja frame-bufs autorstwa Alp Aker - https://github.com/alpaker/Frame-Bufs - która działa z aktualną wersją Emacs Trunk. Napisałem funkcję, która kojarzy otwierany plik z ramką, która ma fokus. Chciałbym zrobić jeszcze jeden krok i ustawić listę file types i buffer names, które zawsze będą powiązane z konkretną ramką. Myślałam o funkcji, która robi coś takiego:

* If the file being opened is 
    (or (eq major-mode 'text-mode) (eq major-mode 'latex-mode)) 
      (switch-to-frame "TEXT") 

* If the buffer being opened is 
    (or (equal (buffer-name) "Folder") (equal (buffer-name) "Summary")) 
      (switch-to-frame "WANDERLUST") 

* After completing either of the above, open the file/buffer. 

* Run the custom frame association function -- (associate-current-buffer) 

Zakładam, że jest możliwe, aby dowiedzieć się, w jakim trybie plik jest przed to jest rzeczywiście otwarte w ramce. Jaki byłby najlepszy sposób na zrobienie tego?

+1

Dobrą wiadomością jest to, że właśnie do tego służy 'display-buffer-alist'. Zła wiadomość jest taka, że ​​'display-buffer-alist' jest dość skomplikowany w użyciu. Jego dokumentacja oraz "display-buffer" są kompletne, ale dość lakoniczne. – dfan

+1

Dziękuję za wskazówkę - przyjrzę się bliżej dokumentacji "display-buffer-alist" - może nie będzie tak źle, ponieważ nie muszę przejmować żadnych istniejących okien ani podziału dowolne okna i nie będzie żadnych modyfikacji istniejącej ramki. Będę miał jedną funkcję, która po prostu sprawdza istnienie ramki i tworzy ją, jeśli nie ma jej pod tą nazwą. http://www.gnu.org/software/emacs/manual/html_node/elisp/Display-Action-Functions.html – lawlist

+1

'Zakładam, że możliwe jest ustalenie, który tryb pliku jest, zanim zostanie faktycznie otwarty w frame. "Myślę, że jedynym sposobem jest ręczne parsowanie auto-mode-alist i sprawdzanie pod nazwą pliku. – Malabarba

Odpowiedz

6
;; To try out this example, copy and paste the entire contents of everything 
;; in this answer to the `*scratch*' buffer and type: M-x eval-buffer RET 
;; Then type: M-x db-example RET 
;; 
;; `db-open-file' also works out-of-the-box by typing: M-x db-open-file RET 
;; 
;; 
;; The frame names are defined with the variable `db-frame-name'. 
;; The preconfigured frame names are: SYSTEM, MAIN, ORG, MISCELLANEOUS. 
;; 
;; Buffers are displayed in specific frames based on the `buffer-name'. 
;; 
;; If the `buffer-name' matches a regexp defined `db-special-buffer', 
;; then display that buffer in the current frame. 
;; 
;; If the `buffer-name' matches a regexp defined by `db-system-buffer', 
;; then display that buffer in a frame named SYSTEM. 
;; 
;; If the `buffer-name' matches a regexp defined by `db-main-buffer', 
;; then display that buffer in a frame named MAIN. 
;; 
;; If the `buffer-name' matches a regexp defined by `db-org-buffer', 
;; then display that buffer in a frame named ORG. 
;; 
;; If the `buffer-name' does not match any of the above-mentioned regexp, 
;; then display that buffer in a frame named MISCELLANEOUS. 
;; 
;; 
;; The following are a few methods of setting the `display-buffer-alist': 
;; 
;; (1) Set the `display-buffer-alist' explicitly with `setq': 
;; 
;;  (setq display-buffer-alist '((".*" . (db-pop-up-frame)))) 
;; 
;; (2) Add to an existing `display-buffer-alist' using `add-to-list': 
;; 
;;  (add-to-list 'display-buffer-alist '(".*" . (db-pop-up-frame))) 
;; 
;; (3) Call the function as part of the `display-buffer' statement: 
;; 
;;  (display-buffer (get-buffer-create "foo") '(db-pop-up-frame)) 
;; 
;; (4) Use the `display-buffer-alist' on a let-bound basis: 
;; 
;;  (let ((display-buffer-alist '((".*" . (db-pop-up-frame))))) 
;;  [any additional code]) 

(defvar db-frame-name "^\\(?:SYSTEM\\|MAIN\\|ORG\\|MISCELLANEOUS\\)$" 
    "Frame names that are used to help organize buffers.") 

(defvar db-system-buffer '("\\*scratch\\*" "\\*bbdb\\*" "\\*bar\\*") 
    "Regexp of file/buffer names displayed in frame `SYSTEM`.") 

(defvar db-main-buffer 
    '("\\.txt" "\\.tex" "\\.el" "\\.yasnippet" "\\*foo\\*") 
    "Regexp of file/buffer names displayed in frame `MAIN`.") 

(defvar db-org-buffer 
    '("\\*TODO\\*" "\\*Org Agenda\\*" "\\.org_archive" "\\.org") 
    "Regexp of file/buffer names displayed in frame `ORG`.") 

(defvar db-special-buffer 
    '("\\*special\\*" "\\*baz\\*") 
    "Regexp of file/buffer names that will display in current frame.") 

(defun db-pop-up-frame (buffer alist) 
    (cond 
    ;; condition # 1 -- either file-visiting or no-file buffers 
    ((db-regexp-match-p db-org-buffer (buffer-name buffer)) 
     (if (db-get-frame--drew-adams "ORG") 
     (select-frame-set-input-focus (db-get-frame--drew-adams "ORG")) 
     ;; If unnamed frame exists, then take control of it. 
     (catch 'break (dolist (frame (frame-list)) 
      (if (not (string-match db-frame-name 
       (frame-parameter frame 'name))) 
      (throw 'break (progn 
       (select-frame-set-input-focus 
       (db-get-frame--drew-adams (frame-parameter frame 'name))) 
       (set-frame-name "ORG")))))) 
     ;; If dolist found no unnamed frame, then create/name it. 
     (when (not (db-get-frame--drew-adams "ORG")) 
      (make-frame (list '(name . "ORG"))))) 
     (unless (get-buffer-window buffer) 
     (set-window-buffer (get-largest-window) buffer)) 
     (select-window (get-buffer-window buffer))) 
    ;; condition # 2 -- either file-visiting or no-file buffers 
    ((db-regexp-match-p db-main-buffer (buffer-name buffer)) 
     (if (db-get-frame--drew-adams "MAIN") 
     (select-frame-set-input-focus (db-get-frame--drew-adams "MAIN")) 
     ;; If unnamed frame exists, then take control of it. 
     (catch 'break (dolist (frame (frame-list)) 
      (if (not (string-match db-frame-name 
       (frame-parameter frame 'name))) 
      (throw 'break (progn 
       (select-frame-set-input-focus 
       (db-get-frame--drew-adams (frame-parameter frame 'name))) 
       (set-frame-name "MAIN")))))) 
     ;; If dolist found no unnamed frame, then create/name it. 
     (when (not (db-get-frame--drew-adams "MAIN")) 
      (make-frame (list '(name . "MAIN"))))) 
     (unless (get-buffer-window buffer) 
     (set-window-buffer (get-largest-window) buffer)) 
     (select-window (get-buffer-window buffer))) 
    ;; condition # 3 -- either file-visiting or no-file buffers 
    ((db-regexp-match-p db-system-buffer (buffer-name buffer)) 
     (if (db-get-frame--drew-adams "SYSTEM") 
     (select-frame-set-input-focus (db-get-frame--drew-adams "SYSTEM")) 
     ;; If unnamed frame exists, then take control of it. 
     (catch 'break (dolist (frame (frame-list)) 
      (if (not (string-match db-frame-name 
       (frame-parameter frame 'name))) 
      (throw 'break (progn 
       (select-frame-set-input-focus 
       (db-get-frame--drew-adams (frame-parameter frame 'name))) 
       (set-frame-name "SYSTEM")))))) 
     ;; If dolist found no unnamed frame, then create/name it. 
     (when (not (db-get-frame--drew-adams "SYSTEM")) 
      (make-frame (list '(name . "SYSTEM"))))) 
     (unless (get-buffer-window buffer) 
     (set-window-buffer (get-largest-window) buffer)) 
     (select-window (get-buffer-window buffer))) 
    ;; condition # 4 
    ;; display buffer in the existing frame 
    ((db-regexp-match-p db-special-buffer (buffer-name buffer)) 
     (unless (get-buffer-window buffer) 
     (set-window-buffer (get-largest-window) buffer)) 
     (select-window (get-buffer-window buffer))) 
    ;; condition # 5 
    ;; file-visiting buffers that do NOT match any pre-defined regexp 
    ((and (not (db-regexp-match-p db-org-buffer (buffer-name buffer))) 
      (not (db-regexp-match-p db-main-buffer (buffer-name buffer))) 
      (not (db-regexp-match-p db-system-buffer (buffer-name buffer))) 
      (not (db-regexp-match-p db-special-buffer (buffer-name buffer))) 
      (buffer-file-name (get-buffer (buffer-name buffer)))) 
     (if (db-get-frame--drew-adams "MISCELLANEOUS") 
     (select-frame-set-input-focus 
      (db-get-frame--drew-adams "MISCELLANEOUS")) 
     ;; If unnamed frame exists, then take control of it. 
     (catch 'break (dolist (frame (frame-list)) 
      (if (not (string-match db-frame-name 
       (frame-parameter frame 'name))) 
      (throw 'break (progn 
       (select-frame-set-input-focus 
       (db-get-frame--drew-adams (frame-parameter frame 'name))) 
       (set-frame-name "MISCELLANEOUS")))))) 
     ;; If dolist found no unnamed frame, then create/name it. 
     (when (not (db-get-frame--drew-adams "MISCELLANEOUS")) 
      (make-frame (list '(name . "MISCELLANEOUS"))))) 
     (unless (get-buffer-window buffer) 
     (set-window-buffer (get-largest-window) buffer)) 
     (select-window (get-buffer-window buffer))) 
    ;; condition # 6 
    ;; default display for no-file-visiting buffers 
    (t nil))) 

;; https://github.com/kentaro/auto-save-buffers-enhanced 
;; `db-regexp-match-p` function modified by @sds on stackoverflow 
;; http://stackoverflow.com/a/20343715/2112489 
(defun db-regexp-match-p (regexps string) 
    (and string 
     (catch 'matched 
     (let ((inhibit-changing-match-data t)) 
      (dolist (regexp regexps) 
      (when (string-match regexp string) 
       (throw 'matched t))))))) 

;; Original Author: Drew Adams -- http://www.emacswiki.org/emacs/frame-fns.el 
;; @lawlist combined the functions `get-frame-name` and `get-a-frame`. 
(defun db-get-frame--drew-adams (frame) 
    "Return a frame, if any, named FRAME (a frame or a string). 
    If none, return nil. 
    If FRAME is a frame, it is returned." 
    (let ((get-frame-name--drew-adams 
      (lambda (&optional frame) 
      (unless frame (setq frame (selected-frame))) 
      (if (framep frame) 
       (cdr (assq 'name (frame-parameters frame))) 
       (error "Argument not a frame: `%s'" frame))))) 
    (cond ((framep frame) frame) 
      ((stringp frame) 
      (catch 'get-a-frame-found 
      (dolist (fr (frame-list)) 
       (when (string= frame (funcall get-frame-name--drew-adams fr)) 
       (throw 'get-a-frame-found fr))) 
      nil)) 
      (t 
      (error "Arg neither a string nor a frame: `%s'" frame))))) 

(defun db-open-file (&optional filename) 
"With assistance from the `display-buffer-alist', locate or create a 
specific frame, and then open the file." 
(interactive) 
    (let ((display-buffer-alist '((".*" . (db-pop-up-frame))))) 
    (display-buffer (find-file-noselect 
     (if filename 
     filename 
     (if (eq system-type 'darwin) 
      (ns-read-file-name "Select File: " "~/" t nil nil) 
      (read-file-name "Select File: " "~/" nil nil nil nil))))))) 

(when (eq system-type 'darwin) 

    (defun db-ns-find-file() 
    "Do a `find-file' with the `ns-input-file' as argument." 
    (interactive) 
    (let* (
     (display-buffer-alist '((".*" . (db-pop-up-frame)))) 
     (f (file-truename (expand-file-name (pop ns-input-file) 
       command-line-default-directory)))) 
     (ns-hide-emacs 'activate) 
     (display-buffer (find-file-noselect f)))) 

    (defalias 'ns-find-file 'db-ns-find-file)) 

(defun db-example() 
"This is an example that uses the custom function `db-pop-up-frame' to 
display buffers in different frames or windows depending upon the situation. 
The `auto-mode-alist' is set to `nil` due to a bug in one of the versions 
of `org-mode' where it attempts to recenter a window that is not visible." 
(interactive) 
    ;; condition # 3 | file-visiting buffer 
    (let* (
     (auto-mode-alist nil) 
     (display-buffer-alist '((".*" . (db-pop-up-frame))))) 
    (display-buffer (find-file-noselect "*bar*")) 
    (set-frame-height (selected-frame) 20) 
    (set-frame-width (selected-frame) 80) 
    (set-frame-position (selected-frame) 0 0) 
    (message "\*bar\* appears in frame name SYSTEM.") 
    (sit-for 2) 
    ;; condition # 4(a) | no-file-visiting buffer 
    (display-buffer (get-buffer-create "*default*")) 
    (message "NO-FILE buffer existing frame.") 
    (sit-for 2) 
    ;; condition # 2(a) | file-visiting buffer 
    (display-buffer (find-file-noselect "foo.txt")) 
    (set-frame-height (selected-frame) 20) 
    (set-frame-width (selected-frame) 80) 
    (set-frame-position (selected-frame) 100 100) 
    (message "\"foo.txt\" appears in frame name MAIN.") 
    (sit-for 2) 
    ;; condition # 1 | file-visiting buffer 
    (display-buffer (find-file-noselect "doe.org")) 
    (set-frame-height (selected-frame) 20) 
    (set-frame-width (selected-frame) 80) 
    (set-frame-position (selected-frame) 200 200) 
    (message "\"doe.org\" appears in frame name ORG.") 
    (sit-for 2) 
    ;; condition # 4(b) | file-visiting buffer 
    (display-buffer (find-file-noselect "*special*")) 
    (message "FILE buffer existing frame.") 
    (sit-for 2) 
    ;; condition # 6 | no-file-visiting buffer default display 
    (calendar) 
    (message "Default for no-file-visiting-buffers.") 
    (sit-for 2) 
    ;; condition # 5 | file-visiting buffer with no pre-defined regexp. 
    (display-buffer (find-file-noselect "*undefined*")) 
    (set-frame-height (selected-frame) 20) 
    (set-frame-width (selected-frame) 80) 
    (set-frame-position (selected-frame) 300 300) 
    (message "\*IS\* buffer-filename. \*NOT\* defined by any particular regexp.") 
    (sit-for 2) 
    ;; condition # 2(b) | no-file-visiting buffer 
    (display-buffer (get-buffer-create "*foo*")) 
    (set-frame-height (selected-frame) 20) 
    (set-frame-width (selected-frame) 80) 
    (set-frame-position (selected-frame) 400 400) 
    (message "\*NOT\* buffer-filename. \*IS\* defined by db-main-buffer.") 
    (sit-for 2) 
    (kill-buffer "*foo*") 
    (kill-buffer "*bar*") 
    (kill-buffer "*default*") 
    (kill-buffer "*undefined*") 
    (kill-buffer "*Calendar*") 
    (kill-buffer "*special*") 
    (kill-buffer "foo.txt") 
    (kill-buffer "doe.org") 
    (make-frame) 
    (delete-frame (db-get-frame--drew-adams "SYSTEM")) 
    (delete-frame (db-get-frame--drew-adams "MAIN")) 
    (delete-frame (db-get-frame--drew-adams "ORG")) 
    (delete-frame (db-get-frame--drew-adams "MISCELLANEOUS")) 
    (message "THE END."))) 
+0

+1. Czy nie ma 8 sekund na "siedzenie za"? Wiem, że możesz go złamać wprowadzając dane przez użytkownika, ale nadal ... –

+1

Czytałem powoli i miałem problemy z zobaczeniem, co się dzieje, mimo że to ja jestem tym, który pisze kod. :) Zgasnę kilka sekund dla czytników prędkości. Naprawiony. :) – lawlist

Powiązane problemy