From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Tassilo Horn Newsgroups: gmane.emacs.devel Subject: Re: [GNU ELPA] I'd like to add switchy.el: a last-recently-used window switcher Date: Sun, 9 Apr 2023 11:33:30 +0200 (GMT+02:00) Message-ID: References: <87cz4dpk0n.fsf@gnu.org> <87r0stqvrj.fsf@posteo.net> Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="24658"; mail-complaints-to="usenet@ciao.gmane.io" Cc: emacs-devel To: Philip Kaludercic Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Sun Apr 09 11:34:25 2023 Return-path: Envelope-to: ged-emacs-devel@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1plRRI-0006DK-V8 for ged-emacs-devel@m.gmane-mx.org; Sun, 09 Apr 2023 11:34:25 +0200 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1plRQZ-0004kW-Vs; Sun, 09 Apr 2023 05:33:40 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1plRQX-0004k1-11 for emacs-devel@gnu.org; Sun, 09 Apr 2023 05:33:37 -0400 Original-Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1plRQW-0005LU-4F; Sun, 09 Apr 2023 05:33:36 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:Subject:References:In-Reply-To:To:From: Date; bh=TG+0M+CeJhvCfK9BdGWX6H0XhSuyHHvAqchy+NunWto=; b=hcAebZg9wbYHPNySZ6s4 Hn9vpGbbFr4dqrl/WD9WBKPozR1fvzxd8By6w/WH+7aQ048VAA+wRec0Fpsz0ePIAdokMQzMJPlgH sRvy2Q7g1bvou4QLfU+7TEqONXl4GGUcpkc27kcr9Obb1aEt1S8cXvm9xfTrVl4mKoECAcxTSBUX0 UlGOGT0X6U971Jfw8EO/4opSPW3iwHf73nlqwCxnOYneU8pc32A7FcGejcEh7r8VBQADF5dxQI9om Pb0lA5ANZqj4sDbE2V9PIXj9dNLTdhKzBaGl74MLrThUBfkcYwwalQldBVvkypcVRnDKL4LrrwWUP WNkc1wRMots5zQ==; Original-Received: from auth2-smtp.messagingengine.com ([66.111.4.228]) by fencepost.gnu.org with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1plRQV-0008P7-Mq; Sun, 09 Apr 2023 05:33:35 -0400 Original-Received: from compute5.internal (compute5.nyi.internal [10.202.2.45]) by mailauth.nyi.internal (Postfix) with ESMTP id 7B9A427C0054; Sun, 9 Apr 2023 05:33:33 -0400 (EDT) Original-Received: from mailfrontend2 ([10.202.2.163]) by compute5.internal (MEProxy); Sun, 09 Apr 2023 05:33:33 -0400 X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvhedrvdektddgudejucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhepfffhvfevkfgjfhfugggtgfesthhqredttddtjeenucfhrhhomhepvfgrshhs ihhlohcujfhorhhnuceothhsughhsehgnhhurdhorhhgqeenucggtffrrghtthgvrhhnpe fhleeiteeuffefuedthfdtheeivedtjeejkeeutdehtdevveeluedugefhfefgteenucff ohhmrghinhepshhrrdhhthdpghhnuhdrohhrghenucevlhhushhtvghrufhiiigvpedtne curfgrrhgrmhepmhgrihhlfhhrohhmpehthhhorhhnodhmvghsmhhtphgruhhthhhpvghr shhonhgrlhhithihqdekieejfeekjeekgedqieefhedvleekqdhtshguhheppehgnhhurd horhhgsehfrghsthhmrghilhdrfhhm X-ME-Proxy: Feedback-ID: ib2b94485:Fastmail Original-Received: by mail.messagingengine.com (Postfix) with ESMTPA; Sun, 9 Apr 2023 05:33:32 -0400 (EDT) In-Reply-To: <87r0stqvrj.fsf@posteo.net> X-Correlation-ID: X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.devel:305199 Archived-At: Thanks Philip, I'll address your comments before adding the package. Bye, Tassilo 09.04.2023 10:56:28 Philip Kaludercic : > Tassilo Horn writes: >=20 >> Hi all, >>=20 >> I've written a small utility called switchy.el which I'd like to add to >> GNU ELPA.=C2=A0 I can do that on my own but wanted to give you a chance = for >> commenting first.=C2=A0 I'm attaching the file below. >>=20 >> In essence, the single command provided is `switchy-window' which is >> similar to `other-window' except that it switches to other windows in >> last-recently-used order instead of top-to-bottom-left-to-right order. >> With quick consecutive invocations you can reach any window but if you >> have a small delay between invocations (controlled by the single >> defcustom `switchy-delay'), you toggle between the two last recently >> used windows. >>=20 >> Bye, >> Tassilo >>=20 >> ;;; switchy.el --- A last-recently-used window switcher=C2=A0 -*- lexica= l-binding: t; -*- >> ;; >> ;; Copyright (C) 2023 Tassilo Horn >> ;; >> ;; Author: Tassilo Horn >> ;; Version: 1.0 >> ;; Keywords: windows >> ;; Homepage: https://sr.ht/~tsdh/switchy/ >> ;; Repository: https://git.sr.ht/~tsdh/switchy >> ;; Package-Requires: ((emacs "25.1") (compat "29.1.3.4")) >=20 > If you are to use compat 29.1.0.0 or newer then you also have to require > it! >=20 >> ;; SPDX-License-Identifier: GPL-3.0-or-later >> ;; >> ;; This file is NOT part of GNU Emacs. >=20 > If added to GNU ELPA, this should be change to "... is part of GNU > Emacs", right? >=20 >> ;; >> ;; This program 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 3 >> ;; of the License, or (at your option) any later version. >> ;; >> ;; This program 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.=C2=A0 See the >> ;; GNU General Public License for more details. >> ;; >> ;; You should have received a copy of the GNU General Public License >> ;; along with this program.=C2=A0 If not, see . >> ;; >> ;;; Commentary: >> ;; >> ;; Switchy is a last-recently-used window switcher.=C2=A0 It suits my pe= rsonal Emacs >> ;; layout and workflow where I usually have at most two editing windows = but up >> ;; to three side-windows which I have to select only seldomly. >> ;; >> ;; The idea of switchy is simple: when you invoke `switchy-window' in qu= ick >> ;; succession, it will switch to one window after the other in >> ;; last-recently-used order.=C2=A0 Once you stop switching for long enou= gh time >> ;; (`switchy-delay', 1.5 seconds by default), the selected window gets l= ocked >> ;; in, i.e., its LRU timestamp is updated and this switching sequence is= ended. >> ;; Thusly, you can toggle between two windows simply by invoking >> ;; `switchy-window', waiting at least `switchy-delay', and then invoking >> ;; `switchy-window' again to switch back to the original window. >> ;; >> ;; Activate `switchy-minor-mode' which tracks window changes and bind >> ;; `switchy-window' to a key of your liking in `switchy-minor-mode-map' = (or >> ;; globally, see the variable's docstring for examples). >> ;; >> ;; Hint: Since the order of window switching is not as obvious as it is = with >> ;; `other-window', adding a bit visual feedback to window selection chan= ges can >> ;; be helpful.=C2=A0 That can be done easily with the stock Emacs pulse.= el, e.g.: >> ;; >> ;;=C2=A0 (add-hook 'window-selection-change-functions >> ;;=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (la= mbda (frame) >> ;;=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0 (when (eq frame (selected-frame)) >> ;;=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0 (pulse-momentary-highlight-one-line)))) >>=20 >>=20 >> ;;; Code: >>=20 >> (defgroup switchy nil >> =C2=A0 "Switchy is a last-recently-used window-switcher." >> =C2=A0 :group 'windows) >>=20 >> (defvar switchy--tick-counter 0 >> =C2=A0 "Values of this counter represent the last-recently-used order of= windows. >> Only for internal use.") >>=20 >> (defvar switchy--tick-alist nil >> =C2=A0 "An alist with entries (WINDOW . TICK). >> A higher TICK value means a window has more recently been visited. >> Only for internal use.") >>=20 >> (defcustom switchy-delay 1.5 >> =C2=A0 "Number of seconds before the current window gets locked in. >> If more time elapses between consecutive invocations of >> `switchy-window', the current window's tick (timestamp) is >> updated in `switchy--tick-alist' and the current switching cycle >> ends." >> =C2=A0 :type 'number) >>=20 >> (defvar switchy--timer nil >> =C2=A0 "The timer locking in the current window after `switchy-delay' se= conds. >> Only for internal use.") >>=20 >> (defvar switchy--visited-windows nil >> =C2=A0 "The windows having already been visited in the current switching= cycle.") >>=20 >> (defun switchy--on-window-selection-change (&optional frame) >> =C2=A0 "Record the next `switchy--tick-counter' value for the selected w= indow of FRAME. >> Meant to be used in `window-selection-change-functions' which is >> arranged by `switchy-minor-mode'." >> =C2=A0 (when (eq frame (selected-frame)) >> =C2=A0=C2=A0=C2=A0 (when switchy--timer >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (cancel-timer switchy--timer)) >> =C2=A0=C2=A0=C2=A0 (setq switchy--timer (run-at-time >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0 switchy-delay nil >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0 (lambda () >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0 (setf (alist-get (selected-window) >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 switchy--tick-alist) >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (cl-incf switchy--tick-= counter)) >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0 (setq switchy--visited-windows nil)))))) >>=20 >> (defun switchy-window (&optional arg) >> =C2=A0 "Switch to other windows in last-recently-used order. >> If prefix ARG is given, use least-recently-used order. >>=20 >> If the time between consecutive invocations is smaller than >> `switchy-delay' seconds, selects one after the other window in >> LRU order and cycles when all windows have been visited.=C2=A0 If >> `switchy-delay' has passed, the current switching cycle ends and >> the now selected window gets its tick updated (a kind of >> timestamp)." >> =C2=A0 (interactive) >>=20 >> =C2=A0 (unless switchy-minor-mode >> =C2=A0=C2=A0=C2=A0 (user-error "switchy-window requires `switchy-minor-m= ode' being active")) >>=20 >> =C2=A0 ;; Remove dead windows. >> =C2=A0 (setq switchy--tick-alist (seq-filter >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0 (lambda (e) >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (window-live-p (car e))) >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0 switchy--tick-alist)) >> =C2=A0 ;; Add windows never selected. >> =C2=A0 (dolist (win (window-list (selected-frame))) >> =C2=A0=C2=A0=C2=A0 (unless (assq win switchy--tick-alist) >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (setf (alist-get win switchy--tick-alist)= 0))) >=20 > The setf is strictly speaking unnecessary here and causes an accidental > O(n^2) slowdown, since you traverse the list once to check if it has an > entry and then traverse it again to check if you can set 0 to an > existing entry.=C2=A0 You could also just push a cons-cell to the beginni= ng. > Then again, this is all bounded by the maximal number of windows that > someone has open so it doesn't matter in practice. >=20 >> =C2=A0 ;; Ensure the current window is marked as visited. >> =C2=A0 (setq switchy--visited-windows (cons (selected-window) >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0 switchy--visited-windows)) >>=20 >> =C2=A0 (let ((win-entries (seq-filter >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (lambda (e) >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (let ((w= in (car e))) >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0 (and (eq (window-frame win) (selected-frame)) >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (or (minibuffer-window-active-p win) >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (not (eq win (min= ibuffer-window >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (selecte= d-frame))))) >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (not (memq win switchy--visited-windows))= ))) >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 switchy--tick-alist)= )) >> =C2=A0=C2=A0=C2=A0 (if win-entries >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (when-let ((win (car (seq-red= uce (lambda (x e) >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (if (and x (funcall (if arg #'< #'>) >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= (cdr x) (cdr e))) >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 x >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 e)) >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0 win-entries nil)))) >>=20 >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (progn >=20 > Why the progn if you are using when-let? >=20 >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (setq= switchy--visited-windows (cons win switchy--visited-windows)) >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (sele= ct-window win))) >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ;; Start a new cycle if we're not at the = start already, i.e., we visited >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ;; just one (the current) window. >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (when (> (length switchy--visited-windows= ) 1) >=20 > Or (length> switchy--visited-windows 1)? >=20 >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (setq switchy--visited-window= s nil) >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (switchy-window))))) >>=20 >> (defvar switchy-minor-mode-map (make-sparse-keymap) >> =C2=A0 "The mode map of `switchy-minor-mode'. >> No keys are bound by default.=C2=A0 Bind the main command >> `switchy-window' to a key of your liking, e.g., >>=20 >> =C2=A0 ;; That\\=3D's what I use. >> =C2=A0 (keymap-set switchy-minor-mode-map \"C-<\" #\\=3D'switchy-window) >=20 > If you are already making use of keymap-set, you might as well define > the map itself using defvar-keymap (Compat provides it). >=20 >> =C2=A0 ;; Or as a substitute for `other-window'. >> =C2=A0 (add-hook \\=3D'switchy-minor-mode-hook >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (lamb= da () >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0 (if switchy-minor-mode >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (keymap-global-set \" \= " >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 #\\= =3D'switchy-window) >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0 (keymap-global-unset \" \"))))") >>=20 >> (define-minor-mode switchy-minor-mode >> =C2=A0 "Activates recording of window selection ticks. >> Those are the timestamps for figuring out the last-recently-used >> order of windows. >>=20 >> The minor-mode provides the keymap `switchy-minor-mode-map', >> which see." >> =C2=A0 :global t >> =C2=A0 :keymap switchy-minor-mode-map >=20 > Isn't this the default anyway? >=20 >> =C2=A0 (if switchy-minor-mode >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (add-hook 'window-selection-change-functi= ons >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0 #'switchy--on-window-selection-change) >> =C2=A0=C2=A0=C2=A0 (remove-hook 'window-selection-change-functions >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0 #'switchy--on-window-selection-change))) >>=20 >> (provide 'switchy) >>=20 >> (provide 'switchy) >=20 > Accidentally duplicated? >=20 >> ;;; switchy.el ends here >>=20 >=20