How to intercept a file before it opens and decide which frame

后端 未结 1 1812
你的背包
你的背包 2020-11-27 05:17

I am looking for some ideas, please, regarding how to intercept a file before it opens and make a decision which frame to open it in.

I have a modified version of

相关标签:
1条回答
  • 2020-11-27 06:08
    ;;  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 讨论(0)
提交回复
热议问题