unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
From: Yuan Fu <casouri@gmail.com>
To: Eli Zaretskii <eliz@gnu.org>
Cc: Po Lu <luangruo@yahoo.com>, Jean Louis <bugs@gnu.support>,
	emacs-devel@gnu.org
Subject: Re: Propose to add setup-wizard.el to ELPA
Date: Sun, 9 Jan 2022 14:54:37 -0800	[thread overview]
Message-ID: <64131FC6-A19E-41B5-B636-CD6544140E59@gmail.com> (raw)
In-Reply-To: <83ee5j68z9.fsf@gnu.org>

[-- Attachment #1: Type: text/plain, Size: 145 bytes --]

Ok, I retro-fitted setup-wizard.el to use custom. It works, but more black-boxy and IMO not very pretty. I don’t know if I like it.

Yuan


[-- Attachment #2: setup-wizard.el --]
[-- Type: application/octet-stream, Size: 24358 bytes --]

;;; setup-wizard.el --- Setup wizard  -*- lexical-binding: t; -*-

;; Copyright (C) 2019-2020 Free Software Foundation, Inc.

;; Author: Yuan Fu <casouri@gmail.com>
;; Maintainer: Yuan Fu <casouri@gmail.com>
;; URL: https://github.com/casouri/setup-wizard
;; Version: 1.0.0
;; Keywords: convenience
;; Package-Requires: ((emacs "26.0"))

;; 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 3 of the License, 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.  If not, see <https://www.gnu.org/licenses/>.

;;; Commentary:
;;
;; This package provides a setup wizard that takes a user through an
;; interactive interface, in which he or she can configure key
;; bindings schemes, UI elements, Fonts, packages, etc.

;;; Code:

(require 'widget)
(require 'wid-edit)
(require 'pcase)
(require 'seq)
(require 'cl-lib)

;;; Widgets

(define-widget 'setup-wizard-number-field 'editable-field
  "Editable field but for numbers."
  :valid-regexp
  (rx (seq (? (or "-" "+"))
           (* digit) (? ".") (* digit)
           (? (seq "e" (+ digit)))))
  :value-to-internal
  (lambda (widget val)
    (number-to-string val))
  :value-get
  (lambda (widget)
    (string-to-number (widget-field-value-get widget))))

;;; Custom

(defvar setup-wizard-super-copy-paste-mode-map
  (make-sparse-keymap)
  "Keymap for ‘setup-wizard-super-copy-paste-mode’.")

(define-minor-mode setup-wizard-super-copy-paste-mode
  "Use super as the modifier for cut, copy and paste."
  :global t
  :group 'setup-wizard
  (if setup-wizard-super-copy-paste-mode
      (progn
        (keymap-global-set "s-c" #'kill-ring-save)
        (keymap-global-set "s-x" #'kill-region)
        (keymap-global-set "s-v" #'yank))
    ;; Global map doesn’t have a parent, but using REMOVE is
    ;; semantically correct (see ‘keymap-unset’ for REMOVE).
    (keymap-global-unset "s-c" t)
    (keymap-global-unset "s-x" t)
    (keymap-global-unset "s-v" t)))

(define-minor-mode setup-wizard-linear-undo-mode
  "Use linear undo system."
  :global t
  :group 'setup-wizard
  (if setup-wizard-linear-undo-mode
      (global-set-key [remap undo] #'undo-only)
    (global-unset-key [remap undo])))

(defun setup-wizard--set-magic-variable (symbol value)
  "Magically make VALUE of the magic variable SYMBOL take effect.
If VALUE is nil, do nothing."
  (when value
    (pcase symbol
      ;; Theme.
      ('setup-wizard-theme-magic
       ;; Don’t disable other themes, just load the theme.
       (when (not (eq value 'default))
         (load-theme value)))
      ;; Font.
      ('setup-wizard-font-magic
       (set-face-attribute 'default nil :family value))
      ('setup-wizard-variable-font-magic
       (set-face-attribute 'variable-pitch nil :family value))
      ('setup-wizard-cjk-font
       (dolist (charset '(kana han cjk-misc))
         (set-fontset-font t charset (font-spec :family value))))
      ('setup-wizard-font-size-magic
       (when (> value 0)
         (set-face-attribute
          'variable-pitch nil :height (* 10 value)))))))

(defgroup setup-wizard nil
  "A wizard that helps you setup Emacs."
  :group 'convenience)

(defcustom setup-wizard-theme-magic nil
  "A magic variable that sets themes."
  :type 'string
  :set #'setup-wizard--set-magic-variable)

;; Why not use custom faces?  Custom faces requires you to define the
;; whole face, which isn’t what we want to do here.
(defcustom setup-wizard-font-magic nil
  "A magic variable that sets the default font."
  :type 'string
  :set #'setup-wizard--set-magic-variable)

(defcustom setup-wizard-variable-font-magic nil
  "A magic variable that sets the variable font."
  :type 'string
  :set #'setup-wizard--set-magic-variable)

(defcustom setup-wizard-cjk-font-magic nil
  "A magic variable that sets the CJK font."
  :type 'string
  :set #'setup-wizard--set-magic-variable)

(defcustom setup-wizard-font-size-magic nil
  "A magic variable that sets the font size."
  :type 'integer
  :set #'setup-wizard--set-magic-variable)

(defun setup-wizard--save-option
    (symbol exp &optional now request comment)
  "Save custom option SYMBOL to EXP with NOW, REQUEST and COMMENT.
If EXP is nil, this function is a no-op."
  (custom-set-variables `(,symbol ',exp ,now ,request ,comment))
  (setup-wizard--set-magic-variable symbol exp))

;;; Pages

(defun setup-wizard--char-displayable-p (char)
  "Return non-nil if we can display CHAR."
  ;; Per manual, ‘char-displayable-p’ may return non-nil even when
  ;; there is no font available, since it also checks whether the
  ;; coding system for the text terminal can encode the character.
  ;;
  ;;     ASCII characters are always displayable.
  (cond ((< char 128)
         t)
        ;; Maybe there's a font for it, but we can't put it in the
        ;; buffer.
        ((not enable-multibyte-characters)
         nil)
        (t (when-let ((font-glyph (internal-char-font nil char)))
             (if (consp font-glyph)
		         ;; On a window system, a character is displayable
		         ;; if a font for that character is in the default
		         ;; face of the currently selected frame.
		         (car font-glyph)
		       ;; On a text terminal supporting glyph codes, CHAR is
		       ;; displayable if its glyph code is nonnegative.
		       (<= 0 font-glyph))))))

(defun setup-wizard--insert (&rest args)
  "Insert ARGS and replace emojis if they can’t be displayed."
  (widget-insert
   (mapconcat (lambda (text)
                (if (and (setup-wizard--char-displayable-p ?🧙)
                         (setup-wizard--char-displayable-p ?🧚))
                    text
                  (string-replace
                   "🧚" "Fairy"
                   (string-replace
                    "🧙" "Wizard" text))))
              args)))

;;;; Themes

(defvar setup-wizard--c-demo
  "    #include <stdlib.h>

    struct point
    {
      x: int;
      y: int;
    };

    int main(int arg, int* argv)
    {
      int x = -1;
      int y = 2;
      void *buf = malloc(sizeof(uin32_t));
      return add(x, y) - 3;
    }
"
  "Demo C code.")

(defun setup-wizard--theme-page ()
  "Theme configuration page."
  (setup-wizard--insert
   "🧚: Heya! You are here for help setting up your Emacs, right?
Wizard will be here when you read to the next line.

🧙: Emacs comes with a couple of themes built-in, which are shown
below. You can browse for more themes online or in the package
manager.

🧚: Here are the built-in themes!

Theme preview:\n\n")
  ;; Insert a C demo.
  (widget-insert
   (with-temp-buffer
     (insert setup-wizard--c-demo)
     (c-mode)
     (font-lock-fontify-region (point-min) (point-max))
     (buffer-string)))
  (widget-insert "\n")
  ;; Insert theme selection menu.
  (apply #'widget-create 'radio-button-choice
         :follow-link t
         :value "default"
         ;; Enable the theme when the user selects it.
         :notify (lambda (widget &rest _)
                   ;; First disable other themes.
                   (dolist (theme custom-enabled-themes)
                     (disable-theme theme))
                   ;; Enable the theme.
                   (let* ((theme (intern (widget-value widget))))
                     (setup-wizard--save-option
                      'setup-wizard-theme-magic theme)))
         (cons '(item "default")
               (cl-loop for theme in (custom-available-themes)
                        collect `(item ,(symbol-name theme)))))
  (setup-wizard--insert "\n🧚: Want to ")
  (widget-create
   'push-button
   :notify (lambda (&rest _)
             (package-refresh-contents)
             (list-packages t)
             (goto-char (point-min))
             (let ((inhibit-read-only t))
               (keep-lines "-theme")))
   :value "browse the package manager for themes")
  (widget-insert "?\n"))

;;;; Key binding

(defun setup-wizard--keybinding-page ()
  "Keybinding page."
  (setup-wizard--insert "🧙: This is the notation for modifiers in Emacs:

    C (control)   Ctrl
    M (meta)      Alt/Option
    s (super)     Windows/Command
    S (shift)     Shift

🧚: Which binding scheme do you like?\n\n")
  (widget-create 'radio-button-choice
                 :follow-link t
                 :value "Default"
                 :notify
                 (lambda (widget &rest _)
                   (cua-mode -1)
                   (setup-wizard-super-copy-paste-mode -1)
                   (pcase (widget-value widget)
                     ("Alternative"
                      (setup-wizard--save-option
                       'cua-mode t nil nil
                       "This enables the Alternative binding scheme"))
                     ("Utilize the super key"
                      (setup-wizard--save-option
                       'setup-wizard-super-copy-paste-mode t))))
                 '(item :value "Default"
                        :format "%v\n\n%d\n"
                        :doc "    M-w           Copy
    C-w           Cut
    C-y           Paste")
                 '(item :value "Alternative"
                        :format "%v\n\n%d\n"
                        :doc "    C-c           Copy
    C-x           Cut
    C-v           Paste")
                 '(item :value "Utilize the super key"
                        :format "%v\n\n%d\n"
                        :doc "    s-c           Copy
    s-x           Cut
    s-v           Paste"))
  (setup-wizard--insert
   "\n🧙: In the alternative binding scheme, the binding for copy
and cut only take effect when some text is selected. So when
nothing is selected, they are still normal prefix keys.\n"))

;;;; UI features

(defun setup-wizard--ui-features-page ()
  "UI features page."
  (setup-wizard--insert "🧚: What UI elements do you like?\n\n")
  ;; Line numbers.
  (widget-create 'checkbox
                 :notify
                 (lambda (widget &rest _)
                   (let ((val (widget-value widget)))
                     (setup-wizard--save-option
                      'global-display-line-numbers-mode val)))
                 :value global-display-line-numbers-mode)
  (widget-insert " Line numbers.\n")
  ;; Thin cursor.
  (widget-create 'checkbox
                 :notify
                 (lambda (widget &rest _)
                   (let ((val (widget-value widget)))
                     (setup-wizard--save-option
                      'cursor-type (if val 'bar t))))
                 :value (eq cursor-type 'bar))
  (widget-insert " Thin cursor bar.\n")
  ;; Blink cursor.
  (widget-create 'checkbox
                 :notify
                 (lambda (widget &rest _)
                   (let ((val (widget-value widget)))
                     (setup-wizard--save-option
                      'blink-cursor-mode val)))
                 :value blink-cursor-mode)
  (widget-insert " Blink cursor.\n")
  ;; ‘hl-line’.
  (widget-create 'checkbox
                 :notify
                 (lambda (widget &rest _)
                   (let ((val (widget-value widget)))
                     (setup-wizard--save-option
                      'global-hl-line-mode val)))
                 :value global-hl-line-mode)
  (widget-insert " Highlight current line.\n")
  ;; Tool bar.
  (widget-create 'checkbox
                 :notify
                 (lambda (widget &rest _)
                   (let ((val (widget-value widget)))
                     (setup-wizard--save-option
                      'tool-bar-mode val)))
                 :value tool-bar-mode)
  (widget-insert " Tool bar.\n")
  ;; Menu bar.
  (widget-create 'checkbox
                 :notify
                 (lambda (widget &rest _)
                   (let ((val (widget-value widget)))
                     (setup-wizard--save-option
                      'menu-bar-mode val)))
                 :value menu-bar-mode)
  (widget-insert " Menu bar.\n")
  ;; Scroll bar.
  (widget-create 'checkbox
                 :notify
                 (lambda (widget &rest _)
                   (let ((val (widget-value widget)))
                     (setup-wizard--save-option
                      'scroll-bar-mode val)))
                 :value scroll-bar-mode)
  (widget-insert " Scroll bar.\n")
  ;; Tab width
  (let ((width (widget-create 'setup-wizard-number-field
                              :size 2
                              :value tab-width
                              :format "%v Tab width ")))
    (widget-create 'push-button
                   :value "Apply"
                   :notify (lambda (&rest _)
                             (let ((val (widget-value width)))
                               (unless (eq val 0)
                                 (setup-wizard--save-option
                                  'tab-width val)))))
    (widget-insert "\n"))

  ;; Font.
  (widget-insert "\n")
  (let* (default-font
         variable-font
         cjk-font
         font-size
         action
         (phrase "The quick brown fox jumps over the lazy dog.\n"))
    (widget-insert "Font preview:\n\n")
    (widget-insert "    " phrase)
    (widget-insert "    " (propertize phrase 'face 'variable-pitch))
    (widget-insert "    大漠孤烟直,长河落日圆。射は正しきを己に求む。\n\n")
    (setq default-font
          (widget-create 'editable-field
                         :size 20
                         :value ""
                         :format "Default font: %v \n"))
    (setq variable-font
          (widget-create 'editable-field
                         :size 20
                         :value ""
                         :format "Variable-pitch font: %v \n"))
    (setq cjk-font
          (widget-create 'editable-field
                         :size 20
                         :value ""
                         :format "CJK font: %v \n"))
    (setq font-size
          (widget-create 'setup-wizard-number-field
                         :size 2
                         :value 0
                         :format "Font size: %v \n\n"))
    (setq action
          (lambda (&rest _)
            (let* ((default-font (widget-value default-font))
                   (variable-font (widget-value variable-font))
                   (cjk-font (widget-value cjk-font))
                   (font-size (widget-value font-size)))
              (unless (equal default-font "")
                (setup-wizard--save-option
                 'setup-wizard-font-magic default-font))
              (unless (equal variable-font "")
                (setup-wizard--save-option
                 'setup-wizard-variable-font-magic variable-font))
              (unless (equal cjk-font "")
                (setup-wizard--save-option
                 'setup-wizard-cjk-font-magic cjk-font))
              (unless (<= font-size 0)
                (setup-wizard--save-option
                 'setup-wizard-font-size-magic font-size)))))
    (widget-create 'push-button
                   :value "Apply font settings"
                   :notify action)
    (widget-insert "\n")))

;;;; Undo

(defun setup-wizard--undo-page ()
  "Undo page."
  (setup-wizard--insert
   "🧙: Emacs has a powerful (but probably unintuitive) undo system,
where undo operations themselves are recorded in the undo
history, and redo is done by undoing an previous undo operation.

🧚: Which undo system do you like?\n\n")
  (widget-create 'radio-button-choice
                 :value "Default"
                 :follow-lint t
                 :notify (lambda (widget &rest _)
                           (let ((val (widget-value widget)))
                             (pcase val
                               ("Linear"
                                (setup-wizard--save-option
                                 'setup-wizard-linear-undo-mode t))
                               ("Default"
                                (setup-wizard--save-option
                                 'setup-wizard-linear-undo-mode nil)))))
                 '(item :value "Default"
                        :format "%v\n\n%d\n"
                        :doc "    One undo rules them all")
                 '(item :value "Linear"
                        :format "%v\n\n%d\n"
                        :doc "    Undo and redo")))

;;;; Extra package

(defun setup-wizard--package-activate (package)
  "Install and activate PACKAGE."
  (require 'package)
  (unless (package-installed-p package)
    (package-install package))
  (package-activate package)
  (require package))

(defun setup-wizard--package-page ()
  "Extra package page."
  (setup-wizard--insert
   "🧙: Here are some packages that I always install:

(🧚: They will be automatically installed from Internet. That
might take a while!)\n\n")
  ;; Ivy.
  (widget-create 'checkbox
                 :notify
                 (lambda (widget &rest _)
                   (let ((val (widget-value widget)))
                     (setup-wizard--package-activate 'ivy)
                     (setup-wizard--package-activate 'counsel)
                     (custom-set-variables
                      `(enable-recursive-minibuffers
                        ,val nil nil "Recommended by Wizard for ivy.")
                      `(ivy-use-selectable-prompt
                        ,val nil nil "Recommended by Wizard for ivy")
                      `(ivy-use-virtual-buffers
                        ,val nil nil "Recommended by Wizard for ivy"))
                     (setup-wizard--save-option 'ivy-mode val)
                     (setup-wizard--save-option
                      'counsel-mode val nil nil
                      "Recommended by Wizard for ivy")))
                 :value (bound-and-true-p ivy-mode))
  (widget-insert
   " Ivy: A completion package that makes typing file names, buffer
names, commands, etc so much easier.\n")
  ;; Company
  (widget-create 'checkbox
                 :notify
                 (lambda (widget &rest _)
                   (let ((val (widget-value widget)))
                     (setup-wizard--package-activate 'company)
                     (setup-wizard--save-option 'company-mode val)))
                 :value (bound-and-true-p company-mode))
  (widget-insert
   " Company: Popup completion menu when writing programs.\n")
  (setup-wizard--insert
   "🧙: Here are some built-in packages that I always enable:\n\n")
  ;; Electric-pair.
  (widget-create 'checkbox
                 :notify
                 (lambda (widget &rest _)
                   (let ((val (widget-value widget)))
                     (setup-wizard--save-option
                      'electric-pair-mode val)))
                 :value electric-pair-mode)
  (widget-insert
   " Electric-pair-mode: Automatically closes parenthesis\n")
  (setup-wizard--insert "\n🧙: ...\n\n")
  (setup-wizard--insert "🧙: I don’t use many packages.\n"))

;;; The wizard framework

(defun setup-wizard--with-boilerplate
    (setup-fn &optional page-list finish-fn)
  "Call page setup function SETUP-FN with widget boilerplate.
PAGE-LIST is a list of setup function for pages to show in a
series. FINISH-FN is called when user clicks the finish button.
If PAGE-LIST or FINISH-FN are nil, don’t insert navigation
buttons."
  (kill-all-local-variables)
  (let ((inhibit-read-only t))
    (erase-buffer))
  (remove-overlays)
  (funcall setup-fn)
  (widget-insert "\n")
  (when (and page-list finish-fn)
    (setup-wizard--insert-step-buttons setup-fn page-list finish-fn))
  (use-local-map widget-keymap)
  (widget-setup)
  (goto-char (point-min))
  (local-set-key (kbd "q") #'setup-wizard--quit))

(defun setup-wizard--quit (&rest _)
  "Quite the wizard."
  (interactive)
  (kill-buffer)
  (message (with-temp-buffer
             (setup-wizard--insert "🧚: See ya!")
             (buffer-string))))

(defun setup-wizard--insert-step-buttons (page page-list finish-fn)
  "Insert buttons that go to previous and next page of PAGE.
PAGE-LIST is a list of setup function for pages to show in a series.
Insert a Button that calls FINISH-FN at the last page."
  (let* ((idx (seq-position page-list page))
         (previous-page (if (eq idx 0) nil
                          (nth (1- idx) page-list)))
         (next-page (nth (1+ idx) page-list)))
    (setup-wizard--insert
     (format "🧚: We are at step %s/%s, what’s next? "
             (1+ idx) (length page-list)))
    (when previous-page
      (widget-create
       'push-button
       :notify (lambda (&rest _)
                 (setup-wizard--with-boilerplate
                  previous-page page-list finish-fn))
       :value "Back"))
    (widget-insert " ")
    (if next-page
        (widget-create
         'push-button
         :notify (lambda (&rest _)
                   (setup-wizard--with-boilerplate
                    next-page page-list finish-fn))
         :value "Next")
      (widget-create
       'push-button
       :notify (lambda (&rest _) (funcall finish-fn))
       :value "Finish"))
    (widget-insert " ")
    (widget-create
     'push-button
     :value "Quit"
     :notify #'setup-wizard--quit)
    (widget-insert "\n")))

(defun setup-wizard--finish ()
  "The default finish function.
Constructs the config and display them."
  (setup-wizard--with-boilerplate
   (lambda ()
     (custom-save-all)
     (setup-wizard--insert
      "🧚: All done! Enjoy Emacs!\n"))))

(defvar setup-wizard--pages '(setup-wizard--theme-page
                              setup-wizard--keybinding-page
                              setup-wizard--ui-features-page
                              setup-wizard--undo-page
                              setup-wizard--package-page)
  "A list of page functions.")

(defun setup-wizard ()
  "Run the setup wizard."
  (interactive)
  (switch-to-buffer (get-buffer-create "*mage tower*"))
  (let ((page-list setup-wizard--pages))
    (setup-wizard--with-boilerplate
     (car page-list) page-list
     #'setup-wizard--finish)))

;;; Backport

(unless (fboundp 'undo--last-change-was-undo-p)
  (defun undo--last-change-was-undo-p (undo-list)
    (while (and (consp undo-list) (eq (car undo-list) nil))
      (setq undo-list (cdr undo-list)))
    (gethash undo-list undo-equiv-table)))

(unless (fboundp 'undo-redo)
  (defun undo-redo (&optional arg)
    "Undo the last ARG undos."
    (interactive "*p")
    (cond
     ((not (undo--last-change-was-undo-p buffer-undo-list))
      (user-error "No undo to undo"))
     (t
      (let* ((ul buffer-undo-list)
             (new-ul
              (let ((undo-in-progress t))
                (while (and (consp ul) (eq (car ul) nil))
                  (setq ul (cdr ul)))
                (primitive-undo arg ul)))
             (new-pul (undo--last-change-was-undo-p new-ul)))
        (message "Redo%s" (if undo-in-region " in region" ""))
        (setq this-command 'undo)
        (setq pending-undo-list new-pul)
        (setq buffer-undo-list new-ul))))))

(unless (fboundp 'undo-only)
  (defun undo-only (&optional arg)
    "Undo some previous changes.
Repeat this command to undo more changes.
A numeric ARG serves as a repeat count.
Contrary to `undo', this will not redo a previous undo."
    (interactive "*p")
    (let ((undo-no-redo t)) (undo arg))))

(provide 'setup-wizard)

;;; setup-wizard.el ends here

;; Local Variables:
;; sentence-end-double-space: t
;; End:

  reply	other threads:[~2022-01-09 22:54 UTC|newest]

Thread overview: 119+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-01-02  2:07 Propose to add setup-wizard.el to ELPA Yuan Fu
2022-01-02  2:37 ` Po Lu
2022-01-02  3:02   ` Yuan Fu
2022-01-02  3:22     ` Po Lu
2022-01-02  5:51       ` Yuan Fu
2022-01-02  6:30         ` Po Lu
2022-01-02  7:58           ` Yuan Fu
2022-01-02  8:07             ` Po Lu
2022-01-02  9:07               ` Yuan Fu
2022-01-02  9:22                 ` xenodasein--- via Emacs development discussions.
2022-01-02  9:45                   ` Eduardo Ochs
2022-01-02  9:45                   ` Po Lu
2022-01-02 10:09                     ` Eduardo Ochs
2022-01-02 10:15                       ` Po Lu
2022-01-02 10:25                         ` Eduardo Ochs
2022-01-02 10:34                           ` xenodasein--- via Emacs development discussions.
2022-01-02 10:52                             ` Eli Zaretskii
2022-01-02 10:57                               ` xenodasein--- via Emacs development discussions.
2022-01-02 11:14                                 ` Eli Zaretskii
2022-01-02 11:30                                   ` xenodasein--- via Emacs development discussions.
2022-01-02 11:38                                     ` Eli Zaretskii
2022-01-02 12:01                                     ` Po Lu
2022-01-02 11:31                                   ` xenodasein--- via Emacs development discussions.
     [not found]                             ` <CADs++6jtFBah1hhsuN6T_-kFyjc_pNmmVKA+16vOWa8OctOZLw@mail.gmail.com>
2022-01-02 11:02                               ` xenodasein--- via Emacs development discussions.
2022-01-02 11:17                             ` Po Lu
2022-01-02 11:36                               ` xenodasein--- via Emacs development discussions.
2022-01-02 12:03                                 ` Po Lu
2022-01-02 15:27                                 ` Stefan Kangas
     [not found]                               ` <MsPZqa9--3-2@tutanota.de-MsP_1xO----2>
2022-01-02 11:57                                 ` xenodasein--- via Emacs development discussions.
2022-01-02 12:05                                   ` Po Lu
2022-01-02 15:27                                   ` Stefan Kangas
2022-01-02 15:37                                     ` Eli Zaretskii
2022-01-02 16:43                                       ` xenodasein--- via Emacs development discussions.
2022-01-02 17:32                                         ` Stefan Kangas
2022-01-02 18:51                                         ` FW: [External] : " Drew Adams
2022-01-02 19:07                                           ` xenodasein--- via Emacs development discussions.
2022-01-02 21:29                                             ` Drew Adams
2022-01-02 22:14                                               ` Stefan Kangas
2022-01-03  6:42                                                 ` Sean Whitton
2022-01-03  7:02                                                   ` Stefan Kangas
2022-01-03  8:19                                                     ` xenodasein--- via Emacs development discussions.
2022-01-03  9:27                                                       ` Po Lu
2022-01-03  9:55                                                         ` xenodasein--- via Emacs development discussions.
2022-01-03 10:10                                                           ` Po Lu
2022-01-03 10:21                                                             ` xenodasein--- via Emacs development discussions.
2022-01-03 10:53                                                               ` Po Lu
2022-01-03 11:07                                                                 ` xenodasein--- via Emacs development discussions.
2022-01-03 11:25                                                                   ` Po Lu
2022-01-03 11:32                                                                     ` xenodasein--- via Emacs development discussions.
2022-01-03 12:13                                                                       ` Po Lu
2022-01-03 12:20                                                                         ` xenodasein--- via Emacs development discussions.
2022-01-03 12:32                                                                           ` Po Lu
2022-01-03 12:44                                                                             ` xenodasein--- via Emacs development discussions.
2022-01-03 12:55                                                                               ` Po Lu
2022-01-03 13:24                                                                                 ` xenodasein--- via Emacs development discussions.
2022-01-03 15:15                                                                                 ` xenodasein--- via Emacs development discussions.
2022-01-03 16:04                                                       ` Drew Adams
2022-01-04 21:19                                                     ` Sean Whitton
2022-01-04 21:28                                                       ` Drew Adams
2022-01-04 22:38                                                         ` Sean Whitton
2022-01-04 22:51                                                           ` Drew Adams
2022-01-05  5:28                                                         ` tomas
2022-01-05  7:43                                                           ` Drew Adams
2022-01-05  8:13                                                             ` tomas
2022-01-07 10:34                                                     ` Jean Louis
2022-01-03 16:03                                                   ` Drew Adams
2022-01-03 16:05                                                   ` Stefan Monnier
2022-01-04  1:50                                                     ` Yuan Fu
2022-01-04  2:53                                                       ` Po Lu
2022-01-04  4:13                                                       ` Stefan Monnier
2022-01-04  4:30                                                         ` Yuan Fu
2022-01-04  6:10                                                           ` Stefan Monnier
2022-01-04 15:04                                                       ` Lars Ingebrigtsen
2022-01-04 21:25                                                         ` Sean Whitton
2022-01-05  0:58                                                           ` Po Lu
2022-01-05 15:35                                                           ` Lars Ingebrigtsen
2022-01-06  6:32                                                             ` Sean Whitton
2022-01-03  0:42                                         ` Po Lu
2022-01-02 18:47                                       ` [External] : " Drew Adams
2022-01-02 11:58                             ` Philip Kaludercic
2022-01-07 10:09                     ` Jean Louis
2022-01-02 18:47                   ` [External] : " Drew Adams
2022-01-02  9:41                 ` Po Lu
2022-01-02 17:18                   ` Yuan Fu
2022-01-02 18:47                     ` [External] : " Drew Adams
2022-01-07 10:02               ` Jean Louis
2022-01-07 10:50                 ` Po Lu
2022-01-07 12:11                 ` Eli Zaretskii
2022-01-09 22:54                   ` Yuan Fu [this message]
2022-01-10  4:15                   ` Jean Louis
2022-01-10 15:45                     ` [External] : " Drew Adams
2022-01-10 17:24                     ` Eli Zaretskii
2022-01-11  4:47                       ` Jean Louis
2022-01-11  4:51                     ` Richard Stallman
2022-01-02  7:55 ` Eli Zaretskii
2022-01-02  8:07   ` Yuan Fu
2022-01-02 15:42     ` Stefan Kangas
2022-01-02 17:26       ` Yuan Fu
2022-01-02 17:36         ` xenodasein--- via Emacs development discussions.
     [not found]         ` <MsQrOAf--J-2@tutanota.de-MsQrQR2----2>
2022-01-02 17:55           ` xenodasein--- via Emacs development discussions.
2022-01-02 18:50         ` Stefan Kangas
2022-01-02 21:14           ` Yuan Fu
2022-01-03  0:45             ` Po Lu
2022-01-03  0:59               ` Yuan Fu
2022-01-03  1:02             ` Stefan Kangas
2022-01-03  9:12             ` Joost Kremers
2022-01-03 12:49               ` Eli Zaretskii
2022-01-03 13:00                 ` Po Lu
2022-01-03 19:30                 ` Joost Kremers
2022-01-02  8:07   ` Po Lu
2022-01-02 15:23     ` nanjunjie
2022-01-03  8:28       ` Philip Kaludercic
2022-01-04 16:09         ` Nan JunJie
2022-01-04 19:45           ` Philip Kaludercic
2022-01-02 12:02 ` Philip Kaludercic
2022-01-07  9:58 ` Jean Louis
  -- strict thread matches above, loose matches on Subject: below --
2022-01-02 15:46 Simon Pugnet
2022-01-02 17:26 Simon Pugnet
2022-01-02 18:49 ` Stefan Kangas

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=64131FC6-A19E-41B5-B636-CD6544140E59@gmail.com \
    --to=casouri@gmail.com \
    --cc=bugs@gnu.support \
    --cc=eliz@gnu.org \
    --cc=emacs-devel@gnu.org \
    --cc=luangruo@yahoo.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).