Centre Emacs buffer within window - emacs

I wrap all my code at 80 columns, and there are times where the Emacs window is wider than 80 columns and there is a lot of unused whitespace on the right side.
I would like to position the Emacs buffer, so all the text is displayed in the middle of the window.
This is different to centre aligning text (more akin to the whitespace on either side of the text when viewing pdfs).
I think this can be achieved by dynamically adjusting the fringe mode widths, depending on the current window size, but I'm not sure where to start. Any ideas?

As demonstrated here this is indeed possible:
(set-fringe-mode
(/ (- (frame-pixel-width)
(* 80 (frame-char-width)))
2))
However, as I am testing this I seem to have more luck with using margins, at least when also resizing my frame:
(defun my-resize-margins ()
(let ((margin-size (/ (- (frame-width) 80) 2)))
(set-window-margins nil margin-size margin-size)))
(add-hook 'window-configuration-change-hook #'my-resize-margins)
(my-resize-margins)

Here is a function which should do what you want, using margins instead of fringes (since I tend to display buffer boundaries in the fringe and I find it becomes ugly if the fringe is too large).
(defun my/center (width)
(interactive "nBuffer width: ")
(let* ((adj (- (window-text-width)
width))
(total-margin (+ adj
left-margin-width
right-margin-width)))
(setq left-margin-width (/ total-margin 2))
(setq right-margin-width (- total-margin left-margin-width)))
(set-window-buffer (selected-window) (current-buffer)))

