Cara menggunakan "o" untuk membuka dari dired / ibuffer ke bingkai lain

8

Saya memiliki dua jendela yang terbuka dan terbelah secara vertikal (satu frame):

A) berisi pekerjaan saya
B) berisi dired atau ibuffer.

Saya ingin dapat menavigasi ke file / buffer di panel B dan tekan "o" buka di panel A. Apakah ini mungkin? Sekarang emacs sedang membuat panel baru di bagian bawah panel A untuk membuka file.

sunting: sesuai dengan daftar hukum pengguna, perilaku yang dijelaskan di atas akan terjadi ketika bingkai besar. Ini tampaknya menjadi masalah bagi saya karena sekarang saya di rumah (bukan pada monitor eksternal, bingkai yang lebih kecil) berperilaku seperti yang saya inginkan. Pertanyaannya sekarang menjadi: bisakah saya mencegah emacs membuka jendela baru ketika bingkai saat ini besar?

Robert
sumber
1
Selamat datang di forum beta Emacs. Sebagai bagian dari istilah / jargon Emacs, kami menggunakan kata tersebut windowuntuk merujuk ke kuadran buffer di dalam yang sama frame. A framedianggap sebagai keseluruhan kucing-kaboodle, yang dapat memiliki banyak jendela di dalamnya. Emacs dapat menghasilkan banyak bingkai, dengan setiap bingkai berisi banyak jendela.
hukum
terimakasih atas klarifikasinya! Saya sudah lama menjadi pengguna emacs tetapi tidak pernah sepenuhnya memahami terminologinya.
Robert

Jawaban:

6

Berikut adalah empat (4) contoh display-bufferkelompok fungsi kustom yang dapat disesuaikan sesuai kebutuhan khusus pengguna - di atas ; di bawah ; kiri ; kanan - dan di sini ada empat (4) interactivefungsi untuk menampilkan file atau direktori dari baris dired-modebuffer saat ini. Hanya ada tiga kondisi: (a) jika sudah ada jendela yang menampilkan buffer target, lalu pilih; (B) jika ada jendela ke arah yang diinginkan yang tersedia, maka gunakan; (C) catch-all adalah untuk membuat jendela baru ke arah yang diinginkan jika kondisi lain tidak terpenuhi.

Pemakaian:

M-x dired-display-above

M-x dired-display-below

M-x dired-display-left

M-x dired-display-right

Ada begitu banyak ikatan kunci yang sudah ada di dalamnya dired-modedan dired+, sehingga saya tidak berani mencoba membuat milik saya sendiri. Pengguna bebas memilih pintasan keyboardnya sendiri, yang berada di luar cakupan contoh terbatas ini.

Pengguna bebas untuk menambahkan kondisi tambahan ke display-bufferkeluarga contoh fungsi untuk menangani lebih banyak situasi - misalnya, lebih banyak jendela daripada hanya beberapa.

