3

My Emacs Dired window is wider than it is tall. After marking some files (say %m *.cpp) in Dired and running M-x dired-do-find-regexp <REGEXP> (A), I find myself in split-window-below (ex split-window-horizontally). I would like to split vertically (split-window-right) instead.

Neither setting

(setq split-width-threshold nil)

in my .emacs nor this suggestion work.

(Emacs 25.3.1 on macOS)

1
  • I added a second example to a related thread describing how to display a dired-mode buffer, or a file at point in a dired-mode buffer, in one of four directions (left, right, above, below): emacs.stackexchange.com/a/15118/2287 . I have not played around with the searching in dired feature, so I don't have a specific example for that feature. If you are a little handy with Lisp, then perhaps you may enjoy the first and/or second examples in the above link.
    – lawlist
    May 21, 2018 at 17:13

1 Answer 1

3

The function at issue is pop-to-buffer, which is called within xref--show-xref-buffer. The variable xref-show-xrefs-function is set with the default value of xref--show-xref-buffer. Thus, it is relatively simple to set the variable xref-show-xrefs-function to a user-defined function. The example below replaces xref--show-xref-buffer with a new function that calls a custom display-buffer function instead of pop-to-buffer. Over the past few years, there have been a few threads on stackexchange/stackoverflow seeking to modify the default behavior of pop-to-buffer, and there are a variety of approaches such as customizing the display-buffer-alist, or installing additional libraries designed to trump the default behavior of displaying buffers in favor of a user-defined approach, or changing the split-window-preferred-function (i.e., split-window-sensibly) to something else, and the list of other options/ideas goes on .... Inasmuch as the O.P. has indicated previously adjusting the variable split-width-threshold, @lawlist did not invest any time attempting to customize that variable and/or the companion variable for splitting in the opposite direction (i.e., split-height-threshold).

The function dired-do-find-regexp is bound in Emacs 25 to the capital letter A in dired-mode. The following code will present the user with four options when performing a search at the outset, e.g., display the target buffer left, right, above, or below. Please feel free to hard-wire it to a particular direction (by passing the optional DIRECTION argument ['left | 'right | 'above | 'below] to my-xref-display-buffer) if that seems more appealing. The sky is the limit in terms of customization, e.g., control size of the new window, etc. However, further customization is beyond the scope of this limited example.

(defun my-xref--show-xref-buffer (xrefs alist)
  (let ((xref-alist (xref--analyze xrefs)))
    (with-current-buffer (get-buffer-create xref-buffer-name)
      (let ((inhibit-read-only t))
        (erase-buffer)
        (xref--insert-xrefs xref-alist)
        (xref--xref-buffer-mode)
        (my-xref-display-buffer (current-buffer))
        (goto-char (point-min))
        (setq xref--window (assoc-default 'window alist))
        (current-buffer)))))

(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 my-xref-display-buffer (buffer &optional direction alist)
"Display an xref results buffer in the desired direction: l/r/a/b."
(interactive)
  (let* ((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 "my-xref-display-buffer:  "
                                       "You did not select l/r/a/b "
                                       "-- exiting.")))
                      (signal 'quit `(,msg)))))))))
    (select-window (my-display-buffer buffer alist direction))))

(setq xref-show-xrefs-function 'my-xref--show-xref-buffer)
2
  • Nice, especially in also handling the unpredictability of above/below and left/right, but an automated solution ("if the aspect ratio is greater than m:1, split vertically; otherwise split horizontally") would be nicer. Would gladly settle for the dired buffer to always be, say, right or below.
    – Calaf
    Aug 12, 2018 at 13:37
  • You may be interested in having a look at the built-in function window-splittable-p and weave that into your own custom function. If you run into trouble, you can always open a new question showing what you have tried, etc.
    – lawlist
    Aug 12, 2018 at 15:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.