From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Philip Kaludercic Newsgroups: gmane.emacs.devel Subject: Re: [GNU ELPA] I'd like to add switchy.el: a last-recently-used window switcher Date: Sun, 09 Apr 2023 10:30:19 +0000 Message-ID: <87fs99qres.fsf@posteo.net> 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="20348"; mail-complaints-to="usenet@ciao.gmane.io" Cc: emacs-devel To: Tassilo Horn Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Sun Apr 09 12:31:14 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 1plSKI-00057m-Iz for ged-emacs-devel@m.gmane-mx.org; Sun, 09 Apr 2023 12:31:14 +0200 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1plSJd-0004qn-EZ; Sun, 09 Apr 2023 06:30:33 -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 1plSJa-0004qZ-PE for emacs-devel@gnu.org; Sun, 09 Apr 2023 06:30:30 -0400 Original-Received: from mout02.posteo.de ([185.67.36.66]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1plSJX-0006ft-RN for emacs-devel@gnu.org; Sun, 09 Apr 2023 06:30:30 -0400 Original-Received: from submission (posteo.de [185.67.36.169]) by mout02.posteo.de (Postfix) with ESMTPS id 9AAED24014C for ; Sun, 9 Apr 2023 12:30:25 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=posteo.net; s=2017; t=1681036225; bh=kYLC/vEuOaEvHInYEKT2SLNG8yR3PQS0se3YXdnOzTo=; h=From:To:Cc:Subject:Autocrypt:Date:From; b=Bug7WnwJDnKdWBf7et3rJOhXU7v1mWVx81t35+9Uxuc1KKEvmGFTCb8WVXjMhEJci vr5mVQt2Fl1owjn/SmTHtQgkZ4QDl5AG7r9DIwdLO6X3fTNsn3d8wZvp1G5w++fQFE fHeV84MJR19ITxB11T9QYxhgCViiTCr2oS0oR4Uqb97WBhc0foLupb7WtbIL8IgU67 +jTkPP06SMDJ5+K8GWZqTrdNCLFohDNJCi5T42O+0u254YSlbj7zUNpXQwzpSoWxpk HPxRGJ9hje7VcZJJM1TYxP8DDSOQSlfsmxfKz/bxxEPabC67s8JBCMBNL3i9Ui8bZf PGtibiQiTEV+Q== Original-Received: from customer (localhost [127.0.0.1]) by submission (posteo.de) with ESMTPSA id 4PvSzj172Hz9rxL; Sun, 9 Apr 2023 12:30:25 +0200 (CEST) In-Reply-To: (Tassilo Horn's message of "Sun, 9 Apr 2023 11:33:30 +0200 (GMT+02:00)") Autocrypt: addr=philipk@posteo.net; keydata= mDMEZBBQQhYJKwYBBAHaRw8BAQdAHJuofBrfqFh12uQu0Yi7mrl525F28eTmwUDflFNmdui0QlBo aWxpcCBLYWx1ZGVyY2ljIChnZW5lcmF0ZWQgYnkgYXV0b2NyeXB0LmVsKSA8cGhpbGlwa0Bwb3N0 ZW8ubmV0PoiWBBMWCAA+FiEEDg7HY17ghYlni8XN8xYDWXahwukFAmQQUEICGwMFCQHhM4AFCwkI BwIGFQoJCAsCBBYCAwECHgECF4AACgkQ8xYDWXahwulikAEA77hloUiSrXgFkUVJhlKBpLCHUjA0 mWZ9j9w5d08+jVwBAK6c4iGP7j+/PhbkxaEKa4V3MzIl7zJkcNNjHCXmvFcEuDgEZBBQQhIKKwYB BAGXVQEFAQEHQI5NLiLRjZy3OfSt1dhCmFyn+fN/QKELUYQetiaoe+MMAwEIB4h+BBgWCAAmFiEE Dg7HY17ghYlni8XN8xYDWXahwukFAmQQUEICGwwFCQHhM4AACgkQ8xYDWXahwukm+wEA8cml4JpK NeAu65rg+auKrPOP6TP/4YWRCTIvuYDm0joBALw98AMz7/qMHvSCeU/hw9PL6u6R2EScxtpKnWof z4oM Received-SPF: pass client-ip=185.67.36.66; envelope-from=philipk@posteo.net; helo=mout02.posteo.de X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action 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:305200 Archived-At: Tassilo Horn writes: > Thanks Philip, > > I'll address your comments before adding the package. Great, looking forward to seeing the package on ELPA :) > 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 -*- lexic= al-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 p= ersonal 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 q= uick >>> ;; succession, it will switch to one window after the other in >>> ;; last-recently-used order.=C2=A0 Once you stop switching for long eno= ugh time >>> ;; (`switchy-delay', 1.5 seconds by default), the selected window gets = locked >>> ;; in, i.e., its LRU timestamp is updated and this switching sequence i= s 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 cha= nges 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 (l= ambda (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 o= f 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' s= econds. >>> Only for internal use.") >>>=20 >>> (defvar switchy--visited-windows nil >>> =C2=A0 "The windows having already been visited in the current switchin= g cycle.") >>>=20 >>> (defun switchy--on-window-selection-change (&optional frame) >>> =C2=A0 "Record the next `switchy--tick-counter' value for the selected = window 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--ti= ck-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-= mode' 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 beginn= ing. >> 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 = ((win (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 (= minibuffer-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 (sele= cted-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-window= s))))) >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=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-ali= st))) >>> =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-re= duce (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 (set= q 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 (sel= ect-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-window= s) 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-windo= ws 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 (lam= bda () >>> =C2=A0=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-funct= ions >>> =C2=A0=C2=A0=C2=A0=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 --=20 Philip Kaludercic