(defun my-display-buffer-below (buffer alist)
"Doc-string."
  (let (
      (window
        (cond
          ((get-buffer-window buffer (selected-frame)))
          ((window-in-direction 'below))
          (t
            (split-window (selected-window) nil 'below)))))
    (window--display-buffer buffer window 'window alist display-buffer-mark-dedicated)
    window))

(defun my-display-buffer-above (buffer alist)
"Doc-string."
  (let (
      (window
        (cond
          ((get-buffer-window buffer (selected-frame)))
          ((window-in-direction 'above))
          (t
            (split-window (selected-window) nil 'above)))))
    (window--display-buffer buffer window 'window alist display-buffer-mark-dedicated)
    window))

(defun my-display-buffer-left (buffer alist)
"Doc-string."
  (let (
      (window
        (cond
          ((get-buffer-window buffer (selected-frame)))
          ((window-in-direction 'left))
          (t
            (split-window (selected-window) nil 'left)))))
    (window--display-buffer buffer window 'window alist display-buffer-mark-dedicated)
    window))

(defun my-display-buffer-right (buffer alist)
"Doc-string."
  (let (
      (window
        (cond
          ((get-buffer-window buffer (selected-frame)))
          ((window-in-direction 'right))
          (t
            (split-window (selected-window) nil 'right)))))
    (window--display-buffer buffer window 'window alist display-buffer-mark-dedicated)
    window))

(defun dired-display-above ()
"Doc-string."
(interactive)
  (let* (
      (file-or-dir (dired-get-file-for-visit))
      (buffer (find-file-noselect file-or-dir)))
    (my-display-buffer-above buffer nil)))

(defun dired-display-below ()
"Doc-string."
(interactive)
  (let* (
      (file-or-dir (dired-get-file-for-visit))
      (buffer (find-file-noselect file-or-dir)))
    (my-display-buffer-below buffer nil)))

(defun dired-display-left ()
"Doc-string."
(interactive)
  (let* (
      (file-or-dir (dired-get-file-for-visit))
      (buffer (find-file-noselect file-or-dir)))
    (my-display-buffer-left buffer nil)))

(defun dired-display-right ()
"Doc-string."
(interactive)
  (let* (
      (file-or-dir (dired-get-file-for-visit))
      (buffer (find-file-noselect file-or-dir)))
    (my-display-buffer-right buffer nil)))

EDIT: Ini adalah implementasi yang sedikit lebih canggih / menyenangkan dari konsep di atas, yang memberi pengguna kemampuan untuk menggunakan ini secara non-interaktif atau interaktif ; misalnya, M-x dired-display-buffer- di mana pengguna akan diminta untuk memilih direktori jika tidak mengarahkan file dired-mode, dan untuk memilih arah tampilan (kiri, kanan, atas, di bawah, di bawah).

(defun my-display-buffer (buffer-or-name alist direction &optional size pixelwise)
"BUFFER:  The buffer that will be displayed.
ALIST:  See the doc-string of `display-buffer' for more information.
DIRECTION:  Must use one of these symbols:  'left 'right 'below 'above
SIZE:  See the doc-string for `split-window'.
PIXELWISE:  See the doc-string for `split-window'.
There are three possibilities:
-  (1) If a window on the frame already displays the target buffer,
then just reuse the same window.
-  (2) If there is already a window in the specified direction in relation
to the selected window, then display the target buffer in said window.
-  (3) If there is no window in the specified direction, then create one
in that direction and display the target buffer in said window."
  (let* ((buffer
           (if (bufferp buffer-or-name)
             buffer-or-name
             (get-buffer buffer-or-name)))
         (window
           (cond
             ((get-buffer-window buffer (selected-frame)))
             ((window-in-direction direction))
             (t
               (split-window (selected-window) size direction pixelwise)))))
    (window--display-buffer buffer window 'window alist display-buffer-mark-dedicated)
    window))

(defun dired-display-buffer (&optional direction alist)
"Display a dired-mode buffer or a file underneath point in a dired-mode buffer."
(interactive)
  (let* ((file-or-dir (or (and (eq major-mode 'dired-mode) (dired-get-file-for-visit))
                               (read-directory-name "Directory:  ")))
         (buffer (find-file-noselect file-or-dir))
         (direction
           (if direction
             direction
             (let ((char (read-char-exclusive (concat
                      "["
                      (propertize "l" 'face '(:foreground "red"))
                      "]"
                      (propertize "eft" 'face '(:foreground "blue"))
                      " | ["
                      (propertize "r" 'face '(:foreground "red"))
                      "]"
                      (propertize "ight" 'face '(:foreground "blue"))
                      " | ["
                      (propertize "a" 'face '(:foreground "red"))
                      "]"
                      (propertize "bove" 'face '(:foreground "blue"))
                      " | ["
                      (propertize "b" 'face '(:foreground "red"))
                      "]"
                      (propertize "elow" 'face '(:foreground "blue"))))))
                (cond
                  ((eq char ?l)
                    'left)
                  ((eq char ?r)
                    'right)
                  ((eq char ?a)
                    'above)
                  ((eq char ?b)
                    'below)
                  ;;; FIXME:  @lawlist may add a loop similar to `org-capture'
                  ;;; whereby a new `read-char-exclusive' will be initiated if
                  ;;; a user did not initially choose a valid option (l/r/a/b).
                  (t
                    (let ((debug-on-quit nil)
                          (msg (concat "dired-display-buffer:  "
                                       "You did not select l/r/a/b "
                                       "-- exiting.")))
                      (signal 'quit `(,msg)))))))))
    (my-display-buffer buffer alist direction)))
daftar hukum
sumber
oh ini sempurna. Dapatkah seseorang membantu saya dengan hydra sederhana untuk dired-mode-map, terikat ke odan kemudian hjkluntuk tampilan-atas / bawah / kiri / kanan?
iLemming
oh saya rasa saya mengerti: (defhydra dired-open (dired-mode-map "O" :exit t) "dired-open" ("j" dired-display-below "below") ("k" dired-display-above "above") ("h" dired-display-left "left") ("l" dired-display-right "left"))
iLemming
Hal kecil tentang pendekatan - tidak melompat ke jendela yang baru dibuat. Tidak tahu bagaimana cara memaksanya.
iLemming
2
@ Agzam - Fungsi select-windowini dapat digunakan di ujung setiap my-display-buffer-...fungsi. Seperti yang Anda lihat, hasil / nilai yang dilemparkan di akhir pada baris terakhir adalah window. Jika Anda tidak perlu hasil / nilai untuk digunakan dalam hubungannya dengan fungsi lain, maka hanya membungkus window pada baris yang terakhir dengan ini: (select-window window). Lakukan itu dengan keempat (4) fungsi - yaitu my-display-buffer-below,; my-display-buffer-above; my-display-buffer-left; dan my-display-buffer-right.
hukum
3

Pertanyaan Anda tidak jelas, dan karenanya berisiko ditutup. Apakah Anda memiliki dua bingkai atau satu bingkai dengan dua jendela Emacs? Apa pun itu, jika ada dua, apakah masing - masing dibelah secara vertikal? Dan apa yang Anda maksud dengan "membagi secara vertikal"? Apa yang Anda maksud dengan "panel"? Apa yang Anda maksud dengan "itu", di "sudah terbuka di panel A"?

Tebakan liar adalah bahwa Anda memiliki satu bingkai Emacs yang terbagi menjadi dua jendela Emacs, A dan B, dengan jendela A di atas jendela B, jendela B dipilih, dan jendela B menunjukkan buffer Dired.

oterikat secara default ke dired-find-file-other-window. Jika di atas menebak benar maka opada nama file dalam B harus terbuka di A. Ini adalah apa yang saya lihat ketika memulai Emacs tanpa file init: emacs -Q. Apakah kamu tidak melihat itu?

Jika ini bukan skenarionya, jelaskan dengan jelas apa yang Anda lakukan, langkah demi langkah, dimulai dengan emacs -Q.

Drew
sumber
2
Tergantung pada ukuran bingkai - bingkai besar akan menghasilkan perilaku yang dijelaskan oleh OP; sedangkan, kerangka yang lebih kecil akan menghasilkan perilaku yang dijelaskan Drew.
hukum
daftar hukum saya pikir itulah yang terjadi. Ketika terpasang ke monitor eksternal saya dengan bingkai besar apa yang saya gambarkan terjadi, tetapi sekarang saya berada di rumah pada layar laptop saya yang lebih kecil itu bertanya seperti yang saya inginkan - apakah ada cara untuk memaksanya untuk tidak membuka jendela lain?
Robert
Hai Drew, maaf, saya tidak sepenuhnya mempercepat emacs lingo sehubungan dengan perbedaan antara bingkai & jendela. Apa yang saya maksudkan dalam pertanyaan awal saya (jika sekarang saya mengerti jendela dan bingkai dengan benar) adalah bahwa saya memiliki satu bingkai emacs dan dua jendela emacs berdampingan (secara vertikal Cx 3). Semuanya berfungsi seperti yang dimaksudkan ketika saya di laptop saya dan bingkainya kecil, tapi seperti yang tercantum dalam daftar hukum saat bingkainya besar apa yang saya jelaskan terjadi.
Robert
Ya itu mungkin. Namun, pengaturan umum display-bufferkeluarga variabel akan mempengaruhi situasi lain yang belum diramalkan. Anda dapat menyesuaikan display-buffer-alist, yang agak membingungkan bahkan untuk pengguna Emacs yang berpengalaman. Ada variabel yang mengontrol kapan harus membagi windows dan ukuran minimum windows, dan daftar berjalan terus. Untuk mengatasi wabah, Anda dapat memberi saran dired-find-file-other-windowdengan versi let-bound display-buffer-alist, tetapi saya akan menyerahkan jawaban itu kepada peserta forum lain. Ada berbagai solusi. :)
hukum
1

CATATAN : Variabel berikut bersifat global , yang berarti bahwa mereka akan memengaruhi fungsi lain di samping dired-find-file-other-window. Pengguna mungkin ingin menyarankan fungsi yang dipermasalahkan agar tidak memengaruhi fungsi lainnya secara global . [Namun, penulis ini akan menyerahkan opsi itu kepada peserta forum lain.] Atau, ada jawaban lain yang diposting penulis ini yang berisi fungsi khusus yang dapat digunakan agar tidak mempengaruhi hal lain.


Variabel split-width-thresholdmemiliki doc-string yang menyatakan:

Minimum width for splitting windows sensibly.
If this is an integer, ‘split-window-sensibly’ may split a window
horizontally only if it has at least this many columns.  If this
is nil, ‘split-window-sensibly’ is not allowed to split a window
horizontally.

Pengaturan berikut ini di .emacsfile akan mencapai efek yang diinginkan. Pengguna juga dapat mengatur nilai ke angka yang lebih tinggi. Nilai standarnya adalah 160

(setq split-width-threshold nil)

Berikut ini tautan ke bagian yang relevan di manual:

https://www.gnu.org/software/emacs/manual/html_node/emacs/Window-Choice.html


Lihat juga variabel terkait split-height-threshold, yang memiliki nilai default 80

Doc-string menyatakan:

Minimum height for splitting windows sensibly.
If this is an integer, `split-window-sensibly' may split a window
vertically only if it has at least this many lines.  If this is
nil, `split-window-sensibly' is not allowed to split a window
vertically.  If, however, a window is the only window on its
frame, `split-window-sensibly' may split it vertically
disregarding the value of this variable.
daftar hukum
sumber
Ini sebenarnya bekerja dengan sangat baik! Sekarang jika sesuatu yang lucu mulai terjadi saya setidaknya tahu ke mana harus mencari. Terima kasih lagi!
Robert