8

Using C-x C-+ and C-x C-- (text-scale-adjust) is very convenient to increase/decrease the font size in one buffer. This is nice to reduce head bumping when a few people work together in front of the same monitor.

Is there a way to increase (and later decrease) the font size in one frame (or all frames simultaneously)? I am wondering if there is a way faster than 1- retyping C-x C-+ in each new buffer, 2- Calling M-x x-select-font and using the mouse to choose, and 3- running elisp code in the scratch buffer.

Update:

If you are interested in satisfying not just 1-3 above but also:

4- Keep the size (and position) of the frame still.

Then look at this question.

Community
  • 1
  • 1
Calaf
  • 10,113
  • 15
  • 57
  • 120

6 Answers6

6

Based on @Jordon Biondo's answer, this is an alternative solution that solves the collateral effect of changing the frame's size by using set-frame-font with the argument KEEP-SIZE equals to t.

;; Resize the whole frame, and not only a window
;; Adapted from https://stackoverflow.com/a/24714383/5103881
(defun acg/zoom-frame (&optional amt frame)
  "Increaze FRAME font size by amount AMT. Defaults to selected
frame if FRAME is nil, and to 1 if AMT is nil."
  (interactive "p")
  (let* ((frame (or frame (selected-frame)))
         (font (face-attribute 'default :font frame))
         (size (font-get font :size))
         (amt (or amt 1))
         (new-size (+ size amt)))
    (set-frame-font (font-spec :size new-size) t `(,frame))
    (message "Frame's font new size: %d" new-size)))

(defun acg/zoom-frame-out (&optional amt frame)
  "Call `acg/zoom-frame' with negative argument."
  (interactive "p")
  (acg/zoom-frame (- (or amt 1)) frame))

(global-set-key (kbd "C-x C-=") 'acg/zoom-frame)
(global-set-key (kbd "C-x C--") 'acg/zoom-frame-out)
(global-set-key (kbd "<C-down-mouse-4>") 'acg/zoom-frame)
(global-set-key (kbd "<C-down-mouse-5>") 'acg/zoom-frame-out)
  • 1
    Nice! Just in time (with covid-19) to ask folks to abstain from sticking their heads right above your shoulders just because you are showing them something. The resizing is a bit jarring, but you only need to do this once until everyone confirms they can see clearly from where they are. – Calaf Mar 11 '20 at 18:44
  • 2
    Works great for me! – Dave Abrahams Nov 07 '21 at 22:40
  • 1
    It works perfectly! (Although, why `C-x C-=` for zoom, and not `C-x C-+`?) This answer would deserve to be the first one in this other, heavily-voted [How to set the font size in Emacs?](https://stackoverflow.com/q/294664/9450152) post! – kotchwane Feb 12 '22 at 12:47
  • 1
    Works! Btw. what are down-mouse-4/5 buttons? – Ev Dolzhenko May 05 '23 at 10:37
  • 1
    @EvDolzhenko these were mouse scroll events, if I remember correctly. – Arthur Colombini Gusmão May 10 '23 at 08:59
3

See the Emacs Wiki page about frame zooming.

It tells you about several ways to do this, including commands from libraries zoom-frm.el, doremi-frm.el, and frame-cmds.el.

In particular, the single command zoom-in/out lets you zoom either a frame or a buffer in or out. (The former: zooming a frame, is what you requested.)

Calaf
  • 10,113
  • 15
  • 57
  • 120
Drew
  • 29,895
  • 7
  • 74
  • 104
  • 1
    None of the three is available via Melpa. Should one bite the bullet and just install the dependencies (each has several) manually? – Calaf Jul 18 '19 at 15:50
  • @Calaf: If one wants to use the libraries, yes. The libraries are offered freely. It's not hard to "manually" put them in a directory that is in one's `load-path` and `require` them. But if one doesn't want to do that then one can do without the libraries. – Drew Jul 18 '19 at 16:41
  • Funny.. It was an innocent question, really. I'm not familiar with the process for getting something into melpa, and one is... um.. I am still manually maintaining my own collection, partly because sometimes a firewall makes this the only option. But I also keep thinking that it's 2019 and I should modernize the setup and hop fully on melpa. Glad to know that you in particular do bless this approach as non, or not yet, arcane. – Calaf Jul 18 '19 at 17:43
  • 1
    @Calaf: Sorry if I sounded harsh. Sorry for the added trouble. – Drew Jul 18 '19 at 20:50
3

This is not the most correct way to do it, I have in the past use these functions to do frame by frame resizing:

In this case it is done by changing the :height attribute of the default face.

(defun zoom-frame (&optional n frame amt)
  "Increase the default size of text by AMT inside FRAME N times.
  N can be given as a prefix arg.
  AMT will default to 10.
  FRAME will default the selected frame."
  (interactive "p")
  (let ((frame (or frame (selected-frame)))
        (height (+ (face-attribute 'default :height frame) (* n (or amt 10)))))
    (set-face-attribute 'default frame :height height)
    (when (called-interactively-p)
      (message "Set frame's default text height to %d." height))))

(defun zoom-frame-out (&optional n frame amt)
  "Call `zoom-frame' with -N."
  (interactive "p")
  (zoom-frame (- n) frame amt))


(global-set-key (kbd "C-c z i") 'zoom-frame)

(global-set-key (kbd "C-c z o") 'zoom-frame-out)

This scales the whole frame, not just the text, so it'll shrink or grow on your desktop, possibly growing outside the visibility bounds and requiring a redraw from your OS.

Another possible solution is which I may look into, is setting a frame local variable to a desired height and using a hook that runs each time a buffer is selected to redisplay the text in that buffer to the frame's desired size. This would work decently well unless a buffer was shown on two frames.

Jordon Biondo
  • 3,974
  • 1
  • 27
  • 37
0

You can change font size for all frames using the command line

$ emacsclient -e "(set-face-attribute 'default nil :height 180)"

Change the height value to your needs. Then bind that command to an alias or a shortcut your window manager provides.

Gregory Vincic
  • 304
  • 3
  • 8
0

An easy solution

I noticed that although I usually use C-x + to zoom in, I could do the same with C-+. This led me to a nice observation:

  • I can hold down a button (C) and then press another button repeatedly (+) to zoom.

This means that I can keep the behaviour of C-x + to affect the zoom of only current buffer, while having another key C-+ to affect zoom of the entire frame. This in my opinion is nice behaviour - your requirements may vary. The code is quite simple as well:

(defvar face-attribute-height 125
  "Default font face height when Emacs starts.")

(defun face-attribute-height-increase ()
  (interactive)
  (setq face-attribute-height (+ face-attribute-height 5))
  (set-face-attribute 'default nil :height face-attribute-height)
  )
(defun face-attribute-height-decrease ()
  (interactive)
  (setq face-attribute-height (- face-attribute-height 5))
  (set-face-attribute 'default nil :height face-attribute-height)
  )

(define-key global-map (kbd "C-+") 'face-attribute-height-increase)
(define-key global-map (kbd "C--") 'face-attribute-height-decrease)

I'm not an "expert" elisp-coder, and it can probably be written better. Feedback is welcome!

alexpanter
  • 1,222
  • 10
  • 25
-1

See http://www.emacswiki.org/emacs/GlobalTextScaleMode, or for a more general explanation: http://www.emacswiki.org/emacs/SetFonts#toc6

rje
  • 6,388
  • 1
  • 21
  • 40
  • No, text scaling is not *frame* zooming. Global text scaling is just *buffer* zooming applied to all buffers. Frame and buffer zooming are two different things. See your second link for info about the differences. – Drew Jul 11 '14 at 21:31