How do I set the size of Emacs' window? - emacs

I'm trying to detect the size of the screen I'm starting emacs on, and adjust the size and position the window it is starting in (I guess that's the frame in emacs-speak) accordingly. I'm trying to set up my .emacs so that I always get a "reasonably-big" window with it's top-left corner near the top-left of my screen.
I guess this is a big ask for the general case, so to narrow things down a bit I'm most interested in GNU Emacs 22 on Windows and (Debian) Linux.

If you want to change the size according to resolution you can do something like this (adjusting the preferred width and resolutions according to your specific needs):
(defun set-frame-size-according-to-resolution ()
(interactive)
(if window-system
(progn
;; use 120 char wide window for largeish displays
;; and smaller 80 column windows for smaller displays
;; pick whatever numbers make sense for you
(if (> (x-display-pixel-width) 1280)
(add-to-list 'default-frame-alist (cons 'width 120))
(add-to-list 'default-frame-alist (cons 'width 80)))
;; for the height, subtract a couple hundred pixels
;; from the screen height (for panels, menubars and
;; whatnot), then divide by the height of a char to
;; get the height we want
(add-to-list 'default-frame-alist
(cons 'height (/ (- (x-display-pixel-height) 200)
(frame-char-height)))))))
(set-frame-size-according-to-resolution)
Note that window-system is deprecated in newer versions of emacs. A suitable replacement is (display-graphic-p). See this answer to the question How to detect that emacs is in terminal-mode? for a little more background.

I've got the following in my .emacs:
(if (window-system)
(set-frame-height (selected-frame) 60))
You might also look at the functions set-frame-size, set-frame-position, and set-frame-width. Use C-h f (aka M-x describe-function) to bring up detailed documentation.
I'm not sure if there's a way to compute the max height/width of a frame in the current windowing environment.

Taken from: http://www.gnu.org/software/emacs/windows/old/faq4.html
(setq default-frame-alist
'((top . 200) (left . 400)
(width . 80) (height . 40)
(cursor-color . "white")
(cursor-type . box)
(foreground-color . "yellow")
(background-color . "black")
(font . "-*-Courier-normal-r-*-*-13-*-*-*-c-*-iso8859-1")))
(setq initial-frame-alist '((top . 10) (left . 30)))
The first setting applies to all emacs frames including the first one that pops up when you start. The second setting adds additional attributes to the first frame. This is because it is sometimes nice to know the original frame that you start emacs in.

Try adding the following code to .emacs
(add-to-list 'default-frame-alist '(height . 24))
(add-to-list 'default-frame-alist '(width . 80))

The easiest way I've found to do that in an X-Window environment is through X resources. The relevant part of my .Xdefaults looks like this:
Emacs.geometry: 80x70
You should be able to suffix it with +0+0 location coordinates to force it to the upper-left corner of your display. (the reason I don't do it is that I occasionnally spawn new frames, and it makes things confusing if they appear in the exact same location as the previous one)
According to the manual, this technique works on MS Windows too, storing the resources as key/value pairs in the registry. I never tested that. It might be great, it might be much more of an inconvenience compared to simply editing a file.

You can also the -geometry parameter when firing up emacs: emacs -geometry 80x60+20+30 will give you a window 80 characters wide, 60 rows high, with the top left corner 20 pixels to the right and 30 pixels down from the top left corner of the background.

On ubuntu do:
(defun toggle-fullscreen ()
(interactive)
(x-send-client-message nil 0 nil "_NET_WM_STATE" 32
'(2 "_NET_WM_STATE_MAXIMIZED_VERT" 0))
(x-send-client-message nil 0 nil "_NET_WM_STATE" 32
'(2 "_NET_WM_STATE_MAXIMIZED_HORZ" 0))
)
(toggle-fullscreen)

On windows, you could make emacs frame maximized using this function :
(defun w32-maximize-frame ()
"Maximize the current frame"
(interactive)
(w32-send-sys-command 61488))

(setq initial-frame-alist
(append '((width . 263) (height . 112) (top . -5) (left . 5) (font . "4.System VIO"))
initial-frame-alist))
(setq default-frame-alist
(append '((width . 263) (height . 112) (top . -5) (left . 5) (font . "4.System VIO"))
default-frame-alist))

(defun set-frame-size-according-to-resolution ()
(interactive)
(if window-system
(progn
;; use 120 char wide window for largeish displays
;; and smaller 80 column windows for smaller displays
;; pick whatever numbers make sense for you
(if (> (x-display-pixel-width) 1280)
(add-to-list 'default-frame-alist (cons 'width 120))
(add-to-list 'default-frame-alist (cons 'width 80)))
;; for the height, subtract a couple hundred pixels
;; from the screen height (for panels, menubars and
;; whatnot), then divide by the height of a char to
;; get the height we want
(add-to-list 'default-frame-alist
(cons 'height (/ (- (x-display-pixel-height) 200)
(frame-char-height)))))))
(set-frame-size-according-to-resolution)
I prefer Bryan Oakley's settings. However the 'height not work properly in my GNU Emacs 24.1.1.

Related

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.
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.)
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)
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.
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.
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!
See http://www.emacswiki.org/emacs/GlobalTextScaleMode, or for a more general explanation:
http://www.emacswiki.org/emacs/SetFonts#toc6

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

How to call a function interactively

When I start up Emacs, I want it to fill the left half of my screen. I accomplish this using
;; set initial window size to the left half of the screen
(defun set-frame-pixel-size (frame width height)
"Sets size of FRAME to WIDTH by HEIGHT, measured in pixels."
(let ((pixels-per-char-width (/ (frame-pixel-width) (frame-width)))
(pixels-per-char-height (/ (frame-pixel-height) (frame-height))))
(set-frame-size frame
(floor (/ width pixels-per-char-width))
(floor (/ height pixels-per-char-height)))))
(defun use-left-half-screen ()
(interactive)
(let* ((excess-width 32)
(excess-height 48)
(half-screen-width (- (/ (x-display-pixel-width) 2) excess-width))
(screen-height (- (x-display-pixel-height) excess-height)))
(set-frame-pixel-size (selected-frame) half-screen-width screen-height)))
(if window-system
(use-left-half-screen))
And it works beautifully. However, I sometimes want to call that same command another time during the day. Hence, I do M-x use-left-half-screen but nothing happens.
That is, unless I run M-: (set-frame-pixel-size (selected-frame) 1024 768) (or something similar) first. If I do that, and I don't change the frame size using my mouse, then use-left-half-screen works. As soon as I change the frame size using the mouse or an OS shortcut, it ceases to work.
Do you have any ideas of how I can make M-x use-left-half-screen work?

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.

Command to center screen horizontally around cursor on emacs?

I'm familiar with and use very frequently the C-l (recenter-top-bottom) to
Move current line to window center,
top, and bottom, successively.
I'd like to have an equivalent command to move the current column to window center, left and right borders, successively. Either built-in or a snippet of Elisp.
Here you go:
(defun my-horizontal-recenter ()
"make the point horizontally centered in the window"
(interactive)
(let ((mid (/ (window-width) 2))
(line-len (save-excursion (end-of-line) (current-column)))
(cur (current-column)))
(if (< mid cur)
(set-window-hscroll (selected-window)
(- cur mid)))))
And the obvious binding (from obvio171) is:
(global-set-key (kbd "C-S-l") 'my-horizontal-recenter)
If you move to a chosen column and hit C-x C-n, then the commands C-n and C-p will go to that column until you hit C-u C-x C-n to turn the behavior off.
A sort of poor-man's version of what you are looking for.