Calaf
Calaf

Reputation: 10837

Increase/decrease font size in an emacs frame (not just buffer)

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.

Upvotes: 10

Views: 6631

Answers (6)

alexpanter
alexpanter

Reputation: 1588

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!

Upvotes: 0

Gregory Vincic
Gregory Vincic

Reputation: 324

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.

Upvotes: 1

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)

Upvotes: 6

Drew
Drew

Reputation: 30708

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.)

Upvotes: 3

Jordon Biondo
Jordon Biondo

Reputation: 4039

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.

Upvotes: 4

rje
rje

Reputation: 6438

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

Upvotes: -1

Related Questions