From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Thierry Volpiatto Newsgroups: gmane.emacs.bugs Subject: bug#66394: 29.1; Make register-read-with-preview more useful Date: Sat, 25 Nov 2023 21:14:31 +0000 Message-ID: <87zfz1cz7s.fsf@posteo.net> References: <87il7ib6cu.fsf@posteo.net> <875y3386ep.fsf@posteo.net> <87a5sddh14.fsf@web.de> <8734y5vnj7.fsf@posteo.net> <87bkcslr18.fsf@web.de> <87y1fwtyrl.fsf@posteo.net> <87y1fut1wp.fsf@web.de> <87ttqgpjiz.fsf@posteo.net> <87wmvbibpr.fsf@web.de> <877cnb2n63.fsf@posteo.net> <8734xyc8z0.fsf@web.de> <87zg05rewi.fsf@posteo.net> <87ttqcg8gw.fsf@web.de> <87h6mcr8ol.fsf@posteo.net> <87r0l73029.fsf@web.de> <877cmdx8ud.fsf@posteo.net> <87sf50s1gh.fsf@posteo.net> <83o7ficesp.fsf@gnu.org> <878r6leh9d.fsf@posteo.net> <83il5pbnmh.fsf@gnu.org> Mime-Version: 1.0 Content-Type: multipart/signed; boundary="==-=-="; micalg=pgp-sha512; protocol="application/pgp-signature" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="10215"; mail-complaints-to="usenet@ciao.gmane.io" Cc: michael_heerdegen@web.de, 66394@debbugs.gnu.org, monnier@iro.umontreal.ca, stefankangas@gmail.com To: Eli Zaretskii Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Sat Nov 25 22:15:14 2023 Return-path: Envelope-to: geb-bug-gnu-emacs@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 1r6zze-0002Pl-4Q for geb-bug-gnu-emacs@m.gmane-mx.org; Sat, 25 Nov 2023 22:15:14 +0100 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1r6zzO-0001dr-KM; Sat, 25 Nov 2023 16:14:58 -0500 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 1r6zzN-0001dj-Nk for bug-gnu-emacs@gnu.org; Sat, 25 Nov 2023 16:14:57 -0500 Original-Received: from debbugs.gnu.org ([2001:470:142:5::43]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1r6zzN-0000LM-FM for bug-gnu-emacs@gnu.org; Sat, 25 Nov 2023 16:14:57 -0500 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1r6zzS-00042j-MS for bug-gnu-emacs@gnu.org; Sat, 25 Nov 2023 16:15:02 -0500 X-Loop: help-debbugs@gnu.org Resent-From: Thierry Volpiatto Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sat, 25 Nov 2023 21:15:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 66394 X-GNU-PR-Package: emacs Original-Received: via spool by 66394-submit@debbugs.gnu.org id=B66394.170094689615511 (code B ref 66394); Sat, 25 Nov 2023 21:15:02 +0000 Original-Received: (at 66394) by debbugs.gnu.org; 25 Nov 2023 21:14:56 +0000 Original-Received: from localhost ([127.0.0.1]:40366 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1r6zzL-000426-GY for submit@debbugs.gnu.org; Sat, 25 Nov 2023 16:14:56 -0500 Original-Received: from mout02.posteo.de ([185.67.36.66]:59421) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1r6zzH-00041p-Ph for 66394@debbugs.gnu.org; Sat, 25 Nov 2023 16:14:53 -0500 Original-Received: from submission (posteo.de [185.67.36.169]) by mout02.posteo.de (Postfix) with ESMTPS id 6924F240103 for <66394@debbugs.gnu.org>; Sat, 25 Nov 2023 22:14:40 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=posteo.net; s=2017; t=1700946880; bh=yOPaBOtIqBzsKQEEcPiPlel2QZUQH+9ZO7CZKo5DZ5c=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version:Autocrypt:OpenPGP: From; b=DUdoPfzRMSsXw7q08pnlZlMRednN2xZmTLR20JSC0P+bokmirKM/Jrbwi3KTyxa8k 23+FNxtqxw71GwPOHWffFqKHDnhrWDoC96QR+4PBAMfwNWMWqx7NCfeL7IR6tL/KyY J8l4U80/HhrlVhCZaDzSKSEAyHoMkkaJ6dvtkCYpx8KpY6rXOFivb03Cn6Zb4tRgdj 6oDXoAHajIifP8qoUyaOfUBh0axj+ma7EH+abHRkSY63N6vdZx/d9Uh6QbpZHms9pO YQRwxQkgC6Czln0rCa8PCCxlVLQ303QMYkCG497h3sQPv91WyEnSLR271JRjxGrowU xQvKPIIie9n5Q== Original-Received: from customer (localhost [127.0.0.1]) by submission (posteo.de) with ESMTPSA id 4Sd4Nt1VBPz6tsB; Sat, 25 Nov 2023 22:14:37 +0100 (CET) In-Reply-To: <83il5pbnmh.fsf@gnu.org> (Eli Zaretskii's message of "Sat, 25 Nov 2023 22:10:14 +0200 (53 minutes, 35 seconds ago)") Autocrypt: addr=thievol@posteo.net; prefer-encrypt=mutual; keydata=xsDNBF8ylcIBDADG+hy+zR6L4/vbdDDZuSaMmSrU3A5QZJpeBCvxTr7MpzzruZbhLPW1K3R6N2MA edi8Y+C8o27FVRIjpdbaKMGu9je7JV/TbUQYo3SOwCK1vM4LUn4V6ZLzSYkuiEt4eyMoiDdyvN0p kcK6P9x9DCetcEVszXzQg+yzCVrQ2hXWDXWT4M18EC3wtO7RHPouMqGiwBFhBAYErCqFWFxQHkfb tG/4yGyJ58rglb65O3qijjMWvYwcWZun9/7qm8Z4/4mHopmo2zgU+OrptnLSZfkZGz3Y7Uf452xQ GVq0Fv75NPvQru7y+DYVhuVXXyAmGxt+vf4rIiixMBbhKEPjcxEPAa2LTzex2IsTZR+QVG9uDnqC WcgaOEQ58fzXNvNhtwwF/Rgio2XWAJVdmFWS59/k9W58CIUSNKBMZh2XeGdEmtHvDtCxW3z6FJha 36RzOM3fMNNiAGdFZJA84gcdloJR+sHCDTTPT3784fjr+V8An7sI581NGFzkRQqPvEQCZbUAEQEA Ac0SdGhpZXZvbEBwb3N0ZW8ubmV0wsEOBBMBCgA4AhsDBQsJCAcCBhUKCQgLAgQWAgMBAh4BAheA FiEEI9twfRN7r3nig/xwDsVtFB0W75MFAmL3HCoACgkQDsVtFB0W75OVEAv/f6XxmtIFz08fUb8h Bp/zJP6IC4/rhhh+0GMRIRzLN8DK0jV8JCzYdFHiRJOy2lNIOpmrrCmjRRxferc2G42+ePFIsslx hU46VSz1Z83NwIG3mpdYNV5WUTUdgzxExHTNTFCd7NKv0nlHKQaA OpenPGP: url=https://posteo.de/keys/thievol@posteo.net.asc; preference=encrypt X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.bugs:275019 Archived-At: --==-=-= Content-Type: multipart/mixed; boundary="=-=-=" --=-=-= Content-Type: text/plain Content-Transfer-Encoding: quoted-printable Eli Zaretskii writes: > How would "make clean" help? I did remove register.elc, it didn't > help. Not only register is involved here but indirectly cl-generic. > OK, so I guess I shouldn't have tried to install it. Here a patch with the change suggested by Stefan applied, slighly modified though because it fails if I put the call to cl--generic-prefill-dispatchers at the recommended place. I recompiled Emacs with this patch with no errors. =20 =2D-=20 Thierry --=-=-= Content-Type: text/x-diff Content-Disposition: attachment; filename=0001-Improve-register-preview-Fix-bug-66394.patch Content-Transfer-Encoding: quoted-printable From=20ccecd34b8307c7168e89289f933e63590ce6fc9c Mon Sep 17 00:00:00 2001 From: Thierry Volpiatto Date: Sun, 19 Nov 2023 20:42:56 +0100 Subject: [PATCH] Improve register-preview (Fix bug#66394) A minibuffer is used now instead of read-key. Registers in preview buffer are now filtered according to type of registers the current command requires. Navigation with C-n/p or up/down is now provided and update minibuffer. Current register is highlighted in preview buffer. * cl-generic.el: Add a call to `cl--generic-prefill-dispatchers` to fix build error. * register.el: * (register-preview-default-keys): new user var. * (register-use-preview): Same. * (register-preview-info): New structure to store various info for preview. * (register-command-info): New generic. * (register-preview-forward-line): New, provide navigation in preview buffer. * (register-preview-next, register-preview-previous): New, navigation. * (register-type): New, returns register type. * (register--type): Generic fn, new, returns register type according to value. * (register-of-type-alist): New, filter register-alist according to type. * (register-preview): Signature changed, use TYPES now. * (register-preview-get-defaults): New generic, compute defauts according to action. * (register-read-with-preview): Now use read-from-minibuffer and minibuffer-setup-hook. =2D-- lisp/emacs-lisp/cl-generic.el | 1 + lisp/register.el | 295 +++++++++++++++++++++++++++++----- 2 files changed, 259 insertions(+), 37 deletions(-) diff --git a/lisp/emacs-lisp/cl-generic.el b/lisp/emacs-lisp/cl-generic.el index 56eb83e6f75..0ef0d1e192a 100644 =2D-- a/lisp/emacs-lisp/cl-generic.el +++ b/lisp/emacs-lisp/cl-generic.el @@ -1379,6 +1379,7 @@ See the full list and their hierarchy in `cl--typeof-= types'." (cl--generic-prefill-dispatchers 0 integer) (cl--generic-prefill-dispatchers 1 integer) (cl--generic-prefill-dispatchers 0 cl--generic-generalizer integer) +(cl--generic-prefill-dispatchers 0 (eql 'x) integer) =20 ;;; Dispatch on major mode. =20 diff --git a/lisp/register.el b/lisp/register.el index ca6de450993..61bef503f91 100644 =2D-- a/lisp/register.el +++ b/lisp/register.el @@ -35,6 +35,8 @@ =20 ;; FIXME: Clean up namespace usage! =20 +(declare-function frameset-register-p "frameset") + (cl-defstruct (registerv (:constructor nil) (:constructor registerv--make (&optional data print-func @@ -91,6 +93,7 @@ of the marked text." :type '(choice (const :tag "None" nil) (character :tag "Use register" :value ?+))) =20 +;; FIXME: This is no more needed, remove it. (defcustom register-preview-delay 1 "If non-nil, time to wait in seconds before popping up register preview = window. If nil, do not show register previews, unless `help-char' (or a member of @@ -99,6 +102,14 @@ If nil, do not show register previews, unless `help-cha= r' (or a member of :type '(choice number (const :tag "No preview unless requested" nil)) :group 'register) =20 +(defcustom register-preview-default-keys (mapcar #'string (number-sequence= ?a ?z)) + "Default keys for setting a new register." + :type '(repeat string)) + +(defcustom register-use-preview t + "Always show register preview when non nil." + :type 'boolean) + (defun get-register (register) "Return contents of Emacs register named REGISTER, or nil if none." (alist-get register register-alist)) @@ -128,53 +139,263 @@ See the documentation of the variable `register-alis= t' for possible VALUEs." Called with one argument, a cons (NAME . CONTENTS) as found in `register-a= list'. The function should return a string, the description of the argument.") =20 =2D(defun register-preview (buffer &optional show-empty) +(cl-defstruct register-preview-info + "Store data for a specific register command. +TYPES are the types of register supported. +MSG is the minibuffer message to send when a register is selected. +ACT is the type of action the command is doing on register. +SMATCH accept a boolean value to say if command accept non matching regist= er." + types msg act smatch) + +(cl-defgeneric register-command-info (command) + "Returns a `register-preview-info' object storing data for COMMAND." + (ignore command)) +(cl-defmethod register-command-info ((_command (eql insert-register))) + (make-register-preview-info + :types '(string number) + :msg "Insert register `%s'" + :act 'insert + :smatch t)) +(cl-defmethod register-command-info ((_command (eql jump-to-register))) + (make-register-preview-info + :types '(window frame marker kmacro + file buffer file-query) + :msg "Jump to register `%s'" + :act 'jump + :smatch t)) +(cl-defmethod register-command-info ((_command (eql view-register))) + (make-register-preview-info + :types '(all) + :msg "View register `%s'" + :act 'view + :smatch t)) +(cl-defmethod register-command-info ((_command (eql append-to-register))) + (make-register-preview-info + :types '(string number) + :msg "Append to register `%s'" + :act 'modify + :smatch t)) +(cl-defmethod register-command-info ((_command (eql prepend-to-register))) + (make-register-preview-info + :types '(string number) + :msg "Prepend to register `%s'" + :act 'modify + :smatch t)) +(cl-defmethod register-command-info ((_command (eql increment-register))) + (make-register-preview-info + :types '(string number) + :msg "Increment register `%s'" + :act 'modify + :smatch t)) + +(defun register-preview-forward-line (arg) + "Move to next or previous line in register preview buffer. +If ARG is positive goto next line, if negative to previous. +Do nothing when defining or executing kmacros." + ;; Ensure user enter manually key in minibuffer when recording a macro. + (unless (or defining-kbd-macro executing-kbd-macro + (not (get-buffer-window "*Register Preview*" 'visible))) + (let ((fn (if (> arg 0) #'eobp #'bobp)) + (posfn (if (> arg 0) + #'point-min + (lambda () (1- (point-max))))) + str) + (with-current-buffer "*Register Preview*" + (let ((ovs (overlays-in (point-min) (point-max))) + pos) + (goto-char (if ovs + (overlay-start (car ovs)) + (point-min))) + (setq pos (point)) + (and ovs (forward-line arg)) + (when (and (funcall fn) + (or (> arg 0) (eql pos (point)))) + (goto-char (funcall posfn))) + (setq str (buffer-substring-no-properties + (pos-bol) (1+ (pos-bol)))) + (remove-overlays) + (with-selected-window (minibuffer-window) + (delete-minibuffer-contents) + (insert str))))))) + +(defun register-preview-next () + "Goto next line in register preview buffer." + (interactive) + (register-preview-forward-line 1)) + +(defun register-preview-previous () + "Goto previous line in register preview buffer." + (interactive) + (register-preview-forward-line -1)) + +(defun register-type (register) + "Return REGISTER type. +Current register types actually returned are one of: +- string +- number +- marker +- buffer +- file +- file-query +- window +- frame +- kmacro + +One can add new types to a specific command by defining a new `cl-defmetho= d' +matching this command. Predicate for type in new `cl-defmethod' should +satisfy `cl-typep' otherwise the new type should be defined with +`cl-deftype'." + ;; Call register--type against the register value. + (register--type (if (consp (cdr register)) + (cadr register) + (cdr register)))) + +(cl-defgeneric register--type (regval) + "Returns type of register value REGVAL." + (ignore regval)) + +(cl-defmethod register--type ((_regval string)) 'string) +(cl-defmethod register--type ((_regval number)) 'number) +(cl-defmethod register--type ((_regval marker)) 'marker) +(cl-defmethod register--type ((_regval (eql 'buffer))) 'buffer) +(cl-defmethod register--type ((_regval (eql 'file))) 'file) +(cl-defmethod register--type ((_regval (eql 'file-query))) 'file-query) +(cl-defmethod register--type ((_regval window-configuration)) 'window) +(cl-deftype frame-register () '(satisfies frameset-register-p)) +(cl-defmethod register--type :extra "frame-register" (_regval) 'frame) +(cl-deftype kmacro-register () '(satisfies kmacro-register-p)) +(cl-defmethod register--type :extra "kmacro-register" (_regval) 'kmacro) + +(defun register-of-type-alist (types) + "Filter `register-alist' according to TYPES." + (if (memq 'all types) + register-alist + (cl-loop for register in register-alist + when (memq (register-type register) types) + collect register))) + +(defun register-preview (buffer &optional show-empty types) "Pop up a window showing the registers preview in BUFFER. If SHOW-EMPTY is non-nil, show the window even if no registers. +Argument TYPES (a list) specify the types of register to show, when nil sh= ow all +registers, see `register-type' for suitable types. Format of each entry is controlled by the variable `register-preview-funct= ion'." =2D (when (or show-empty (consp register-alist)) =2D (with-current-buffer-window =2D buffer =2D (cons 'display-buffer-below-selected =2D '((window-height . fit-window-to-buffer) =2D (preserve-size . (nil . t)))) =2D nil =2D (with-current-buffer standard-output =2D (setq cursor-in-non-selected-windows nil) =2D (mapc (lambda (elem) =2D (when (get-register (car elem)) =2D (insert (funcall register-preview-function elem)))) =2D register-alist))))) + (let ((registers (register-of-type-alist (or types '(all))))) + (when (or show-empty (consp registers)) + (with-current-buffer-window + buffer + (cons 'display-buffer-below-selected + '((window-height . fit-window-to-buffer) + (preserve-size . (nil . t)))) + nil + (with-current-buffer standard-output + (setq cursor-in-non-selected-windows nil) + (mapc (lambda (elem) + (when (get-register (car elem)) + (insert (funcall register-preview-function elem)))) + registers)))))) + +(cl-defgeneric register-preview-get-defaults (action) + "Returns default registers according to ACTION." + (ignore action)) +(cl-defmethod register-preview-get-defaults ((_action (eql set))) + (cl-loop for s in register-preview-default-keys + unless (assoc (string-to-char s) register-alist) + collect s)) =20 (defun register-read-with-preview (prompt) "Read and return a register name, possibly showing existing registers. =2DPrompt with the string PROMPT. If `register-alist' and =2D`register-preview-delay' are both non-nil, display a window =2Dlisting existing registers after `register-preview-delay' seconds. +Prompt with the string PROMPT. If `help-char' (or a member of `help-event-list') is pressed, display such a window regardless." (let* ((buffer "*Register Preview*") =2D (timer (when (numberp register-preview-delay) =2D (run-with-timer register-preview-delay nil =2D (lambda () =2D (unless (get-buffer-window buffer) =2D (register-preview buffer)))))) =2D (help-chars (cl-loop for c in (cons help-char help-event-list) =2D when (not (get-register c)) =2D collect c))) + (pat "") + (map (let ((m (make-sparse-keymap))) + (set-keymap-parent m minibuffer-local-map) + m)) + (data (register-command-info this-command)) + types msg result timer act win strs smatch) + (if data + (setq types (register-preview-info-types data) + msg (register-preview-info-msg data) + act (register-preview-info-act data) + smatch (register-preview-info-smatch data)) + (setq types '(all) + msg "Overwrite register `%s'" + act 'set)) + (setq strs (mapcar (lambda (x) + (string (car x))) + (register-of-type-alist types))) + (when (and (memq act '(insert jump view)) (null strs)) + (error "No register suitable for `%s'" act)) + (dolist (k (cons help-char help-event-list)) + (define-key map + (vector k) (lambda () + (interactive) + (unless (get-buffer-window buffer) + (with-selected-window (minibuffer-selected-window) + (register-preview buffer 'show-empty types)))))) + (define-key map (kbd "") 'register-preview-next) + (define-key map (kbd "") 'register-preview-previous) + (define-key map (kbd "C-n") 'register-preview-next) + (define-key map (kbd "C-p") 'register-preview-previous) + (unless (or executing-kbd-macro (null register-use-preview)) + (register-preview buffer nil types)) (unwind-protect =2D (progn =2D (while (memq (read-key (propertize prompt 'face 'minibuffer-prompt)) =2D help-chars) =2D (unless (get-buffer-window buffer) =2D (register-preview buffer 'show-empty))) =2D (when (or (eq ?\C-g last-input-event) =2D (eq 'escape last-input-event) =2D (eq ?\C-\[ last-input-event)) =2D (keyboard-quit)) =2D (if (characterp last-input-event) last-input-event =2D (error "Non-character input-event"))) =2D (and (timerp timer) (cancel-timer timer)) + (progn + (minibuffer-with-setup-hook + (lambda () + (setq timer + (run-with-idle-timer + 0.01 'repeat + (lambda () + (with-selected-window (minibuffer-window) + (let ((input (minibuffer-contents))) + (when (> (length input) 1) + (let ((new (substring input 1)) + (old (substring input 0 1))) + (setq input (if (or (null smatch) + (member new strs)) + new old)) + (delete-minibuffer-contents) + (insert input))) + (when (and smatch (not (string=3D input "")) + (not (member input strs))) + (setq input "") + (delete-minibuffer-contents) + (minibuffer-message "Not matching")) + (when (not (string=3D input pat)) + (setq pat input)))) + (if (setq win (get-buffer-window buffer)) + (with-selected-window win + (let ((ov (make-overlay (point-min) (point= -min)))) + (goto-char (point-min)) + (remove-overlays) + (unless (string=3D pat "") + (if (re-search-forward (concat "^" pat= ) nil t) + (progn (move-overlay + ov + (match-beginning 0) (pos-e= ol)) + (overlay-put ov 'face 'matc= h) + (when msg + (with-selected-window (mi= nibuffer-window) + (minibuffer-message msg= pat)))) + (with-selected-window (minibuffer-wi= ndow) + (minibuffer-message + "Register `%s' is empty" pat)))))) + (unless (string=3D pat "") + (if (member pat strs) + (with-selected-window (minibuffer-window) + (minibuffer-message msg pat)) + (with-selected-window (minibuffer-window) + (minibuffer-message + "Register `%s' is empty" pat))))))))) + (setq result (read-from-minibuffer + prompt nil map nil nil (register-preview-get-de= faults act)))) + (cl-assert (and result (not (string=3D result ""))) + nil "No register specified") + (string-to-char result)) + (when timer (cancel-timer timer)) (let ((w (get-buffer-window buffer))) (and (window-live-p w) (delete-window w))) (and (get-buffer buffer) (kill-buffer buffer))))) =2D-=20 2.34.1 --=-=-=-- --==-=-= Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iQHHBAEBCgAxFiEEI9twfRN7r3nig/xwDsVtFB0W75MFAmViY7cTHHRoaWV2b2xA cG9zdGVvLm5ldAAKCRAOxW0UHRbvkyYKC/9RXiecwTB6vgNE/dlSve2M8NZyTsQ+ QspssF+GAtIZng1uqBtrTkEOP866cFE3OFUvn/FOd6b3J7+/eVRBPmH2+zVu8uNO c0uEwzP1eho/THvIL5UEnmdrOdcxi48oeTb4ACtIgmPjwtlFQMMPpBwNR6rLkB4Y fddk2vbZd6N1R16+nEmKM4B+9CsQf2HgRo5OTbPEKo5iQsss0zzubbauQKCdI+tB 7gQ/eAmUf1LZMuO9hvFUkFwXw75gRvcOpzE5aX3j4fMDNI/iRs6/NaG0+dNzmzJY gzhodHdkc/G+tvxCvHNjwTYuaOMLITVwWl+m4G4Yp/D614yvcvbWMAw60Wp9seM1 qbOb1ELbaBo4+O7E/NnjiDtLMpGDi7GoOlxbzwPfbyd+1VVKfXEPzcMZiBPYCn9M LgZaS47Mw+OE0LDRx8zjrsX8t5AcmpjjmbKrPVBRN1XkszQbfcYSuZoZt2K02Ryf r1r6QuDrzkwvu3bN5V7MN9DlPERyPUnSMDA= =lTkc -----END PGP SIGNATURE----- --==-=-=--