emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] Changes to emacs/lisp/windmove.el [gnus-5_10-branch]


From: Miles Bader
Subject: [Emacs-diffs] Changes to emacs/lisp/windmove.el [gnus-5_10-branch]
Date: Sat, 04 Sep 2004 08:29:13 -0400

Index: emacs/lisp/windmove.el
diff -c /dev/null emacs/lisp/windmove.el:1.7.2.1
*** /dev/null   Sat Sep  4 12:02:35 2004
--- emacs/lisp/windmove.el      Sat Sep  4 12:01:08 2004
***************
*** 0 ****
--- 1,610 ----
+ ;;; windmove.el --- directional window-selection routines
+ ;;
+ ;; Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
+ ;;
+ ;; Author: Hovav Shacham (address@hidden)
+ ;; Created: 17 October 1998
+ ;; Keywords: window, movement, convenience
+ ;;
+ ;; This file is part of GNU Emacs.
+ ;;
+ ;; GNU Emacs is free software; you can redistribute it and/or modify
+ ;; it under the terms of the GNU General Public License as published by
+ ;; the Free Software Foundation; either version 2, or (at your option)
+ ;; any later version.
+ ;;
+ ;; GNU Emacs is distributed in the hope that it will be useful,
+ ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+ ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ ;; GNU General Public License for more details.
+ ;;
+ ;; You should have received a copy of the GNU General Public License
+ ;; along with GNU Emacs; see the file COPYING.  If not, write to the
+ ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ ;; Boston, MA 02111-1307, USA.
+ ;;
+ ;; --------------------------------------------------------------------
+ 
+ ;;; Commentary:
+ ;;
+ ;; This package defines a set of routines, windmove-{left,up,right,
+ ;; down}, for selection of windows in a frame geometrically.  For
+ ;; example, `windmove-right' selects the window immediately to the
+ ;; right of the currently-selected one.  This functionality is similar
+ ;; to the window-selection controls of the BRIEF editor of yore.
+ ;;
+ ;; One subtle point is what happens when the window to the right has
+ ;; been split vertically; for example, consider a call to
+ ;; `windmove-right' in this setup:
+ ;;
+ ;;                    -------------
+ ;;                    |      | A  |
+ ;;                    |      |    |
+ ;;                    |      |-----
+ ;;                    | *    |    |    (* is point in the currently
+ ;;                    |      | B  |     selected window)
+ ;;                    |      |    |
+ ;;                    -------------
+ ;;
+ ;; There are (at least) three reasonable things to do:
+ ;; (1) Always move to the window to the right of the top edge of the
+ ;;     selected window; in this case, this policy selects A.
+ ;; (2) Always move to the window to the right of the bottom edge of
+ ;;     the selected window; in this case, this policy selects B.
+ ;; (3) Move to the window to the right of point in the selected
+ ;;     window.  This may select either A or B, depending on the
+ ;;     position of point; in the illustrated example, it would select
+ ;;     B.
+ ;;
+ ;; Similar issues arise for all the movement functions.  Windmove
+ ;; resolves this problem by allowing the user to specify behavior
+ ;; through a prefix argument.  The cases are thus:
+ ;; * if no argument is given to the movement functions, or the
+ ;;   argument given is zero, movement is relative to point;
+ ;; * if a positive argument is given, movement is relative to the top
+ ;;   or left edge of the selected window, depending on whether the
+ ;;   movement is to be horizontal or vertical;
+ ;; * if a negative argument is given, movement is relative to the
+ ;;   bottom or right edge of the selected window, depending on whether
+ ;;   the movement is to be horizontal or vertical.
+ ;;
+ ;;
+ ;; Another feature enables wrap-around mode when the variable
+ ;; `windmove-wrap-around' is set to a non-nil value.  In this mode,
+ ;; movement that falls off the edge of the frame will wrap around to
+ ;; find the window on the opposite side of the frame.  Windmove does
+ ;; the Right Thing about the minibuffer; for example, consider:
+ ;;
+ ;;                    -------------
+ ;;                    |    *      |
+ ;;                    |-----------|
+ ;;                    |     A     |
+ ;;                    |-----------|    (* is point in the currently
+ ;;                    |  B   | C  |     selected window)
+ ;;                    |      |    |
+ ;;                    -------------
+ ;;
+ ;; With wraparound enabled, windmove-down will move to A, while
+ ;; windmove-up will move to the minibuffer if it is active, or to
+ ;; either B or C depending on the prefix argument.
+ ;;
+ ;;
+ ;; A set of default keybindings is supplied: shift-{left,up,right,down}
+ ;; invoke the corresponding Windmove function.  See the installation
+ ;; section if you wish to use these keybindings.
+ 
+ 
+ ;; Installation:
+ ;;
+ ;; Put the following line in your `.emacs' file:
+ ;;
+ ;;     (windmove-default-keybindings)         ; shifted arrow keys
+ ;;
+ ;; or
+ ;;
+ ;;     (windmove-default-keybindings 'hyper)  ; etc.
+ ;;
+ ;; to use another modifier key.
+ ;;
+ ;;
+ ;; If you wish to enable wrap-around, also add a line like:
+ ;;
+ ;;    (setq windmove-wrap-around t)
+ ;;
+ ;;
+ ;; Note: If you have an Emacs that manifests a bug that sometimes
+ ;; causes the occasional creation of a "lost column" between windows,
+ ;; so that two adjacent windows do not actually touch, you may want to
+ ;; increase the value of `windmove-window-distance-delta' to 2 or 3:
+ ;;
+ ;;     (setq windmove-window-distance-delta 2)
+ ;;
+ 
+ ;; Acknowledgements:
+ ;;
+ ;; Special thanks to Julian Assange (address@hidden), whose
+ ;; change-windows-intuitively.el predates Windmove, and provided the
+ ;; inspiration for it.  Kin Cho (address@hidden) was the first
+ ;; to suggest wrap-around behavior.  Thanks also to Gerd Moellmann
+ ;; (address@hidden) for his comments and suggestions.
+ 
+ ;;; Code:
+ 
+ 
+ ;; User configurable variables:
+ 
+ ;; For customize ...
+ (defgroup windmove nil
+   "Directional selection of windows in a frame."
+   :prefix "windmove-"
+   :version "21.1"
+   :group 'windows
+   :group 'convenience)
+ 
+ 
+ (defcustom windmove-wrap-around nil
+   "Whether movement off the edge of the frame wraps around.
+ If this variable is set to t, moving left from the leftmost window in
+ a frame will find the rightmost one, and similarly for the other
+ directions.  The minibuffer is skipped over in up/down movements if it
+ is inactive."
+   :type 'boolean
+   :group 'windmove)
+ 
+ ;; If your Emacs sometimes places an empty column between two adjacent
+ ;; windows, you may wish to set this delta to 2.
+ (defcustom windmove-window-distance-delta 1
+   "How far away from the current window to look for an adjacent window.
+ Measured in characters either horizontally or vertically; setting this
+ to a value larger than 1 may be useful in getting around window-
+ placement bugs in old versions of Emacs."
+   :type 'number
+   :group 'windmove)
+ 
+ 
+ 
+ ;; Implementation overview:
+ ;;
+ ;; The conceptual framework behind this code is all fairly simple.  We
+ ;; are on one window; we wish to move to another.  The correct window
+ ;; to move to is determined by the position of point in the current
+ ;; window as well as the overall window setup.
+ ;;
+ ;; Early on, I made the decision to base my implementation around the
+ ;; built-in function `window-at'.  This function takes a frame-based
+ ;; coordinate, and returns the window that contains it.  Using this
+ ;; function, the job of the various top-level windmove functions can
+ ;; be decomposed: first, find the current frame-based location of
+ ;; point; second, manipulate it in some way to give a new location,
+ ;; that hopefully falls in the window immediately at left (or right,
+ ;; etc.); third, use `window-at' and `select-window' to select the
+ ;; window at that new location.
+ ;;
+ ;; This is probably not the only possible architecture, and it turns
+ ;; out to have some inherent cruftiness.  (Well, okay, the third step
+ ;; is pretty clean....)  We will consider each step in turn.
+ ;;
+ ;; A quick digression about coordinate frames: most of the functions
+ ;; in the windmove package deal with screen coordinates in one way or
+ ;; another.  These coordinates are always relative to some reference
+ ;; points.  Window-based coordinates have their reference point in the
+ ;; upper-left-hand corner of whatever window is being talked about;
+ ;; frame-based coordinates have their reference point in the
+ ;; upper-left-hand corner of the entire frame (of which the current
+ ;; window is a component).
+ ;;
+ ;; All coordinates are zero-based, which simply means that the
+ ;; reference point (whatever it is) is assigned the value (x=0, y=0).
+ ;; X-coordinates grow down the screen, and Y-coordinates grow towards
+ ;; the right of the screen.
+ ;;
+ ;; Okay, back to work.  The first step is to gather information about
+ ;; the frame-based coordinates of point, or rather, the reference
+ ;; location.  The reference location can be point, or the upper-left,
+ ;; or the lower-right corner of the window; the particular one used is
+ ;; controlled by the prefix argument to `windmove-left' and all the
+ ;; rest.
+ ;;
+ ;; This work is done by `windmove-reference-loc'.  It can figure out
+ ;; the locations of the corners by calling `window-edges', but to
+ ;; calculate the frame-based location of point, it calls the workhorse
+ ;; function `windmove-coordinates-of-position', which itself calls the
+ ;; incredibly hairy builtin `compute-motion'.  There is a good deal of
+ ;; black magic in getting all the arguments to this function just right.
+ ;;
+ ;; The second step is more messy.  Conceptually, it is fairly simple:
+ ;; if we know the reference location, and the coordinates of the
+ ;; current window, we can "throw" our reference point just over the
+ ;; appropriate edge of the window, and see what other window is
+ ;; there.  More explicitly, consider this example from the user
+ ;; documentation above.
+ ;;
+ ;;                    -------------
+ ;;                    |      | A  |
+ ;;                    |      |    |
+ ;;                    |      |-----
+ ;;                    | *    |    |    (* is point in the currently
+ ;;                    |      | B  |     selected window)
+ ;;                    |      |    |
+ ;;                    -------------
+ ;;
+ ;; The asterisk marks the reference point; we wish to move right.
+ ;; Since we are moving horizontally, the Y coordinate of the new
+ ;; location will be the same.  The X coordinate can be such that it is
+ ;; just past the edge of the present window.  Obviously, the new point
+ ;; will be inside window B.  This in itself is fairly simple: using
+ ;; the result of `windmove-reference-loc' and `window-edges', all the
+ ;; necessary math can be performed.  (Having said that, there is a
+ ;; good deal of room for off-by-one errors, and Emacs 19.34, at least,
+ ;; sometimes manifests a bug where two windows don't actually touch,
+ ;; so a larger skip is required.)  The actual math here is done by
+ ;; `windmove-other-window-loc'.
+ ;;
+ ;; But we can't just pass the result of `windmove-other-window-loc' to
+ ;; `window-at' directly.  Why not?  Suppose a move would take us off
+ ;; the edge of the screen, say to the left.  We want to give a
+ ;; descriptive error message to the user.  Or, suppose that a move
+ ;; would place us in the minibuffer.  What if the minibuffer is
+ ;; inactive?
+ ;;
+ ;; Actually, the whole subject of the minibuffer edge of the frame is
+ ;; rather messy.  It turns out that with a sufficiently large delta,
+ ;; we can fly off the bottom edge of the frame and miss the minibuffer
+ ;; altogther.  This, I think, is never right: if there's a minibuffer
+ ;; and you're not in it, and you move down, the minibuffer should be
+ ;; in your way.
+ ;;
+ ;; (By the way, I'm not totally sure that the code does the right
+ ;; thing in really weird cases, like a frame with no minibuffer.)
+ ;;
+ ;; So, what we need is some ways to do constraining and such.  The
+ ;; early versions of windmove took a fairly simplistic approach to all
+ ;; this.  When I added the wrap-around option, those internals had to
+ ;; be rewritten.  After a *lot* of futzing around, I came up with a
+ ;; two-step process that I think is general enough to cover the
+ ;; relevant cases.  (I'm not totally happy with having to pass the
+ ;; window variable as deep as I do, but we can't have everything.)
+ ;;
+ ;; In the first phase, we make sure that the new location is sane.
+ ;; "Sane" means that we can only fall of the edge of the frame in the
+ ;; direction we're moving in, and that we don't miss the minibuffer if
+ ;; we're moving down and not already in the minibuffer.  The function
+ ;; `windmove-constrain-loc-for-movement' takes care of all this.
+ ;;
+ ;; Then, we handle the wraparound, if it's enabled.  The function
+ ;; `windmove-wrap-loc-for-movement' takes coordinate values (both X
+ ;; and Y) that fall off the edge of the frame, and replaces them with
+ ;; values on the other side of the frame.  It also has special
+ ;; minibuffer-handling code again, because we want to wrap through the
+ ;; minibuffer if it's not enabled.
+ ;;
+ ;; So, that's it.  Seems to work.  All of this work is done by the fun
+ ;; function `windmove-find-other-window'.
+ ;;
+ ;; So, now we have a window to move to (or nil if something's gone
+ ;; wrong).  The function `windmove-do-window-select' is the main
+ ;; driver function: it actually does the `select-window'.  It is
+ ;; called by four little convenience wrappers, `windmove-left',
+ ;; `windmove-up', `windmove-right', and `windmove-down', which make
+ ;; for convenient keybinding.
+ 
+ 
+ ;; Quick & dirty utility function to add two (x . y) coords.
+ (defun windmove-coord-add (coord1 coord2)
+   "Add the two coordinates.
+ Both COORD1 and COORD2 are coordinate cons pairs, (HPOS . VPOS).  The
+ result is another coordinate cons pair."
+   (cons (+ (car coord1) (car coord2))
+         (+ (cdr coord1) (cdr coord2))))
+ 
+ 
+ (defun windmove-constrain-to-range (n min-n max-n)
+   "Ensure that N is between MIN-N and MAX-N inclusive by constraining.
+ If N is less than MIN-N, return MIN-N; if greater than MAX-N, return
+ MAX-N."
+   (max min-n (min n max-n)))
+ 
+ (defun windmove-constrain-around-range (n min-n max-n)
+   "Ensure that N is between MIN-N and MAX-N inclusive by wrapping.
+ If N is less than MIN-N, return MAX-N; if greater than MAX-N, return
+ MIN-N."
+   (cond
+    ((< n min-n) max-n)
+    ((> n max-n) min-n)
+    (t n)))
+ 
+ (defun windmove-frame-edges (window)
+   "Return (X-MIN Y-MIN X-MAX Y-MAX) for the frame containing WINDOW.
+ If WINDOW is nil, return the edges for the selected frame.
+ \(X-MIN, Y-MIN) is the zero-based coordinate of the top-left corner
+ of the frame; (X-MAX, Y-MAX) is the zero-based coordinate of the
+ bottom-right corner of the frame.
+ For example, if a frame has 76 rows and 181 columns, the return value
+ from `windmove-frame-edges' will be the list (0 0 180 75)."
+   (let* ((frame (if window
+                   (window-frame window)
+                 (selected-frame)))
+        (top-left (window-inside-edges (frame-first-window frame)))
+        (x-min (nth 0 top-left))
+        (y-min (nth 1 top-left))
+        (x-max (+ x-min (frame-width frame) -1)) ; 1- for last row & col
+        (y-max (+ x-max (frame-height frame) -1)))
+     (list x-min y-min x-max y-max)))
+ 
+ ;; it turns out that constraining is always a good thing, even when
+ ;; wrapping is going to happen.  this is because:
+ ;; first, since we disallow exotic diagonal-around-a-corner type
+ ;; movements, so we can always fix the unimportant direction (the one
+ ;; we're not moving in).
+ ;; second, if we're moving down and we're not in the minibuffer, then
+ ;; constraining the y coordinate to max-y is okay, because if that
+ ;; falls in the minibuffer and the minibuffer isn't active, that y
+ ;; coordinate will still be off the bottom of the frame as the
+ ;; wrapping function sees it and so will get wrapped around anyway.
+ (defun windmove-constrain-loc-for-movement (coord window dir)
+   "Constrain COORD so that it is reasonable for the given movement.
+ This involves two things: first, make sure that the \"off\" coordinate
+ -- the one not being moved on, e.g., y for horizontal movement -- is
+ within frame boundaries; second, if the movement is down and we're not
+ moving from the minibuffer, make sure that the y coordinate does not
+ exceed the frame max-y, so that we don't overshoot the minibuffer
+ accidentally.  WINDOW is the window that movement is relative to; DIR
+ is the direction of the movement, one of `left', `up', `right',
+ or `down'.
+ Returns the constrained coordinate."
+   (let ((frame-edges (windmove-frame-edges window))
+         (in-minibuffer (window-minibuffer-p window)))
+     (let ((min-x (nth 0 frame-edges))
+           (min-y (nth 1 frame-edges))
+           (max-x (nth 2 frame-edges))
+           (max-y (nth 3 frame-edges)))
+       (let ((new-x
+              (if (memq dir '(up down))    ; vertical movement
+                  (windmove-constrain-to-range (car coord) min-x max-x)
+                (car coord)))
+             (new-y
+              (if (or (memq dir '(left right)) ; horizontal movement
+                      (and (eq dir 'down)
+                           (not in-minibuffer))) ; don't miss minibuffer
+                  ;; (technically, we shouldn't constrain on min-y in the
+                  ;; second case, but this shouldn't do any harm on a
+                  ;; down movement.)
+                  (windmove-constrain-to-range (cdr coord) min-y max-y)
+                (cdr coord))))
+         (cons new-x new-y)))))
+ 
+ ;; having constrained in the limited sense of windmove-constrain-loc-
+ ;; for-movement, the wrapping code is actually much simpler than it
+ ;; otherwise would be.  the only complication is that we need to check
+ ;; if the minibuffer is active, and, if not, pretend that it's not
+ ;; even part of the frame.
+ (defun windmove-wrap-loc-for-movement (coord window dir)
+   "Takes the constrained COORD and wraps it around for the movement.
+ This makes an out-of-range x or y coordinate and wraps it around the
+ frame, giving a coordinate (hopefully) in the window on the other edge
+ of the frame.  WINDOW is the window that movement is relative to (nil
+ means the currently selected window); DIR is the direction of the
+ movement, one of `left', `up', `right',or `down'.
+ Returns the wrapped coordinate."
+   (let* ((frame-edges (windmove-frame-edges window))
+          (frame-minibuffer (minibuffer-window (if window
+                                                   (window-frame window)
+                                                 (selected-frame))))
+          (minibuffer-active (minibuffer-window-active-p
+                                frame-minibuffer)))
+     (let ((min-x (nth 0 frame-edges))
+           (min-y (nth 1 frame-edges))
+           (max-x (nth 2 frame-edges))
+           (max-y (if (not minibuffer-active)
+                      (- (nth 3 frame-edges)
+                         (window-height frame-minibuffer))
+                    (nth 3 frame-edges))))
+       (cons
+        (windmove-constrain-around-range (car coord) min-x max-x)
+        (windmove-constrain-around-range (cdr coord) min-y max-y)))))
+ 
+ 
+ 
+ ;; `windmove-coordinates-of-position' is stolen and modified from the
+ ;; Emacs Lisp Reference Manual, section 27.2.5.  It seems to work
+ ;; okay, although I am bothered by the fact that tab-offset (the cdr
+ ;; of the next-to- last argument) is set to 0.  On the other hand, I
+ ;; can't find a single usage of `compute-motion' anywhere that doesn't
+ ;; set this component to zero, and I'm too lazy to grovel through the
+ ;; C source to figure out what's happening in the background.  there
+ ;; also seems to be a good deal of fun in calculating the correct
+ ;; width of lines for telling `compute-motion' about; in particular,
+ ;; it seems we need to subtract 1 (for the continuation column) from
+ ;; the number that `window-width' gives, or continuation lines aren't
+ ;; counted correctly.  I haven't seen anyone doing this before,
+ ;; though.
+ (defun windmove-coordinates-of-position (pos &optional window)
+   "Return the coordinates of position POS in window WINDOW.
+ Return the window-based coodinates in a cons pair: (HPOS . VPOS),
+ where HPOS and VPOS are the zero-based x and y components of the
+ screen location of POS.  If WINDOW is nil, return the coordinates in
+ the currently selected window.
+ As an example, if point is in the top left corner of a window, then
+ the return value from `windmove-coordinates-of-position' is (0 . 0)
+ regardless of the where point is in the buffer and where the window
+ is placed in the frame."
+   (let* ((wind (if (null window) (selected-window) window))
+          (big-hairy-result (compute-motion
+                             (window-start)
+                             '(0 . 0)
+                             pos
+                             nil ; (window-width window-height)
+                             nil ; window-width
+                             (cons (window-hscroll)
+                                   0)    ; why zero?
+                             wind)))
+     (cons (nth 1 big-hairy-result)      ; hpos, not vpos as documented
+           (nth 2 big-hairy-result))))   ; vpos, not hpos as documented
+ 
+ ;; This calculates the reference location in the current window: the
+ ;; frame-based (x . y) of either point, the top-left, or the
+ ;; bottom-right of the window, depending on ARG.
+ (defun windmove-reference-loc (&optional arg window)
+   "Return the reference location for directional window selection.
+ Return a coordinate (HPOS . VPOS) that is frame-based.  If ARG is nil
+ or not supplied, the reference point is the buffer's point in the
+ currently-selected window, or WINDOW if supplied; otherwise, it is the
+ top-left or bottom-right corner of the selected window, or WINDOW if
+ supplied, if ARG is greater or smaller than zero, respectively."
+   (let ((effective-arg (if (null arg) 0 (prefix-numeric-value arg)))
+         (edges (window-inside-edges window)))
+     (let ((top-left (cons (nth 0 edges)
+                           (nth 1 edges)))
+         ;; Subtracting 1 converts the edge to the last column or line
+         ;; within the window.
+           (bottom-right (cons (- (nth 2 edges) 1)
+                               (- (nth 3 edges) 1))))
+       (cond
+        ((> effective-arg 0)
+           top-left)
+        ((< effective-arg 0)
+           bottom-right)
+        ((= effective-arg 0)
+           (windmove-coord-add
+              top-left
+              (windmove-coordinates-of-position (window-point window)
+                                                window)))))))
+ 
+ ;; This uses the reference location in the current window (calculated
+ ;; by `windmove-reference-loc' above) to find a reference location
+ ;; that will hopefully be in the window we want to move to.
+ (defun windmove-other-window-loc (dir &optional arg window)
+   "Return a location in the window to be moved to.
+ Return value is a frame-based (HPOS . VPOS) value that should be moved
+ to.  DIR is one of `left', `up', `right', or `down'; an optional ARG
+ is handled as by `windmove-reference-loc'; WINDOW is the window that
+ movement is relative to."
+   (let ((edges (window-edges window))   ; edges: (x0, y0, x1, y1)
+         (refpoint (windmove-reference-loc arg window))) ; (x . y)
+     (cond
+      ((eq dir 'left)
+       (cons (- (nth 0 edges)
+                windmove-window-distance-delta)
+             (cdr refpoint)))            ; (x0-d, y)
+      ((eq dir 'up)
+       (cons (car refpoint)
+             (- (nth 1 edges)
+                windmove-window-distance-delta))) ; (x, y0-d)
+      ((eq dir 'right)
+       (cons (+ (nth 2 edges)
+                windmove-window-distance-delta)
+             (cdr refpoint)))            ; (x1+d, y)
+      ((eq dir 'down)
+       (cons (car refpoint)
+             (+ (nth 3 edges)
+                windmove-window-distance-delta))) ; (x, y1+d)
+      (t (error "Invalid direction of movement: %s" dir)))))
+ 
+ (defun windmove-find-other-window (dir &optional arg window)
+   "Return the window object in direction DIR.
+ DIR, ARG, and WINDOW are handled as by `windmove-other-window-loc'."
+   (let* ((actual-current-window (or window (selected-window)))
+          (raw-other-window-loc
+           (windmove-other-window-loc dir arg actual-current-window))
+          (constrained-other-window-loc
+           (windmove-constrain-loc-for-movement raw-other-window-loc
+                                                actual-current-window
+                                                dir))
+          (other-window-loc
+           (if windmove-wrap-around
+             (windmove-wrap-loc-for-movement constrained-other-window-loc
+                                             actual-current-window
+                                             dir)
+             constrained-other-window-loc)))
+     (window-at (car other-window-loc)
+                (cdr other-window-loc))))
+ 
+ 
+ ;; Selects the window that's hopefully at the location returned by
+ ;; `windmove-other-window-loc', or screams if there's no window there.
+ (defun windmove-do-window-select (dir &optional arg window)
+   "Move to the window at direction DIR.
+ DIR, ARG, and WINDOW are handled as by `windmove-other-window-loc'.
+ If no window is at direction DIR, an error is signaled."
+   (let ((other-window (windmove-find-other-window dir arg window)))
+     (cond ((null other-window)
+            (error "No window %s from selected window" dir))
+           ((and (window-minibuffer-p other-window)
+                 (not (minibuffer-window-active-p other-window)))
+            (error "Minibuffer is inactive"))
+           (t
+            (select-window other-window)))))
+ 
+ 
+ ;;; end-user functions
+ ;; these are all simple interactive wrappers to `windmove-do-
+ ;; window-select', meant to be bound to keys.
+ 
+ ;;;###autoload
+ (defun windmove-left (&optional arg)
+   "Select the window to the left of the current one.
+ With no prefix argument, or with prefix argument equal to zero,
+ \"left\" is relative to the position of point in the window; otherwise
+ it is relative to the top edge (for positive ARG) or the bottom edge
+ \(for negative ARG) of the current window.
+ If no window is at the desired location, an error is signaled."
+   (interactive "P")
+   (windmove-do-window-select 'left arg))
+ 
+ ;;;###autoload
+ (defun windmove-up (&optional arg)
+   "Select the window above the current one.
+ With no prefix argument, or with prefix argument equal to zero, \"up\"
+ is relative to the position of point in the window; otherwise it is
+ relative to the left edge (for positive ARG) or the right edge (for
+ negative ARG) of the current window.
+ If no window is at the desired location, an error is signaled."
+   (interactive "P")
+   (windmove-do-window-select 'up arg))
+ 
+ ;;;###autoload
+ (defun windmove-right (&optional arg)
+   "Select the window to the right of the current one.
+ With no prefix argument, or with prefix argument equal to zero,
+ \"right\" is relative to the position of point in the window;
+ otherwise it is relative to the top edge (for positive ARG) or the
+ bottom edge (for negative ARG) of the current window.
+ If no window is at the desired location, an error is signaled."
+   (interactive "P")
+   (windmove-do-window-select 'right arg))
+ 
+ ;;;###autoload
+ (defun windmove-down (&optional arg)
+   "Select the window below the current one.
+ With no prefix argument, or with prefix argument equal to zero,
+ \"down\" is relative to the position of point in the window; otherwise
+ it is relative to the left edge (for positive ARG) or the right edge
+ \(for negative ARG) of the current window.
+ If no window is at the desired location, an error is signaled."
+   (interactive "P")
+   (windmove-do-window-select 'down arg))
+ 
+ 
+ ;;; set up keybindings
+ ;; Idea for this function is from iswitchb.el, by Stephen Eglen
+ ;; (address@hidden).
+ ;; I don't think these bindings will work on non-X terminals; you
+ ;; probably want to use different bindings in that case.
+ 
+ ;;;###autoload
+ (defun windmove-default-keybindings (&optional modifier)
+   "Set up keybindings for `windmove'.
+ Keybindings are of the form MODIFIER-{left,right,up,down}.
+ Default MODIFIER is 'shift."
+   (interactive)
+   (unless modifier (setq modifier 'shift))
+   (global-set-key (vector (list modifier 'left))  'windmove-left)
+   (global-set-key (vector (list modifier 'right)) 'windmove-right)
+   (global-set-key (vector (list modifier 'up))    'windmove-up)
+   (global-set-key (vector (list modifier 'down))  'windmove-down))
+ 
+ 
+ (provide 'windmove)
+ 
+ ;;; arch-tag: 56267432-bf1a-4296-a9a0-85c6bd9f2375
+ ;;; windmove.el ends here




reply via email to

[Prev in Thread] Current Thread [Next in Thread]