I came across this gist
(defun swap-windows ()
"If you have 2 windows, it swaps them."
(interactive)
(cond ((not (= (count-windows) 2))
(message "You need exactly 2 windows to do this."))
(t
(let* ((w1 (first (window-list)))
(w2 (second (window-list)))
(b1 (window-buffer w1))
(b2 (window-buffer w2))
(s1 (window-start w1))
(s2 (window-start w2)))
(set-window-buffer w1 b2)
(set-window-buffer w2 b1)
(set-window-start w1 s2)
(set-window-start w2 s1)))))
today, which swaps the contents of the buffers in two windows, as long as there are exactly two windows. The problem for me is that I usually have ecb running, which creates 1 or more extra windows. I've never really done anything with elisp except tweak methods I get from other places, and this (hopefully) simple change is a bit above my current comprehension.
I spent some time looking through both the ecb information, and the emacs manual, but can't find a reasonable way to determine if there are exactly two non-ecb windows open.
I also tried using things like 'bury-buffer' on the ecb windows, so I could just assume the they wouldn't be at the front of the list, but that was a flawed approach to begin with.
So my question, is there a way to modify the gist to make it work with ecb? I'm assuming there is something special about ecb windows, but I couldn't find anything I could access.
I also tried using things like 'bury-buffer' on the ecb windows, so I could just assume the they wouldn't be at the front of the list, but that was a flawed approach to begin with.
Bit of a hack, but you can hide the ECB windows, call swap-windows, and show them again, like so:
(defun my-swap-windows ()
(interactive)
(ecb-hide-ecb-windows)
(swap-windows)
(ecb-show-ecb-windows))
By the way, I had to add this line to get the gist to work:
(require 'cl)
Edit: I wasn't seeing the window resizing problem you described, but this code should swap non-ECB windows while ignoring ECB windows.
(require 'cl)
(defun non-ecb-window-list ()
(remove-if
#'(lambda (window)
(find (window-buffer window) (ecb-dedicated-special-buffers)))
(window-list)))
(defun count-non-ecb-windows ()
(length (non-ecb-window-list)))
(defun swap-windows ()
"If you have 2 windows, it swaps them."
(interactive)
(cond ((not (= (count-non-ecb-windows) 2))
(message "You need exactly 2 windows to do this."))
(t
(let* ((w1 (first (non-ecb-window-list)))
(w2 (second (non-ecb-window-list)))
(b1 (window-buffer w1))
(b2 (window-buffer w2))
(s1 (window-start w1))
(s2 (window-start w2)))
(set-window-buffer w1 b2)
(set-window-buffer w2 b1)
(set-window-start w1 s2)
(set-window-start w2 s1)))))
I'll go ahead and post this answer, as I wrote/discovered it with some more trial and error. It isn't what I asked for, which the accepted answer is, but it has its own merits for others reading this thread.
(defun swap-windows ()
"Swap two windows."
(interactive)
(let* ((w1 (selected-window))
(w2 (next-window))
(b1 (window-buffer w1))
(b2 (window-buffer w2))
(s1 (window-start w1))
(s2 (window-start w2)))
(set-window-buffer w1 b2)
(set-window-buffer w2 b1)
(set-window-start w1 s2)
(set-window-start w2 s1)))
Since I basically always know what C-x o will go to, which is what 'next-window' is supposed to return, this function is almost always what I want. However, it leaves off any kind of error checking, and doesn't really answer the question as written, just my poorly expressed intent.
Related
I often find myself switching from a horizontal view of two windows in emacs to a vertical view. This requires me to first do C-x 1 and then C-x 3 and then C-x o followed by C-x b <RET> to switch to the other buffer or something like that. I would like to only have to type C-x | (analogous to how, in Ediff, you hit | to toggle the split view).
I found this in the emacs wiki site:
http://www.emacswiki.org/emacs/ToggleWindowSplit
But how do I map that to the key combo I want? Or whether there is a simpler way to do it (taking less .emacs space).
Making it easier for other people that also happened to be looking for the script (in this link), already modified with the other answer's keybinding:
(defun toggle-window-split ()
(interactive)
(if (= (count-windows) 2)
(let* ((this-win-buffer (window-buffer))
(next-win-buffer (window-buffer (next-window)))
(this-win-edges (window-edges (selected-window)))
(next-win-edges (window-edges (next-window)))
(this-win-2nd (not (and (<= (car this-win-edges)
(car next-win-edges))
(<= (cadr this-win-edges)
(cadr next-win-edges)))))
(splitter
(if (= (car this-win-edges)
(car (window-edges (next-window))))
'split-window-horizontally
'split-window-vertically)))
(delete-other-windows)
(let ((first-win (selected-window)))
(funcall splitter)
(if this-win-2nd (other-window 1))
(set-window-buffer (selected-window) this-win-buffer)
(set-window-buffer (next-window) next-win-buffer)
(select-window first-win)
(if this-win-2nd (other-window 1))))))
(global-set-key (kbd "C-x |") 'toggle-window-split)
The last line is where the key combo is defined. It should be (global-set-key (kbd "C-x |") 'toggle-window-split)
I have two buffer windows open in emacs, arranged vertically. Is there a command that rearranges them horizontally?
The Transpose Frame library provides an excellent set of functionality for manipulating the windows in a frame (any of transpose-frame, rotate-frame-clockwise, or rotate-frame-anti-clockwise would suffice for your particular example).
There are other alternatives, but I find this library fairly comprehensive. See the Wiki page (or the Commentary in the code) for ascii drawings of what each function does.
I use following snippet taken from Emacs wiki:
(defun toggle-window-split ()
(interactive)
(if (= (count-windows) 2)
(let* ((this-win-buffer (window-buffer))
(next-win-buffer (window-buffer (next-window)))
(this-win-edges (window-edges (selected-window)))
(next-win-edges (window-edges (next-window)))
(this-win-2nd (not (and (<= (car this-win-edges)
(car next-win-edges))
(<= (cadr this-win-edges)
(cadr next-win-edges)))))
(splitter
(if (= (car this-win-edges)
(car (window-edges (next-window))))
'split-window-horizontally
'split-window-vertically)))
(delete-other-windows)
(let ((first-win (selected-window)))
(funcall splitter)
(if this-win-2nd (other-window 1))
(set-window-buffer (selected-window) this-win-buffer)
(set-window-buffer (next-window) next-win-buffer)
(select-window first-win)
(if this-win-2nd (other-window 1))))))
(define-key ctl-x-4-map "t" 'toggle-window-split)
Just put this into init.el and use Ctrl-x 4 t.
You asked about tiling windows in a frame. Others will answer you directly about that (C-x 3 is a start). But you might also want to know that you can use separate frames and tile the frames across or down your display.
There's a couple of emacs features, such as flyspell-mode,
highlight-beyond-fill-column, or auto-fill-mode, I find so useful that I
want them enabled almost all the time. However, there's always certain
conditions in which they don't make much sense.
highlight-beyond-fill-column, for example, I tend to want for pretty much
everything I edit myself, but for reading things others wrote, like in Gnus or
when reading the built-in documentation, it's actually quite annoying.
Similarly auto-fill-mode is incredibly handy when writing just Text. However,
it's entirely unhelpful when programming.
For those reasons I can't just enable features like that globally. Always
enabling them manually isn't very practical as well, but so is having to write
hooks for each and every mode or application I'm using within emacs, obviously
not being able to cover all of them, and still ending up enabling those features
manually.
What I believe I'm looking for is a way to globally enable some features, but
selectively turn them off again, based on various conditions such as which major
or minor modes are being used, if the buffer is read-only or writable, or
depending on the buffer containing text or source code. I do realize that at
least the last thing might not be easy for emacs to answer, but at least for
that I believe I'd be fine with a hard-coded list of "programming-modes" i use
regularly.
So you want total control over what's executed when a particular mode is opened or a particular type of file... OK here is what you need :
;; The function where you could put all your customization
(defun my-func ()
(turn-on-auto-fill))
;; This is an example, customize it like you need it.
(defvar functions-to-call
`(((c-mode c++-mode) ".h$" (my-func))
((cperl-mode perl-mode) nil (my-func)))
"A list of triples, used for storing functions.
A triplet is composed of a symbol for the major mode (or a list of symbols),
a regular expression to match against the buffer's file name,
and the functions to call when both the major mode and regular expr match.")
(defun call-mode-functions ()
"call functions, based on major mode and buffer name regexp matching"
(interactive)
(let ((l functions-to-call))
(while l
(let* ((elt (car l))
(modes (if (listp (car elt)) (car elt) (list (car elt))))
(re (cadr elt))
(fcts (caddr elt)))
(when (and (member major-mode modes)
(or (null re)
(string-match re (buffer-file-name))))
(while fcts
(funcall (car fcts))
(setq fcts (cdr fcts)))
(setq l nil)))
(setq l (cdr l)))))
(add-hook 'after-change-major-mode-hook 'call-mode-functions)
With this code, you can can do the fine-grained customization you require. This is just an example, you can adapt it to your needs.
Interesting idea. I recommend using the
espect extension from your github.
It sounds like you basically want to turn specific minor-modes on or off for "specific buffers". Usually, the "specific buffers" can be distinguished by their major mode, which is how I usually look at this type of problem. How to turn minor modes on or off depends on the implementation of both the minor mode you're trying to turn on/off and the major mode you're trying to turn it on/off in.
The usual way to enable/disable things based on major-mode is via the major-mode-hook variable. This is where you stick things to customize the mode:
(add-hook 'text-mode-hook 'auto-fill-mode)
I usually write my own function, even if it's a simple one-liner, because I almost always will add stuff later on:
(defun my-text-mode-hook ()
"Stuff to do when `text-mode' is invoked."
(auto-fill-mode 1))
(add-hook 'text-mode-hook 'my-text-mode-hook)
You can also make things within the hook conditional:
(defun my-text-mode-hook ()
"Stuff to do when `text-mode' is invoked."
;; skip modes based on text-mode
(when (eq major-mode 'text-mode)
(auto-fill-mode 1))
)
(add-hook 'text-mode-hook 'my-text-mode-hook)
I usually do all of this in a major-mode-load-hook, so that it only happens when the major-mode's code is loaded:
(defun my-tnt-load-hook ()
(defun my-tnt-im-mode-hook ()
"Hook for TNT's im-mode hook."
(flyspell-mode 1)
(setq fill-column (- (frame-width) 5)))
(add-hook 'tnt-im-mode-hook 'my-tnt-im-mode-hook)
(add-hook 'tnt-chat-mode-hook 'my-tnt-im-mode-hook))
(add-hook 'tnt-load-hook 'my-tnt-load-hook)
A well-written major-mode will have a load-hook variable defined (I usually look at the mode's source code to find out). If it doesn't have a load-hook, you can simulate one with the eval-after-load function:
(defun my-view-mode-after-load-hook ()
"Stuff to do after view mode loads."
(defun my-view-mode-hook ()
"Stuff to run in `view-mode'."
(flyspell-mode 0))
(add-hook 'view-mode-hook 'my-view-mode-hook)
(define-key view-mode-map "b" 'View-scroll-page-backward)
(define-key view-mode-map [(delete)] 'View-scroll-page-backward)
(define-key view-mode-map "q" 'View-kill-and-leave)
(define-key view-mode-map "Q" 'View-quit))
(eval-after-load 'view '(my-view-mode-after-load-hook))
If you don't do this in a load-hook then you have to make sure the mode-hook is customizable, and then add in your my-mode-hook via customize; I'd rather have all of the stuff in one place in my .emacs, so I don't usually customize my hooks this way.
If you ever find a major-mode that does not have a major-mode-hook you can create your own major-mode based off of it using define-derived-mode. You'll then have to get the newly defined mode invoked whenever the old mode was.
(defun replace-alist-mode (alist oldmode newmode)
(dolist (aitem alist)
(if (eq (cdr aitem) oldmode)
(setcdr aitem newmode))))
(define-derived-mode hooked-foobar-mode foobar-mode "Foobar")
(replace-alist-mode auto-mode-alist 'foobar-mode 'hooked-foobar-mode)
(defun my-hooked-foobar-mode-hook ()
"Hook to run when `hooked-foobar-mode' is called."
(flyspell-mode 0))
(add-hook 'hooked-foobar-mode-hook 'my-hooked-foobar-mode-hook)
Some minor modes can be enabled globally. If you want them on most of the time and it supports it, you can turn it on globally and then turn it off for specific major modes.
(global-font-lock-mode 1)
;; example of how to do it without a defun
(add-hook 'text-mode-hook (function
(lambda () ""
(interactive)
(font-lock-mode 0))))
If the minor mode can't be enabled globally, or you don't want it enabled globally, just turn it on for specific modes, as shown above.
So here's what I came up with after reading [Jérôme Radix][1]'s excellent
reply. Especially the pointer to after-change-major-mode-hook has helped a
lot.
I now define my buffer-specific settings in a list like this:
;; no `highlight-beyond-fill-column' for w3m and gnus
'((((:not ((:mode "^gnus") (:mode w3m-mode))))
(lambda () (highlight-beyond-fill-column)))
;; `flyspell-mode` and `auto-fill-mode` for text-ish buffers
(((:mode message-mode)
(:mode org-mode)
(:mode pod-mode)
(:mode markdown-mode)
(:name "\\.\\(txt\\|mkn\\)$"))
(lambda ()
(flyspell-mode)
(auto-fill-mode)))
;; indenting with tabs for certain projects
(((:name t :fun (lambda () (and (not eproject-root)
(eproject-maybe-turn-on)))))
(lambda () (setq indent-tabs-mode t)))
When the major mode changes, I then iterate over all those settings, evaluate
the defined conditions in the buffer, and call the appropriate lambda if a
condition matches:
(add-hook 'after-change-major-mode-hook
(lambda () (rafl:apply-buffer-settings rafl:buffer-settings)))
(defun rafl:apply-buffer-settings (settings)
(dolist (setting rafl:buffer-settings)
(let ((condition (car setting))
(action (cadr setting)))
(when (rafl:evaluate-buffer-condition condition)
(funcall action)))))
Evaluating those conditions is a little messy, but works rather well for me.
(defun rafl:evaluate-buffer-condition (con)
(cond
((functionp con)
(funcall con))
((listp con)
(cond
((listp (car con))
(reduce
(lambda (a b) (or a b))
(cons nil (mapcar #'rafl:evaluate-buffer-condition con))))
(t
(reduce
(lambda (a b) (and a b))
(cons
t
(let (ret)
(while con
(let ((k (pop con))
(v (pop con)))
(push (cond
((eq k :fun)
(funcall v))
((eq k :not)
(when (not (listp v))
(error ":not requires a list"))
(not (rafl:evaluate-buffer-condition v)))
((eq k :mode)
(if (stringp v)
(string-match-p v (symbol-name major-mode))
(eq v major-mode)))
((eq k :name)
(cond
((and (buffer-file-name) (stringp v))
(string-match-p v (buffer-file-name)))
((buffer-file-name)
v)
(t
(not v))))
(t
(error "unknown cond")))
ret)))
ret))))))
(t
(error "invalid condition"))))
It also turns out that I could do all my per-project setting, which I did quite
differently before, using this mechanism. I'm very happy about that.
1: Enabling certain emacs modes or features *almost* always
I do this
(require 'linum)
;(global-linum-mode t)
(add-hook 'find-file-hook (lambda ()
(if (not(equal major-mode 'term-mode))
(linum-mode nil))))
I've got 2 windows open in Emacs and I'd like to swap their positions.
Ie Consider having a REPL above the source file and I'd like to swap their locations so that the REPL is below the source file.
I'd also like to preserve the sizes of the windows
I shamelessly stole this from Steve Yegge's .emacs
(defun swap-windows ()
"If you have 2 windows, it swaps them."
(interactive)
(cond ((not (= (count-windows) 2)) (message "You need exactly 2 windows to do this."))
(t
(let* ((w1 (first (window-list)))
(w2 (second (window-list)))
(b1 (window-buffer w1))
(b2 (window-buffer w2))
(s1 (window-start w1))
(s2 (window-start w2)))
(set-window-buffer w1 b2)
(set-window-buffer w2 b1)
(set-window-start w1 s2)
(set-window-start w2 s1)))))
Tested on Emacs 23.1.1 on Gentoo. This does preserve window sizes.
I also found this which is a little cleaner.
(defun transpose-windows ()
(interactive)
(let ((this-buffer (window-buffer (selected-window)))
(other-buffer (prog2
(other-window +1)
(window-buffer (selected-window))
(other-window -1))))
(switch-to-buffer other-buffer)
(switch-to-buffer-other-window this-buffer)
(other-window -1)))
Also tested on Emacs 23.1.1
The following version works with any number of windows. When there are more than two windows, repeated invocations will make the selected buffer appear in each windows successively.
(defun swap-buffer ()
(interactive)
(cond ((one-window-p) (display-buffer (other-buffer)))
((let* ((buffer-a (current-buffer))
(window-b (cadr (window-list)))
(buffer-b (window-buffer window-b)))
(set-window-buffer window-b buffer-a)
(switch-to-buffer buffer-b)
(other-window 1)))))
I find the TransposeFrame library useful. I mostly use it for swapping two windows, as per this question; but it provides more general functionality than just that.
Follow the link to see ascii diagrams of the various transformations.
See http://www.emacswiki.org/cgi-bin/wiki/buffer-move.el. You can install it through elpa
My windows configuration looks like this:
+----------+-----------+
| | |
| | |
| | |
| | |
| | |
| +-----------+
| | |
+----------+-----------+
And I use the lower right window for special displays (like help, completion etc.), but emacs insists on using that window when I call commands (find-file-other-window, etc.) that use display-buffer, and resize that window as well. It's annoying... Is there a way that I can force emacs NOT to use that windows? I was thinking of advising display-buffer, but it's a function in c. Any thoughts on this?
EDIT:
Based heavily on Trey's answer, this is what works for me so far:
(setq special-display-function 'my-display-buffer)
(setq special-display-regexps '(".*"))
(defun display-special-buffer (buf)
"put the special buffers in the right spot (bottom rigt)"
(let ((target-window (window-at (- (frame-width) 4) (- (frame-height) 4)))
(pop-up-windows t))
(set-window-buffer target-window buf)
target-window))
(defun my-display-buffer (buf)
"put all buffers in a window other than the one in the bottom right"
(message (buffer-name buf))
(if (member (buffer-name buf) special-display-buffer-names)
(display-special-buffer buf)
(progn
(let ((pop-up-windows t)
(windows (delete (window-at (- (frame-width) 4) (- (frame-height) 4))
(delete (minibuffer-window) (window-list)))))
(message (buffer-name (window-buffer (car windows))))
(set-window-buffer (car (cdr windows)) buf)
(car (cdr windows))))))
Well, someone already asked the same question for completion. And I wrote up an answer that seemed to work pretty well.
It looks like you could use that same solution, except instead of adding to special-display-buffer-names, you can use the variable special-display-regexps. So something along the lines of:
(add-to-list 'special-display-regexps '(".*" my-display-buffers))
(defun my-display-buffers (buf)
"put all buffers in a window other than the one in the bottom right"
(let ((windows (delete (window-at (- (frame-width) 2) (- (frame-height) 4))
(delete (minibuffer-window) (window-list))))
(if (<= 2 (length windows))
(progn
(select-window (cadr windows))
(split-window-vertically)))
(let ((pop-up-windows t))
(set-window-buffer (car windows) buf)
(car windows)))))
Obviously you'll have to modify the regexp to not match the *Help* and other buffers that you actually want in the lower right window.
Regarding advising display-buffer, that would work. You can advise functions written in c, advice works in pretty much every case you'd want except when functions are called from c, or advising macros (which doesn't work b/c the macros are generally already expanded everywhere they're used).
Perhaps something like this could work:
(defun display-buffer-avoiding-lr-corner (buffer &optional not-this-window)
(save-selected-window
(when (buffer-file-name buffer)
(select-window (window-at (- (frame-width) 1)
(- (frame-height) 2))))
(let ((display-buffer-function nil))
(display-buffer buffer not-this-window))))
(setq display-buffer-function 'display-buffer-avoiding-lr-corner)
I was thinking of advising display-buffer, but it's a function in c.
"display-buffer is an interactive Lisp function in `window.el'."
Also, you can advise C functions anyway.
Maybe it will make sense for you to make this lower right window dedicated by set-window-dedicated-p. Then this window will be ignored in operations like find-file-other-window as you want.