You ask to display the buffer in the center of the window, which just moves some of the extra whitespace to the left of the buffer, from the right.
How about a solution that eliminates that extra whitespace instead? If that is acceptable, here are two approaches.
If the buffer is alone in its frame, then you can fit the frame to the buffer, using library fit-frame.el. I bind command fit-frame to C-x C-_. This saves space not only within Emacs but for your desktop. (Library zoom-frm.el lets you also shrink/enlarge a frame incrementally, so you can save space by shrinking a frame when you don't need to see its content in detail.)
If not (so the buffer is shown in a frame where there are multiple windows), and if the buffer's window has another window to the left or right of it, then you can do one of the following:
2a. If the buffer's window has another window to the left or right of it, then you can use command fit-window-to-buffer. But you will also need to set option fit-window-to-buffer-horizontally to non-nil.
2b. Use C-{ (shrink-window-horizontally), followed by C-x z z z..., to incrementally shrink the window width (removing the extra whitespace).
2c. Load library face-remap+.el. Whenever you use text-scaling (e.g. C-x C- or C-x =), the window size grows or shrinks along with the text size, so you don't get extra whitespace added at the right when you shrink the text. This is controlled by user option text-scale-resize-window.

Center window mode
https://github.com/anler/centered-window-mode
Global minor mode that centers the text of the window.
If another window is visible the text goes back to normal if its width is less than "cwm-centered-window-width."

Modern answer is https://github.com/rnkn/olivetti or https://github.com/joostkremers/writeroom-mode, both worked immediately for me where other things did not

Related

Emacs 26.3: jerky scroll

Emac's scrolling is quite jerky and unpredictable. Weirdly, as you scroll, the top line nearly never is a line with no characters--but is very very rarely. My best guess is that emacs's vertical scrollbar is perhaps not considering the number of lines in the file but the number of characters, or something? Then once it finds the character it wants to have on the top line it backtracks to find the beginning of that character?
Any way to simply have this give every line an equal share of the scrollbar scroll region?
I added the following to my ~/.emacs file.
The first three adjust appearance while using the scroll bar. Just scroll-conservatively may be enough in most cases but I see edge cases where the other two seem to help. I don't have a full explanation and would like to know more if anyone has an idea.
The next two affect the mouse's scroll wheel. Specifically, the mouse-wheel-scroll-amount setting means move 2 lines per wheel click normally, 10 lines if shift is being held down. or entire page (what nil means in this use) (the number of lines on the screen) if control is being held down. mouse-wheel-progressive-speed prevents scroll from getting faster and faster as you do more of it.
(setq scroll-step 1)
(setq scroll-conservatively 10000)
(setq auto-window-vscroll nil)
(setq mouse-wheel-scroll-amount '(2 ((shift) . 10) ((control) . nil)))
(setq mouse-wheel-progressive-speed nil)

Moving point to the end of the last line without reorienting the buffer

Is it possible to move point to the end of a buffer without reorienting the text around that line? This seems to be the default behaviour of goto-char. My goal is to correct a minor annoyance which places the cursor at the second last line when I press "L". I wrote a custom function to do this properly but now when I move the point to the last line the screen scrolls down half a page and it becomes the center of the buffer.
(defun cf-last-line (count) (interactive "p")
(let ((max (truncate (window-screen-lines))))
(move-to-window-line max)
(line-move (* -1 (1- count)) t t)
(beginning-of-line)))
Edit: It turns out my problem is related to the fact that the GUI shows partial lines (which may appear to be fully exposed but upon closer inspection lie just below the status bus). I suppose my question then becomes whether or not it is possible to have the point lie on such a partial line (though I suspect this is unlikely) without moving it to the center and if not whether it is possible to instead prevent the X11 frame from showing partial lines at the bottom of the window.
Solution as described by lawlist:
(setq scroll-conservatively 101)
(setq make-cursor-line-fully-visible nil)

How to recenter an Emacs buffer around an overlay

I want to recenter an Emacs buffer so as to show as much as possible of an overlay and of its context around it. Specifically, I want this behavior:
If the overlay fits in the visible window, I want to show as much as line before it as lines after it;
Otherwise, I want the beginning of the overlay to be shown.
This behavior is somewhat similar to what I see when using different regions highlighted in ediff.
Is there a not-so-complicated way to achieve this? I tried to look into the ediff code (specifically ediff-util.el) but things seems very complicated to me.
I'm not quite sure what usage you're looking for, but this code should do what you want.
It can be called with an overlay, or if called interactively, will choose one of the overlays at the current position and do the action on it.
(defun make-overlay-visible (overlay)
"given an overlay, center it on the window
(or make beginning visible if it cannot fit in the window)"
(interactive (list (car (overlays-at (point)))))
(when overlay
(goto-char (overlay-start overlay))
(recenter 0)
(when (and (pos-visible-in-window-p (overlay-start overlay))
(pos-visible-in-window-p (overlay-end overlay)))
(goto-char (/ (+ (overlay-start overlay) (overlay-end overlay)) 2))
(recenter))))

Emacs / Slime / Hard Code Vertical Split Ratio

I'm currently in mode: C-x 2
Normally, I don't care much about vertical splitting. However, I'm coding on a 13" display, which makes vertical space rather precious.
I would like some setup where when I do C-x 2, my window is not split 50/50, but rather 70/30 [this way I can send the repl to the bottom portion of the screen, and stll see quite a bit of code.]
C-h a vertical split
brings up:
split-window-vertically, table-split-call-vertically
However, I suspect there is some parameter that changes / controls the split ratio.
What emacs option tells my computer to split 70/30 rather than 50/50?
Thanks!
You can use a prefix argument to tell Emacs how many lines to give each of the two windows.
See: C-hk C-x2
or C-hf split-window-below RET
If optional argument SIZE is omitted or nil, both windows get the
same height, or close to it. If SIZE is positive, the upper
(selected) window gets SIZE lines. If SIZE is negative, the
lower (new) window gets -SIZE lines.
So you could give the upper window 20 lines and the lower window the remainder with: C-u 20 C-x2
(or M-2M-0C-x2, etc...)
And you could give the lower window 10 lines and the upper window the remainder with: C-u -10 C-x2
(or M--M-1M-0C-x2, etc...)
See How to change size of split screen emacs windows? for lots of ways to modify the size of windows after splitting.
Edit:
You can use the following function to do what you want:
(defun my-split-window-below (&optional arg)
"Split the current window 70/30 rather than 50/50.
A single-digit prefix argument gives the top window arg*10%."
(interactive "P")
(let ((proportion (* (or arg 7) 0.1)))
(split-window-below (round (* proportion (window-height))))))
(global-set-key (kbd "C-c x 2") 'my-split-window-below)
The default ratio is 70/30, but you can supply a single-digit prefix argument to specify the size of the top window in 10% increments.
If you bound this command to C-x2 then C-9C-x2 would give the top window 90% and the bottom 10%.
Edit 2: I ended up using a variation of that as my own C-x2 binding. This version defaults to a normal 50/50 split, but provides the same prefix arg functionality of the other function in case I want something different.
(defun my-split-window-below (&optional arg)
"Split the current window 50/50 by default.
A single-digit prefix argument gives the top window ARG * 10%
of the available lines."
(interactive "P")
(let* ((proportion (and arg (* arg 0.1)))
(size (and proportion (round (* proportion (window-height))))))
(split-window-below size)))

How to resize a buffer so it only takes a small part of the screen?

In Emacs how can I resize a buffer so it only takes a small part of the screen ?
Is there any way ?
I would like to have the src taking 70% of the screen and a file manager in the other 30%
Set width of current window on current frame to ~ 70%:
(window-resize nil (- (truncate (* 0.7 (frame-width))) (window-width)) t)
The other windows are shrunk automatically. If you want to adjust more than one it gets more difficult.
As command:
(defun window-resize-to-70-percent ()
(interactive)
(window-resize nil (- (truncate (* 0.7 (frame-width))) (window-width)) t))
Use separate window-manager frames for individual buffers (by default). Automatically shrink-fit the frames to fit the buffer content.
See One-On-One Emacs, in particular, libraries fit-frame.el and autofit-frame.el.