How to make *Buffer List* appear below the other windows? - emacs

So, instead of creating a split window under (or to the right of) the currently active window, it would appear below all the existed ones with a half of the frame height? And, after closing, frame layout would be restored as it was before calling C-x C-b?
I’d like see the full paths to opened files.

See also my previous answer to your related issue: https://stackoverflow.com/a/21544307/2112489
See also a related answer by #phils, which includes a nice halve-other-window-height function: https://stackoverflow.com/a/4988206/2112489
See also the built-in stock functions display-buffer-below-selected or display-buffer-at-bottom, which are available in a recent version of Emacs Trunk -- I'm not sure when each function was first introduced. They are in window.el.
The doc-string of the function split-window states in relevant part:  SIZE defaults to half of
WINDOW's size. That is the second optional argument -- i.e., split-window (&optional window size side pixelwise)
Don't be shy about modifying these things -- you can make it do whatever you want. If want to select the window automatically after it is displayed, then you can add this to the bottom of the lawlist-display-buffer-below function:  (select-window (get-buffer-window (buffer-name buffer))) -- leaving, of course, two closing parenthesis to the right -- i.e., one closing parentheis for the let binding and one closing parenthesis for the defun.
(defun lawlist-list-buffers-below (&optional arg)
"Display a list of existing buffers.
The list is displayed in a buffer named \"*Buffer List*\".
See `buffer-menu' for a description of the Buffer Menu.
By default, all buffers are listed except those whose names start
with a space (which are for internal use). With prefix argument
ARG, show only buffers that are visiting files."
(interactive "P")
(lawlist-display-buffer-below (list-buffers-noselect arg) nil))
(defun lawlist-display-buffer-below (buffer alist)
(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)))

Related

Emacs - Open buffer list without replacing another buffer

I have one frame, one window.
I use Cx 3, I now have two windows.
I use Cx Cb in order to see the list of buffers, however it opens it in another window but doesn't put the focus on it. It is even more annoying if I had opened a buffer on the 2nd window.
I would prefer to either open the buffer list in the window which currently has the focus, or temporarily change the focus to the buffer list.
First of all I want to start by saying that the ibuffer function does similary to what you want and does so in the current window, its definitely worth checking out.
Now onto your actual question. C-x C-b by default calls the function list-buffers. If you search for that command using C-h f it will show you the documentation, from there you can view the source code for the function by clicking on the underlined text that says buff-menu.el.
Now we can view the source of the list-buffers, the first function called is display-buffer. That sounds promising. We can now use C-h f once again to search for the display-buffer command. Reading though this documentation we see that the variable display-buffer-alist dictates how the display-buffer and in turn how list-buffers works. We can then see that by adding ("*Buffer List*" . display-buffer-same-window) to display-buffer-alist you will get the desired result.
All in all you simply need to put (add-to-list 'display-buffer-alist '("*Buffer List*" . display-buffer-same-window)) in your init file for your changes to take place.
Please just try one of these:
open the buffer list who currently has the focus:
(defun my:list-buffers (&optional arg)
(interactive "P")
(display-buffer (list-buffers-no-select arg) '(display-buffer-same-window)))
change the focus
(defun my:list-buffers2 (&optional arg)
(interactive "P")
(select-window (list-buffers arg)))

How to make `C-x b RET` switch to previous buffer even if it's already shown in another frame?

Edit: What the poster calls a "window", Emacs calls a "frame". I fixed the title.
Concisely, the question is: in a window, how do I switch quickly to a buffer previously visited in that window, even if it's already opened in another window?
A more detailed description follows.
Normally, in order to switch window to previous buffer one just types C-x b RET. That is, the default argument to switch-to-buffer (or ido-switch-buffer) is the previous buffer.
This is not, however, the case when that (previous) buffer is already shown in another window. That's exactly what bugs me.
Let's consider an example. Suppose I have three buffers (A, B and C) and two windows showing buffers A and B (C is not visible at this point).
Then I open buffer A in the second window, too. So, now I have buffer A shown in both windows. Then I switch (C-x b RET) to B again. After that, C-x b RET will bring me not to A, but to C because A is already shown in the other window.
How do I make C-x b RET behave more consistently?
Update
After this problem had been solved, I realized I needed more: namely, for point position to be remembered per-window, not per buffer. Luckily, there're ready-made solutions:
winpoint
per-window-point
They're quite similar; for a discussion of differences see here.
I've found a fix for switch-to-buffer. It eventually calls
(other-buffer (current-buffer))
while in order to fix your problem, the call needs to look like this:
(other-buffer (current-buffer) t)
i.e. the visible-ok argument needs to be t.
Here's an advice to have it always at t. Hopefully it won't break other stuff that uses other-buffer:
(defadvice other-buffer (around fix-switch-to-buffer
(&optional buffer visible-ok frame) activate)
(setq visible-ok t)
ad-do-it)
Note that ido-switch-to-buffer uses a different machinery, so a different method is needed to fix it.
update: fix for ido-switch-to-buffer
I needed to re-define ido-make-buffer-list:
(defun ido-make-buffer-list (default)
(let* ((ido-current-buffers (list (buffer-name (current-buffer))))
(ido-temp-list (ido-make-buffer-list-1 (selected-frame) ido-current-buffers)))
(if ido-temp-list
(nconc ido-temp-list ido-current-buffers)
(setq ido-temp-list ido-current-buffers))
(if default
(setq ido-temp-list
(cons default (delete default ido-temp-list))))
(if (bound-and-true-p ido-enable-virtual-buffers)
(ido-add-virtual-buffers-to-list))
(run-hooks 'ido-make-buffer-list-hook)
ido-temp-list))
The diff is just one line, but it's too messy to advice it.
update: use new advice system for other-buffer
The old stuff should still work for quite a while, but here's the new approach:
(defun other-buffer-advice (orig-fun &optional buffer visible-ok frame)
(funcall orig-fun buffer t frame))
(advice-add 'other-buffer :around #'other-buffer-advice)
;; (advice-remove 'other-buffer :around #'other-buffer-advice)
Instead of advising the built-in function other-buffer, you can pre-select visible buffers using a package.
1 Using Ivy
If you're using Ivy, you can use abo-abo's approach to override the lower-use function ivy-switch-buffer.
(defun user/ivy-switch-buffer ()
"Switch to another buffer with visible-ok preselection."
(interactive)
(ivy-read "Switch to buffer: " #'internal-complete-buffer
:keymap ivy-switch-buffer-map
:preselect (buffer-name (other-buffer (current-buffer) t))
:action #'ivy--switch-buffer-action
:matcher #'ivy--switch-buffer-matcher
:caller 'ivy-switch-buffer))
(advice-add 'ivy-switch-buffer :override #'user/ivy-switch-buffer)
2 Using Ido mode
2.1 Switching to a buffer shown in another frame
If by "window" you really mean "frame" (i.e., you'd like to ido-switch-buffer to a buffer that is currently shown in another frame), then ido-mode gives you the behavior you're looking for when you change ido-default-buffer-method from its default value of raise-frame to selected-window:
(setq ido-default-buffer-method 'selected-window)
Emacs constructs an independent buffer list for each frame, so the only thing you have to do is to configure Ido to avoid jumping to another frame when you switch buffers.
2.2 Switching to a buffer that is shown in another window inside the same frame
To get this behavior across windows within the same frame, you should hook a function that reorders the buffer list onto ido-make-buffer-list-hook.
From ido.el:
;; Changing the list of files
;; --------------------------
;; By default, the list of current files is most recent first,
;; oldest last, with the exception that the files visible in the
;; current frame are put at the end of the list. A hook exists to
;; allow other functions to order the list. For example, if you add:
;;
;; (add-hook 'ido-make-buffer-list-hook 'ido-summary-buffers-to-end)
;;
;; then all files matching "Summary" are moved to the end of the
;; list. (I find this handy for keeping the INBOX Summary and so on
;; out of the way.) It also moves files matching "output\*$" to the
;; end of the list (these are created by AUCTeX when compiling.)
;; Other functions could be made available which alter the list of
;; matching files (either deleting or rearranging elements.)

Emacs org-mode: How can i fold everything but the current headline?

I use org-mode to handle my tasks and projects in multiple files.
In the weekly agenda, it is possible to jump to the location of each TODO entry using <TAB> or <RET>. If the target file was not previously open, it is loaded an the cursor is set to the correct headline and the entire document is unfolded, including drawers.
I would very much prefer to see only a sparse tree with everything but the correct headline folded (subtree visibility does not matter).
It is possible to collapse the entire tree by cycling global visibility using C-u <TAB, but then I have to find the heading again.
I know I can hide the rest by narrowing the buffer as described here:
Emacs, How can I display only current task and hide others in org-mode?
but then I loose context (parent heading, easy access to siblings) and the drawers are still open.
Ideally, I would like to have a command that shows the following:
The top level headings
The current headline, and all it's parents up to the top level
The current headline's children
Edit:
A slighty modified version of the functions user3173715 posted seems to do the trick:
(defun org-show-current-heading-tidily ()
"Show next entry, keeping other entries closed."
(if (save-excursion (end-of-line) (outline-invisible-p))
(progn (org-show-entry) (show-children))
(outline-back-to-heading)
(unless (and (bolp) (org-on-heading-p))
(org-up-heading-safe)
(hide-subtree)
(error "Boundary reached"))
(org-overview)
(org-reveal t)
(org-show-entry)
(show-children)))
This is based on the answer in the edit in the actual question.
If of help to anyone:
When I tried to bind the above to a hotkey, I kept getting an error, commandp wrong argument something something ... It turned out one had to add the (interactive) flag to make it work.
Below is an example of the function tied to M-=
(defun org-show-current-heading-tidily ()
(interactive) ;Inteactive
"Show next entry, keeping other entries closed."
(if (save-excursion (end-of-line) (outline-invisible-p))
(progn (org-show-entry) (show-children))
(outline-back-to-heading)
(unless (and (bolp) (org-on-heading-p))
(org-up-heading-safe)
(hide-subtree)
(error "Boundary reached"))
(org-overview)
(org-reveal t)
(org-show-entry)
(show-children)))
(global-set-key "\M-=" 'org-show-current-heading-tidily)
#Patrick.B thanks for edit!
Check your org startup options (customize-group > org-startup) like org-startup-folded or org-agenda-inhibit-startup (others have mentioned these already) and set the options to show only the folded view. Org mode variables like #+STARTUP are discussed here.
You may notice that everything is folded when you now jump to the agenda, even the parents of the active item may not be visible. You can then make the context (parents, children, next sibling) visible with org-reveal (C-c C-r as per the manual)
I am not very sure if this is your demand (I just think it is suitable for your question title), but I use these two functions with plenty of pleasures by binding them in the speed command of org-mode. You can find these two functions in org-mode hacks. I slightly modified them to meet my purposes.
The two functions support:
Unfold every other headings except current heading
Move current heading to top of screen for wider reading area.
In order to accomplish (2), you need to (setq recenter-positions '(top bottom)), there may be some better solutions, but I did not dig into it.
(defun ded/org-show-next-heading-tidily ()
"Show next entry, keeping other entries closed."
(if (save-excursion (end-of-line) (outline-invisible-p))
(progn (org-show-entry) (show-children))
(outline-next-heading)
(unless (and (bolp) (org-on-heading-p))
(org-up-heading-safe)
(hide-subtree)
(error "Boundary reached"))
(org-overview)
(org-reveal t)
(org-show-entry)
(recenter-top-bottom)
(show-children)
(recenter-top-bottom)))
(defun ded/org-show-previous-heading-tidily ()
"Show previous entry, keeping other entries closed."
(let ((pos (point)))
(outline-previous-heading)
(unless (and (< (point) pos) (bolp) (org-on-heading-p))
(goto-char pos)
(hide-subtree)
(error "Boundary reached"))
(org-overview)
(org-reveal t)
(org-show-entry)
(recenter-top-bottom)
(show-children)
(recenter-top-bottom)))
And you can bind them with org-mode speed key with j and l, then you can use j and l to control the folding of headings when your cursor is in the beginning of headings.
(setq org-speed-commands-user
'(("j" . ded/org-show-next-heading-tidily)
("l" . ded/org-show-previous-heading-tidily))))
It is perfect for reading org-mode files, cheers!
Current (2022) emacs no longer requires elaborate setup to achieve the goals stated in the Question:
The top level headings
The current headline, and all it's parents up to the top level
The current headline's children
In the current Emacs and org-mode versions (Emacs 27.1, as of August 2022), you can press Shift-Tab Tab to close all headings, then open the current heading. Crucially, the cursor remains on the current collapsed heading so Tab reopens it.
The only significant change that I have from a default install is Evil, which may or may not affect the fact that the cursor remains on the collapsed heading.

Make *Buffer List* always appear in horizontal split

I know Emacs tries to be intellectual and opens its helper buffers depending on which dimension of the window is bigger, so it may appear in vertical split window if current width is bigger than height, and in horizontal split otherwise.
But I’d prefer it to open that list always in horizontal split, because there are long paths I can’t see when the buffer is placed in vertical split. How can I do this?
I believe you've got the horizontal/vertical split terminology back to front (I can never remember which is which either), but as your goal was to retain the original window's width, I'm forcing a vertical split.
See C-hf split-window-sensibly RET. It tells you what to do:
You can enforce this function to not split WINDOW horizontally,
by setting (or binding) the variable `split-width-threshold' to
nil. If, in addition, you set `split-height-threshold' to zero,
chances increase that this function does split WINDOW vertically.
So as a permanent setting:
(setq split-width-threshold nil)
(setq split-height-threshold 0)
For just a specific function, you can advise that function (but see Edit 2 below!):
(defadvice list-buffers (around list-buffers-split-vertically)
"Always split vertically when displaying the buffer list.
See `split-window-sensibly'."
(let ((split-width-threshold nil)
(split-height-threshold 0))
ad-do-it))
(ad-activate 'list-buffers)
Edit: Actually, in this instance I suspect you're only concerned with the interactive case, in which case it's preferable to define a function and remap the bindings:
(defun my-list-buffers-vertical-split ()
"`list-buffers', but forcing a vertical split.
See `split-window-sensibly'."
(interactive)
(let ((split-width-threshold nil)
(split-height-threshold 0))
(call-interactively 'list-buffers)))
(global-set-key [remap list-buffers] 'my-list-buffers-vertical-split)
Edit 2: And Stefan points out that display-buffer-alist facilitates such things without advising functions (and of course avoiding unnecessary advice is always a good thing). I believe we still need a custom action, so:
(defun my-display-buffer-pop-up-same-width-window (buffer alist)
"A `display-buffer' ACTION forcing a vertical window split.
See `split-window-sensibly' and `display-buffer-pop-up-window'."
(let ((split-width-threshold nil)
(split-height-threshold 0))
(display-buffer-pop-up-window buffer alist)))
(add-to-list 'display-buffer-alist
'("\\*Buffer List\\*" my-display-buffer-pop-up-same-width-window))
If horizontally or vertically, presently neither split-height-threshold nor split-width-threshold seem reliable WRT to expected kind of split. Which looks like a bug, resp. design issue.
As a work-around call M-x split-window-horizontally resp. -vertically before, or advise the function with it.
You can remove (5) if you prefer not to select the window after it is displayed -- i.e., remove (select-window (get-buffer-window (buffer-name buffer))). I like the bottom window to be reserved for a 3-month calendar, so that's why I have a condition to use the window above (if it exists) -- you can remove that condition if you are so inclined. Actually, it's your function so you can modify everything as you see fit now that you see how it works. The alist would be used like this: '((window-width . 33)) if you wanted to control certain aspects of the target window, etc. I find myself always going back to this document page because it is the only scanty formal example I've found . . . and, of course, the source itself window.el: http://www.gnu.org/software/emacs/manual/html_node/elisp/Display-Action-Functions.html
(defun lawlist-list-buffers-left (&optional arg)
"Display a list of existing buffers.
The list is displayed in a buffer named \"*Buffer List*\".
See `buffer-menu' for a description of the Buffer Menu.
By default, all buffers are listed except those whose names start
with a space (which are for internal use). With prefix argument
ARG, show only buffers that are visiting files."
(interactive "P")
(lawlist-display-buffer-left (list-buffers-noselect arg) nil))
(defun lawlist-list-buffers-right (&optional arg)
"Display a list of existing buffers.
The list is displayed in a buffer named \"*Buffer List*\".
See `buffer-menu' for a description of the Buffer Menu.
By default, all buffers are listed except those whose names start
with a space (which are for internal use). With prefix argument
ARG, show only buffers that are visiting files."
(interactive "P")
(lawlist-display-buffer-right (list-buffers-noselect arg) nil))
(defun lawlist-display-buffer-left (buffer alist)
"(1) If `buffer` is already displayed, then display it again in the same window.
(2) If `buffer` is not already displayed, and if there is a window to the left,
then display that `buffer` in said window. (3) If `buffer` is not already
displayed, and if there is a window to the right, then use the selected window.
(4) If all else fails, then create a new window to the left and display `buffer` there.
(5) Select the target window which displays `buffer`."
(let (
(window
(cond
((get-buffer-window buffer (selected-frame)))
((window-in-direction 'above))
((window-in-direction 'left))
((window-in-direction 'right)
(selected-window))
(t
(split-window (selected-window) nil 'left)))))
(window--display-buffer buffer window 'window alist display-buffer-mark-dedicated)
;; OPTIONAL -- uncomment to select the target window.
;; (select-window (get-buffer-window (buffer-name buffer)))
))
(defun lawlist-display-buffer-right (buffer alist)
"(1) If `buffer` is already displayed, then display it again in the same window.
(2) If `buffer` is not already displayed, and if there is a window to the right,
then display that `buffer` in said window. (3) If `buffer` is not already
displayed, and if there is a window to the left, then use the selected window.
(4) If all else fails, then create a new window to the right and display `buffer` there.
(5) Select the target window which displays `buffer`."
(let (
(window
(cond
((get-buffer-window buffer (selected-frame)))
((window-in-direction 'above))
((window-in-direction 'right))
((window-in-direction 'left)
(selected-window))
(t
(split-window (selected-window) nil 'right)))))
(window--display-buffer buffer window 'window alist display-buffer-mark-dedicated)
;; OPTIONAL -- uncomment to select the target window.
;; (select-window (get-buffer-window (buffer-name buffer)))
))

Emacs ido start with open buffers first in cycle list

When switching buffers with emacs ido mode enabled, a list of completions are displayed in the minibuffer. It appears there is a "feature" that buffers that are already open are put to the end of the list. I, however, often open the same buffer in multiple panes.
Is there a way to either turn this "feature" off, or alternatively do the opposite: have the buffers that are already open be at the front of the completion list?
The main point of ido mode is that you don't use arrows to navigate between buffers in the minibuffer. Instead you type the part of the buffer's name. In this case it doesn't matter where the buffer is in the list.
This is not possible unless you want to wade deep in ido's intestines.
As eGlyph already said: You're likely using ido wrongly (and there's also C-s for <right> and C-r for <left>; no need for arrow keys).
But you can define command for choosing among the already shown buffers (here only from the current frame, if you want all shown buffers you have to collect the windows first via `frame-list):
(defun choose-from-shown-buffers ()
(interactive)
(let ((buffers (mapcar (lambda (window)
(buffer-name (window-buffer window)))
(window-list))))
(pop-to-buffer (ido-completing-read "Buffer: " buffers))))