From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED.blaine.gmane.org!not-for-mail From: Yuan Fu Newsgroups: gmane.emacs.devel Subject: Re: Customize =?utf-8?Q?=E2=80=98window-state-get=2Fput=E2=80=99?= Date: Wed, 09 Oct 2019 20:35:51 -0400 Message-ID: References: <87sgo4kyfp.fsf@mail.linkov.net> <87lfttbo70.fsf@mail.linkov.net> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Injection-Info: blaine.gmane.org; posting-host="blaine.gmane.org:195.159.176.226"; logging-data="265544"; mail-complaints-to="usenet@blaine.gmane.org" Cc: Emacs developers To: Juri Linkov Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Thu Oct 10 02:36:41 2019 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([209.51.188.17]) by blaine.gmane.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.89) (envelope-from ) id 1iIMRc-0016sX-Ro for ged-emacs-devel@m.gmane.org; Thu, 10 Oct 2019 02:36:41 +0200 Original-Received: from localhost ([::1]:32796 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iIMRb-0007j6-2P for ged-emacs-devel@m.gmane.org; Wed, 09 Oct 2019 20:36:39 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:46360) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iIMQx-0007iv-JS for emacs-devel@gnu.org; Wed, 09 Oct 2019 20:36:01 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iIMQv-0000vE-8o for emacs-devel@gnu.org; Wed, 09 Oct 2019 20:35:59 -0400 Original-Received: from mail-qk1-x72b.google.com ([2607:f8b0:4864:20::72b]:39233) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1iIMQu-0000v5-W2 for emacs-devel@gnu.org; Wed, 09 Oct 2019 20:35:57 -0400 Original-Received: by mail-qk1-x72b.google.com with SMTP id 4so3996069qki.6 for ; Wed, 09 Oct 2019 17:35:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:in-reply-to:references:date:message-id :mime-version; bh=axqi8LixsajxdhS+o9Qe5FPgum9eG4PQcuEWjyj6cnU=; b=FnowPUxtbrnWlKQ7KTsPPrPNekn5Bm5L2kHQCokxssy31oDdSO1ECKe9XmHEShcSiL kiZ3mE7hiKembv7BpffMbWjs2whZdU6ByBmU+6ceMx1XHthPO+VJkc/GwpZT/0EVP83Y My8Th3Q/EDgYwm3LzZpLs6ZxokNGI1fpKKLXN3KpbFf4Zdv4SKxfJE7tZvyP8PdmZa6R H5kDe6QZNTsSwgYOhpw2vh22s77X8dNcNknmsIPy+r/PqgU0dyDgxYkgVMoyhrl/lBPk /iJsCilGoUADNTyVkUT+lc13veXyZw2GZzuhx8SPDlOQ9iypcCT2Kn8I5X5PUkjwEzBi sfiw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:in-reply-to:references:date :message-id:mime-version; bh=axqi8LixsajxdhS+o9Qe5FPgum9eG4PQcuEWjyj6cnU=; b=IrMoWx3qoJpo7leQkL4N4ZFY6xnbjzx1EHaHmBmuMgGDGLXoB1wPanmPTm1n/fngGs uIha4ZO3wASxF8txpsiwwrt7QhQI7KeYXASx06JaXCSLq4nO1vttTWwZkZUQOJ3dCrCG /Tq9eknwGZBJbQ0fzi7RKio3rrbVcPBXCPhB6q+UOrXwS55BtxYUuw4jxY0H7Hq/NvfZ qVGLwCd/CXFd9O6UNW2UQ6WJS9qdtLpcTBWUqtYsm+0wyY4Oerm2BvpaJpUpJrnnwwLE J2jJj9bMynXvtT0hNCOiI7IO2RUFoUKonI0jlPnFfKJ5JvZNkAZUid+RkYaUU0FitK5f FxSw== X-Gm-Message-State: APjAAAVsm2SowOaF1KrRCoY/r9cQtUdEJHPpmh4/lJACr9PvrCRH+XWQ uC04h6ukupK0D6GA9o7Gp+taL5kNOaQhDA== X-Google-Smtp-Source: APXvYqwgSRbkyfZJEIKK8NeHp9sKlGMfPL5Lu2mGuDo2h1e+K7V+TXp1yC4hNz+oHKPQqHCj7EwFYw== X-Received: by 2002:a05:620a:204a:: with SMTP id d10mr6323209qka.319.1570667755832; Wed, 09 Oct 2019 17:35:55 -0700 (PDT) Original-Received: from missSilver.localdomain (c-71-207-8-160.hsd1.pa.comcast.net. [71.207.8.160]) by smtp.gmail.com with ESMTPSA id c20sm1484497qkm.11.2019.10.09.17.35.53 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Wed, 09 Oct 2019 17:35:54 -0700 (PDT) Original-Received: by missSilver.localdomain (Postfix, from userid 501) id 14CDA20287B7D1; Wed, 9 Oct 2019 20:35:51 -0400 (EDT) In-Reply-To: <87lfttbo70.fsf@mail.linkov.net> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:4864:20::72b X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.23 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.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.org gmane.emacs.devel:240805 Archived-At: --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable > But fortunately now we have window-states that are better suitable to bui= ld > the feature that you are adding. So if you will have such template based > on exported window-state layout: > > (hc (vc (leaf (buffer "\\`\\*\\(locals\\|registers\\) of .*\\*\\'")) > (leaf (buffer "\\`\\*\\(breakpoints\\|threads\\) of .*\\*\\'"))) > (vc (leaf (buffer "\\`\\*memory of .*\\*\\'")) > (leaf (buffer "\\`\\*stack frames of .*\\*\\'")))) > > (window-sizes are omitted in this example, but they could be expressed > as percentage of relative window dimensions) > > then calling (display-buffer "*memory of emacs*") could search in > such window-tree, find a window that matches the buffer name and > display this buffer in it. > > This could be implemented by just adding a new display-buffer action. I=E2=80=99m not sure what are you trying to do overall. Why don=E2=80=99t I= just create the buffer by the buffer configurations I saved when saving the window configuration? OTOH, here is an experiment I did earlier today. I optionally replace the buffer names and configurations with a function when saving window config. So instead of (buffer "*scratch*" (selected . t)=20=20=20=20=20=20=20=20=20=20=20=20=20 ... (dedicated) (point . 290) (start . 1)) I save (buffer lambda nil (create-my-buffer "some useful info")) And when window-state-put finds out the data is not buffer name but a function, it simply calls the function to restore the buffer. This way we can store information about the buffer and how to restore it in a rather compact way. The change to existing code is pretty small, too. WDYT? Yuan --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0001-window.patch >From 9853d8e0f529be0b495415674e96346e575787e9 Mon Sep 17 00:00:00 2001 From: Yuan Fu Date: Wed, 9 Oct 2019 16:26:35 -0400 Subject: [PATCH] window --- lisp/window.el | 261 ++++++++++++++++++++++++++----------------------- 1 file changed, 136 insertions(+), 125 deletions(-) diff --git a/lisp/window.el b/lisp/window.el index d93ec0add6..b2cebdb194 100644 --- a/lisp/window.el +++ b/lisp/window.el @@ -5669,7 +5669,7 @@ balance-windows-area )) ;;; Window states, how to get them and how to put them in a window. -(defun window--state-get-1 (window &optional writable) +(defun window--state-get-1 (window &optional writable buffer-fn) "Helper function for `window-state-get'." (let* ((type (cond @@ -5718,28 +5718,30 @@ window--state-get-1 `((parameters . ,list)))) ,@(when buffer ;; All buffer related things go in here. - (let ((point (window-point window)) - (start (window-start window))) - `((buffer - ,(if writable (buffer-name buffer) buffer) - (selected . ,selected) - (hscroll . ,(window-hscroll window)) - (fringes . ,(window-fringes window)) - (margins . ,(window-margins window)) - (scroll-bars . ,(window-scroll-bars window)) - (vscroll . ,(window-vscroll window)) - (dedicated . ,(window-dedicated-p window)) - (point . ,(if writable - point - (with-current-buffer buffer - (copy-marker point - (buffer-local-value - 'window-point-insertion-type - buffer))))) - (start . ,(if writable - start - (with-current-buffer buffer - (copy-marker start)))))))) + (if buffer-fn + `((buffer . ,(funcall buffer-fn buffer))) + (let ((point (window-point window)) + (start (window-start window))) + `((buffer + ,(if writable (buffer-name buffer) buffer) + (selected . ,selected) + (hscroll . ,(window-hscroll window)) + (fringes . ,(window-fringes window)) + (margins . ,(window-margins window)) + (scroll-bars . ,(window-scroll-bars window)) + (vscroll . ,(window-vscroll window)) + (dedicated . ,(window-dedicated-p window)) + (point . ,(if writable + point + (with-current-buffer buffer + (copy-marker point + (buffer-local-value + 'window-point-insertion-type + buffer))))) + (start . ,(if writable + start + (with-current-buffer buffer + (copy-marker start))))))))) ,@(when next-buffers `((next-buffers . ,(if writable @@ -5765,7 +5767,7 @@ window--state-get-1 (nreverse list))))) (append head tail))) -(defun window-state-get (&optional window writable) +(defun window-state-get (&optional window writable buffer-fn) "Return state of WINDOW as a Lisp object. WINDOW can be any window and defaults to the root window of the selected frame. @@ -5779,6 +5781,13 @@ window-state-get an `invalid-read-syntax' error while attempting to read back the value from file. +Optional argument BUFFER-FN is a function that takes a buffer +object and returns a function that takes no argument and +recreates the buffer. If you set WRITABLE to t, you shouldn't +return any function with non-readable value in it. And it is +recommended to quote the lambda form you return in order to avoid +lexical context. + The return value can be used as argument for `window-state-put' to put the state recorded here into an arbitrary window. The value can be also stored on disk and read back in a new session." @@ -5806,7 +5815,7 @@ window-state-get (min-pixel-width-ignore . ,(window-min-size window t t t)) (min-pixel-height-safe . ,(window-min-size window nil 'safe t)) (min-pixel-width-safe . ,(window-min-size window t 'safe t))) - (window--state-get-1 window writable))) + (window--state-get-1 window writable buffer-fn))) (defvar window-state-put-list nil "Helper variable for `window-state-put'.") @@ -5911,106 +5920,108 @@ window--state-put-2 (set-window-parameter window (car parameter) (cdr parameter)))) ;; Process buffer related state. (when state - (let ((buffer (get-buffer (car state))) - (state (cdr state))) - (if buffer - (with-current-buffer buffer - (set-window-buffer window buffer) - (set-window-hscroll window (cdr (assq 'hscroll state))) - (apply 'set-window-fringes - (cons window (cdr (assq 'fringes state)))) - (let ((margins (cdr (assq 'margins state)))) - (set-window-margins window (car margins) (cdr margins))) - (let ((scroll-bars (cdr (assq 'scroll-bars state)))) - (set-window-scroll-bars - window (car scroll-bars) (nth 2 scroll-bars) - (nth 3 scroll-bars) (nth 5 scroll-bars) (nth 6 scroll-bars))) - (set-window-vscroll window (cdr (assq 'vscroll state))) - ;; Adjust vertically. - (if (or (memq window-size-fixed '(t height)) - (window-preserved-size window)) - ;; A fixed height window, try to restore the - ;; original size. - (let ((delta - (- (cdr (assq - (if pixelwise 'pixel-height 'total-height) - item)) - (window-size window nil pixelwise))) - window-size-fixed) - (when (window--resizable-p - window delta nil nil nil nil nil pixelwise) - (window-resize window delta nil nil pixelwise))) - ;; Else check whether the window is not high enough. - (let* ((min-size - (window-min-size window nil ignore pixelwise)) - (delta - (- min-size (window-size window nil pixelwise)))) - (when (and (> delta 0) - (window--resizable-p - window delta nil ignore nil nil nil pixelwise)) - (window-resize window delta nil ignore pixelwise)))) - ;; Adjust horizontally. - (if (or (memq window-size-fixed '(t width)) - (window-preserved-size window t)) - ;; A fixed width window, try to restore the original - ;; size. - (let ((delta - (- (cdr (assq - (if pixelwise 'pixel-width 'total-width) - item)) - (window-size window t pixelwise))) - window-size-fixed) - (when (window--resizable-p - window delta t nil nil nil nil pixelwise) - (window-resize window delta t nil pixelwise))) - ;; Else check whether the window is not wide enough. - (let* ((min-size (window-min-size window t ignore pixelwise)) - (delta (- min-size (window-size window t pixelwise)))) - (when (and (> delta 0) - (window--resizable-p - window delta t ignore nil nil nil pixelwise)) - (window-resize window delta t ignore pixelwise)))) - ;; Set dedicated status. - (set-window-dedicated-p window (cdr (assq 'dedicated state))) - ;; Install positions (maybe we should do this after all - ;; windows have been created and sized). - (ignore-errors - ;; Set 'noforce argument to avoid that window start - ;; overrides window point set below (Bug#24240). - (set-window-start window (cdr (assq 'start state)) 'noforce) - (set-window-point window (cdr (assq 'point state)))) - ;; Select window if it's the selected one. - (when (cdr (assq 'selected state)) - (select-window window)) - (when next-buffers - (set-window-next-buffers - window - (delq nil (mapcar (lambda (buffer) - (setq buffer (get-buffer buffer)) - (when (buffer-live-p buffer) buffer)) - next-buffers)))) - (when prev-buffers - (set-window-prev-buffers - window - (delq nil (mapcar (lambda (entry) - (let ((buffer (get-buffer (nth 0 entry))) - (m1 (nth 1 entry)) - (m2 (nth 2 entry))) - (when (buffer-live-p buffer) - (list buffer - (if (markerp m1) m1 - (set-marker (make-marker) m1 - buffer)) - (if (markerp m2) m2 - (set-marker (make-marker) m2 - buffer)))))) - prev-buffers))))) - ;; We don't want to raise an error in case the buffer does - ;; not exist anymore, so we switch to a previous one and - ;; save the window with the intention of deleting it later - ;; if possible. - (switch-to-prev-buffer window) - (push window window-state-put-stale-windows))))))) + (if (functionp state) + (funcall state) + (let ((buffer (get-buffer (car state))) + (state (cdr state))) + (if buffer + (with-current-buffer buffer + (set-window-buffer window buffer) + (set-window-hscroll window (cdr (assq 'hscroll state))) + (apply 'set-window-fringes + (cons window (cdr (assq 'fringes state)))) + (let ((margins (cdr (assq 'margins state)))) + (set-window-margins window (car margins) (cdr margins))) + (let ((scroll-bars (cdr (assq 'scroll-bars state)))) + (set-window-scroll-bars + window (car scroll-bars) (nth 2 scroll-bars) + (nth 3 scroll-bars) (nth 5 scroll-bars) (nth 6 scroll-bars))) + (set-window-vscroll window (cdr (assq 'vscroll state))) + ;; Adjust vertically. + (if (or (memq window-size-fixed '(t height)) + (window-preserved-size window)) + ;; A fixed height window, try to restore the + ;; original size. + (let ((delta + (- (cdr (assq + (if pixelwise 'pixel-height 'total-height) + item)) + (window-size window nil pixelwise))) + window-size-fixed) + (when (window--resizable-p + window delta nil nil nil nil nil pixelwise) + (window-resize window delta nil nil pixelwise))) + ;; Else check whether the window is not high enough. + (let* ((min-size + (window-min-size window nil ignore pixelwise)) + (delta + (- min-size (window-size window nil pixelwise)))) + (when (and (> delta 0) + (window--resizable-p + window delta nil ignore nil nil nil pixelwise)) + (window-resize window delta nil ignore pixelwise)))) + ;; Adjust horizontally. + (if (or (memq window-size-fixed '(t width)) + (window-preserved-size window t)) + ;; A fixed width window, try to restore the original + ;; size. + (let ((delta + (- (cdr (assq + (if pixelwise 'pixel-width 'total-width) + item)) + (window-size window t pixelwise))) + window-size-fixed) + (when (window--resizable-p + window delta t nil nil nil nil pixelwise) + (window-resize window delta t nil pixelwise))) + ;; Else check whether the window is not wide enough. + (let* ((min-size (window-min-size window t ignore pixelwise)) + (delta (- min-size (window-size window t pixelwise)))) + (when (and (> delta 0) + (window--resizable-p + window delta t ignore nil nil nil pixelwise)) + (window-resize window delta t ignore pixelwise)))) + ;; Set dedicated status. + (set-window-dedicated-p window (cdr (assq 'dedicated state))) + ;; Install positions (maybe we should do this after all + ;; windows have been created and sized). + (ignore-errors + ;; Set 'noforce argument to avoid that window start + ;; overrides window point set below (Bug#24240). + (set-window-start window (cdr (assq 'start state)) 'noforce) + (set-window-point window (cdr (assq 'point state)))) + ;; Select window if it's the selected one. + (when (cdr (assq 'selected state)) + (select-window window)) + (when next-buffers + (set-window-next-buffers + window + (delq nil (mapcar (lambda (buffer) + (setq buffer (get-buffer buffer)) + (when (buffer-live-p buffer) buffer)) + next-buffers)))) + (when prev-buffers + (set-window-prev-buffers + window + (delq nil (mapcar (lambda (entry) + (let ((buffer (get-buffer (nth 0 entry))) + (m1 (nth 1 entry)) + (m2 (nth 2 entry))) + (when (buffer-live-p buffer) + (list buffer + (if (markerp m1) m1 + (set-marker (make-marker) m1 + buffer)) + (if (markerp m2) m2 + (set-marker (make-marker) m2 + buffer)))))) + prev-buffers))))) + ;; We don't want to raise an error in case the buffer does + ;; not exist anymore, so we switch to a previous one and + ;; save the window with the intention of deleting it later + ;; if possible. + (switch-to-prev-buffer window) + (push window window-state-put-stale-windows)))))))) (defun window-state-put (state &optional window ignore) "Put window state STATE into WINDOW. -- 2.21.0 (Apple Git-122) --=-=-=--