Emacs window positioning - emacs

maybe this is stupid question.. but i'm trying to get my emacs customization fine grained.. is there a direct command to change windows like this?
+----------------+
| |
| |
+----------------+
| |
| |
+----------------+
to
+----------------+------------+
| | |
| | |
+----------------+ |
| | |
| | |
+----------------+------------+
or am i going to need to start learning elisp?

yes you will, but toying with window layout and buffers is very good place to start. here's a solution for you, it gives you most of what you need to customise your layouts.
add the code below to your .emacs. C-x C-e to evaluate it, then hopefully hitting F5 will do as you expect (provided you haven't killed the '*Messages*' buffer).
global-set-key '[f5] '(lambda () (interactive)
(let ((other (buffer-name (window-buffer (next-window)))))
(delete-other-windows)
(set-frame-width (selected-frame)
(+ (frame-width (selected-frame)) (window-width)))
(split-window-horizontally)
(split-window-vertically)
(with-selected-window (next-window)
(set-window-buffer (selected-window) other))
(with-selected-window (previous-window)
(set-window-buffer (selected-window) "*Messages*")))))

Related

Emacs windmove move a buffer without switching

I have Emacs Windmove setup well and working, but I still have a small annoyance with it. There seems to be no way to slide one buffer over another buffer without switching the placement of both buffers. How can I slide a buffer over another buffer, displacing only that buffer.
Here's what I want to do:
___________ ___________ ___________
| | B | | | B | | | C |<-----
| A |_____| ---> | A |_____| ---> | A |_____| |
| | D | | | C | | | D | |
|____|_____| |____|_____| |____|_____| |
Buffer C opens up, ------^ With a key combo, maybe__|
covering buffer D I can slide up buffer C
to get back buffer D
EDIT: I forgot to mention I have some elisp that uses windmove to actually switch two buffers. The use case for what I want to do is that sometimes a buffer will open up in a certain window, covering up another buffer that I want to see. I want to slide the newly open buffer around without disturbing the other buffers, and to get the buffer back that was covered up. I hope that makes sense.
(defun slide-buffer (dir)
"Move current buffer into window at direction DIR.
DIR is handled as by `windmove-other-window-loc'."
(require 'windmove)
(let ((buffer (current-buffer))
(target (windmove-find-other-window dir)))
(if (null target)
(user-error "There is no window %s from here" dir)
(switch-to-prev-buffer)
(select-window target)
(switch-to-buffer buffer nil t))))
(defun slide-buffer-up () (interactive) (slide-buffer 'up))
(defun slide-buffer-down () (interactive) (slide-buffer 'down))
(defun slide-buffer-left () (interactive) (slide-buffer 'left))
(defun slide-buffer-right () (interactive) (slide-buffer 'right))
Bind it to C-S-<arrow>:
(define-key global-map (kbd "C-S-<up>") #'slide-buffer-up)
(define-key global-map (kbd "C-S-<down>") #'slide-buffer-down)
(define-key global-map (kbd "C-S-<left>") #'slide-buffer-left)
(define-key global-map (kbd "C-S-<right>") #'slide-buffer-right)
In your comment you say that you would like a "key combination to do it", meaning to (1) switch to the window showing buffer B and then (2) to switch the buffer shown in that window to buffer C.
How do you do that now? You use keys, no? So you already have a "key combination to do it". If you mean that you want a shorter key combination then write a command that chains together the commands bound to the keys you use now to do that.
There are several ways to do #1, and #2 is just C-x b C.
One way to do #1 is to use C-0 C-o in Icicles. It lets you pick a window by name, using completion. The command in question is icicle-choose-window-by-name.
Putting the two together, with Icicles you could use this code. Then hit F3 to do what you want.
(defun foo ()
(interactive)
(call-interactively #'icicle-choose-window-by-name)
(call-interactively #'switch-to-buffer))
(global-set-key [f3] 'foo)
There are other ways to choose a window, if you don't want to use Icicles. This is the place to start, when looking for info about selecting (navigating among) windows.

Emacs rearrange split panes

If I'm working in (terminal) Emacs and have 2 buffers on screen using a horizontal split:
+--------------------------+
| |
| |
| |
| |
+--------------------------+
| |
| |
| |
| |
+--------------------------+
Then I decide to open the slime repl, Emacs will split one of those horizontal panes vertically:
+--------------------------+
| |
| |
| |
| |
+-------------+------------+
| | |
| | slime |
| | |
| | |
+-------------+------------+
But what I want is to have slime on the right, using the full height of the window:
+-------------+------------+
| | |
| | |
| | |
| | |
+-------------+ slime |
| | |
| | |
| | |
| | |
+-------------+------------+
Is there any easy way to get from the arrangement Emacs automatically gave me, to the one I want (e.g. a rotate arrangement), or do I explicitly close and re-split the windows myself?
EDIT | Also curious if I can directly open a full vertical split if I'm currently using a full horizontal split, or if it's effectively impossible.
If you like pre-set window configurations, take a look at the "workspace management" pakages:
Perspective gives you named workspaces
Equilibrium Emacs Window Manager is similar but more sophisticated tool which allows to configure popup placement, window configuraion, buffers, fonts and keybindings.
There is more on the project management page on EmacsWiki.
To your second question, here is what I have in my configuration to flip horizontal/vertical splits (credit: https://github.com/yyr/emacs.d):
(defun split-window-func-with-other-buffer (split-function)
(lexical-let ((s-f split-function))
(lambda ()
(interactive)
(funcall s-f)
(set-window-buffer (next-window) (other-buffer)))))
(defun split-window-horizontally-instead ()
(interactive)
(save-excursion
(delete-other-windows)
(funcall (split-window-func-with-other-buffer 'split-window-horizontally))))
(defun split-window-vertically-instead ()
(interactive)
(save-excursion
(delete-other-windows)
(funcall (split-window-func-with-other-buffer 'split-window-vertically))))
(global-set-key "\C-x|" 'split-window-horizontally-instead)
(global-set-key "\C-x_" 'split-window-vertically-instead)
There are certainly libraries for transforming a frame's window configuration (flip, rotate, etc...), and other libraries for rotating the visible buffers through the available windows. Combining those would achieve your aim.
I like TransposeFrame for the former, and I can see at least a couple of options for the latter:
https://github.com/banister/window-rotate-for-emacs
http://www.emacswiki.org/emacs/TransposeWindows
In general, CategoryWindows on the Wiki should be useful to you.
Note that the window configuration transforms do need to delete and re-create the splits, so the original window objects do not all survive the process. In that respect, it's not actually possible to do what you're asking; but for most purposes, 'faking it' is sufficient.
Here's a function that does what you want. After loading it into emacs, select the buffer you want to rearrange and do an M-x my-shift-window-right. You can also bind it to a key with global-set-key.
(defun my-shift-window-right (&optional start-window)
"Reset the current window configuration with START-WINDOW
on the right and the rest of the windows on the left. START-WINDOW defaults to
the selected window. Return START-WINDOW, or nil if START-WINDOW isn't live or
if there is only one visible window."
(interactive (list (selected-window)))
(if (or (one-window-p)
(and start-window
(not (window-live-p start-window)))) nil
(let ((other-buffers '())
(start-window (or start-window (selected-window))))
;; add all visible buffers other than the current one to other-buffers list
(walk-windows #'(lambda (window)
(when (not (eq window start-window))
(add-to-list 'other-buffers (window-buffer window)))))
(delete-other-windows)
;; pop the first "other buffer" into a split window on the left
(set-window-buffer (select-window (split-window start-window nil 'left))
(pop other-buffers))
;; make a split window for each buffer in the "other-buffers" list
;; select the start-window and return it when finished
(dolist (buffer other-buffers (select-window start-window))
(set-window-buffer (split-window (selected-window) nil 'above) buffer)))))
This function cycles through the other visible windows and stores each of their buffers in a list called other-buffers. Then it rearranges the windows the way you described by iterating over the other-buffers list.

How do I make this Emacs frame keep its buffer and not get resized?

My Emacs frame looks like this:
+---------------------------+
| | |
| | |
| | B |
| A | |
| | |
| | |
| |-------------|
| | C |
+---------------------------+
C is usually a terminal with some kind of long-running process, like a web server or daemon. Unfortunately, all sorts of things like to switch the buffer in that window and occasionally it gets resized. How can I lock the buffer and height of window C?
If you don't want to be annoyed by window stealing and resizing, put the following lines in your .emacs for a definitive solution that works even with libraries like gud that tries to open a new frame when they can't steal your windows :
(see this answer for info on the following advice)
(defadvice pop-to-buffer (before cancel-other-window first)
(ad-set-arg 1 nil))
(ad-activate 'pop-to-buffer)
;; Toggle window dedication
(defun toggle-window-dedicated ()
"Toggle whether the current active window is dedicated or not"
(interactive)
(message
(if (let (window (get-buffer-window (current-buffer)))
(set-window-dedicated-p window
(not (window-dedicated-p window))))
"Window '%s' is dedicated"
"Window '%s' is normal")
(current-buffer)))
;; Press [pause] key in each window you want to "freeze"
(global-set-key [pause] 'toggle-window-dedicated)
and customize pop-up-windows variable to nil.
you could also use StickyWindows instead of window-dedicated feature.
One possibility is to dedicate the window to its buffer, using set-window-dedicated-p. This will not prevent the window from being resized manually, only protect it from being clobbered by display-buffer. For example,
(add-hook 'shell-mode-hook
(lambda ()
(interactive)
(set-window-dedicated-p (selected-window) 1)))
Replace shell-mode-hook as necessary.
This one also works fine (for emacs 24) https://lists.gnu.org/archive/html/help-gnu-emacs/2007-05/msg00975.html
(define-minor-mode sticky-buffer-mode
"Make the current window always display this buffer."
nil " sticky" nil
(set-window-dedicated-p (selected-window) sticky-buffer-mode))
You could use winner-mode to be able to undo the changes to be the window sizes.
You could also explicitly save and restore the window configuration in registers.

How do I make Emacs' other-window command ignore terminal windows?

Emacs does an okay job of being a window manager. I've been splitting up my Emacs frame like this:
+---------------------------+
| | |
| | |
| | B |
| A | |
| | |
| | |
| |-------------|
| | C |
+---------------------------+
C is usually a terminal with some kind of long-running process, like a web server or daemon. Occasionally I'll move the point there to restart the daemon, but most of the time I'd like to swap only between A and B. How can I make this convenient?
There's nothing built-in to do what you want. You can use the following code to do what you want (just customize the regular expression to match the name of the buffer(s) you want to avoid).
Note: the my-other-window doesn't implement all the features other-window does, that is left as an exercise for the reader.
my-other-window will try to switch to a window whose buffer doesn't match the avoid-window-regexp. If there's no such window available, then it just switches to the next one.
(require 'cl)
(defvar avoid-window-regexp "^[0-9]$")
(defun my-other-window ()
"Similar to 'other-window, only try to avoid windows whose buffers match avoid-window-regexp"
(interactive)
(let* ((window-list (delq (selected-window) (window-list)))
(filtered-window-list (remove-if
(lambda (w)
(string-match-p avoid-window-regexp (buffer-name (window-buffer w))))
window-list)))
(if filtered-window-list
(select-window (car filtered-window-list))
(and window-list
(select-window (car window-list))))))
And bind it appropriately:
(global-set-key (kbd "C-x o") 'my-other-window)
This works for eshell:
(add-hook 'eshell-mode-hook (lambda ()
(set-window-parameter (first (window-list)) 'no-other-window t)))
Setting no-other-window to non-nil makes the standard other-window function skip this. See other-window docs with C-h C-f other-window
There might be a better way to get the current window, but I don't know it yet.
Not the exact answer but I use windmove-mode for that which allow you to use the arrow to visually move between windows and then doing Control-Left or Control-Right to move only between A and B.
Other than that you probably can redefine other-buffer function with something that take buffer-list ignoring some patters when switch-to-buffer to it but I didn't write the code handy.
For the lazy, I use something like this in my .emacs
(fset 'doublejump
"\C-u2\C-xo")
(global-set-key (kbd "C-c o") 'doublejump)
and alternate between using single and double buffer switches.

View the contents of a gzip archive in hexl mode

I want to write a function, similar hexl-find-file, that will open a gzipped file and show the contents in the hexl-mode. How would I do that?
Does this work for you?
(require 'jka-compr)
(defun hexl-find-file ()
"call find file and then jump into hexl mode"
(interactive)
(call-interactively 'find-file)
(hexl-mode 1))
The 'jka-compr provides the seamless compressed file handling, and the 'hexl-find-file just opens the file and turns on hexl-mode.
Turn on auto-compression-mode before you run hexl-find-file?
,----[ C-h f auto-compression-mode RET ]
| `auto-compression-mode' is an interactive compiled Lisp function
| -- loaded from "/usr/share/xemacs21/xemacs-packages/lisp/os-utils/auto-autoloads"
| (auto-compression-mode &optional ARG)
|
| Documentation:
| Toggle automatic file compression and uncompression.
| With prefix argument ARG, turn auto compression on if positive, else off.
| Returns the new status of auto compression (non-nil means on).
|
| Invoked with:
|
| M-x auto-compression-mode
`----