unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
From: Katsumi Yamaoka <yamaoka@jpl.org>
To: Eli Zaretskii <eliz@gnu.org>
Cc: Lars Ingebrigtsen <larsi@gnus.org>, 28907@debbugs.gnu.org
Subject: bug#28907: 26.0.90; [eww] some problems in input/textarea
Date: Fri, 10 Nov 2017 16:57:23 +0900	[thread overview]
Message-ID: <b4mfu9mbm70.fsf@jpl.org> (raw)
In-Reply-To: <b4mefpy2oxq.fsf@jpl.org>

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

On Thu, 02 Nov 2017 16:39:53 +0900, Katsumi Yamaoka wrote:
> On Mon, 30 Oct 2017 08:30:39 +0900, Katsumi Yamaoka wrote:
>> On Fri, 27 Oct 2017 16:31:49 +0300, Eli Zaretskii wrote:
>>>> Date: Fri, 20 Oct 2017 17:39:29 +0900
>>>> From: Katsumi Yamaoka <yamaoka@jpl.org>

>>>> There are some problems with an input form and a textarea as
>>>> follows:

>>>> ・Can't enter text at the beginnig of input/textarea if there is
>>>>   a link just above the form.
>>>> ・Can't enter space at (1- eol).
>>>> ・Can't kill a line.
>>>> ・Can't undo.
>>>> ・Can't retrieve the response for the submit in a certain site.
>>>> ・Padding width gets incorrect if there is a wide character.
>>>> ・A major mode command like `g' doesn't work at the right outside
>>>>   of textarea.

[...]

Some generic editing commands, except for `undo', now almost work
in input/textarea.  To try writing something in those fields, you
can use the following two pages:

<https://html.com/tags/input/#Code_Example>
<https://html.com/tags/textarea/#Code_Example>

A patch is below.

* lisp/net/eww.el (eww-preprocess-text-input): New function that
calculates changed length based on string width, not characters.
(eww-render): Add it to before-change-functions.
(eww-tag-a): Make keymap text property non-sticky.
(eww-text-map, eww-textarea-map): Remap some generic editing keys.
(eww-beginning-of-text, eww-end-of-text): Work on textarea as well.
(eww-field-extract-text, eww-field-uniline-text, eww-field-insert-text)
(eww-field-funcall): New functions.
(eww-field-backward-delete-char-untabify)
(eww-field-delete-backward-char, eww-field-delete-char)
(eww-field-kill-line, eww-field-kill-region, eww-field-newline)
(eww-field-open-line, eww-field-yank, eww-field-yank-pop): New commands.
(eww-form-text): Pass field width to eww-form property.
(eww-field-replace-length): New internal variable.
(eww-process-text-input): Use string width based changed length;
enable a user to enter space at (1- eol);
don't break the form when killing a line at the beginning of the form.
(eww-tag-textarea): Treat textarea's text as its value if it is null;
work the padding correctly when there is a wide character;
make keymap prop non-sticky;
pass field width and height to eww-form property.
(eww-size-text-inputs): Make the field end position a marker.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: Type: text/x-patch, Size: 19527 bytes --]

--- eww.el~	2017-09-14 22:06:50.000000000 +0000
+++ eww.el	2017-11-10 07:54:06.465612900 +0000
@@ -397,7 +397,9 @@
 	    (setq eww-history-position 0)
 	    (and last-coding-system-used
 		 (set-buffer-file-coding-system last-coding-system-used))
-	    (run-hooks 'eww-after-render-hook)))
+	    (run-hooks 'eww-after-render-hook)
+	    (add-hook 'before-change-functions
+		      'eww-preprocess-text-input nil t)))
       (kill-buffer data-buffer))))
 
 (defun eww-parse-headers ()
@@ -546,7 +548,8 @@
   (eww-handle-link dom)
   (let ((start (point)))
     (shr-tag-a dom)
-    (put-text-property start (point) 'keymap eww-link-keymap)))
+    (put-text-property start (point) 'keymap eww-link-keymap)
+    (put-text-property start (point) 'rear-nonsticky '(keymap))))
 
 (defun eww-update-header-line-format ()
   (setq header-line-format
@@ -955,17 +958,29 @@
     (define-key map [(control a)] 'eww-beginning-of-text)
     (define-key map [(control c) (control c)] 'eww-submit)
     (define-key map [(control e)] 'eww-end-of-text)
+    (define-key map [(control j)] 'eww-submit)
     (define-key map [?\t] 'shr-next-link)
     (define-key map [?\M-\t] 'shr-previous-link)
+    (dolist (cmd '(backward-delete-char-untabify
+		   delete-backward-char delete-char
+		   kill-line kill-region yank yank-pop))
+      (define-key map `[remap ,cmd] (intern (format "eww-field-%s" cmd))))
+    (define-key map [remap open-line] 'ignore)
     map))
 
 (defvar eww-textarea-map
   (let ((map (make-keymap)))
     (set-keymap-parent map text-mode-map)
-    (define-key map "\r" 'forward-line)
+    (define-key map "\r" 'eww-field-newline)
+    (define-key map [(control a)] 'eww-beginning-of-text)
     (define-key map [(control c) (control c)] 'eww-submit)
+    (define-key map [(control e)] 'eww-end-of-text)
     (define-key map [?\t] 'shr-next-link)
     (define-key map [?\M-\t] 'shr-previous-link)
+    (dolist (cmd '(backward-delete-char-untabify
+		   delete-backward-char delete-char
+		   kill-line kill-region open-line yank yank-pop))
+      (define-key map `[remap ,cmd] (intern (format "eww-field-%s" cmd))))
     map))
 
 (defvar eww-select-map
@@ -975,20 +990,343 @@
     map))
 
 (defun eww-beginning-of-text ()
-  "Move to the start of the input field."
+  "Move to the beginning of the current line in the input field."
   (interactive)
-  (goto-char (eww-beginning-of-field)))
+  (beginning-of-line)
+  (goto-char (text-property-not-all (point) (line-end-position)
+				    'inhibit-read-only nil)))
 
 (defun eww-end-of-text ()
-  "Move to the end of the text in the input field."
+  "Move to the end of the text of the current line in the input field.
+When the point is already in the end of the text, move to the end of
+the current line."
   (interactive)
-  (goto-char (eww-end-of-field))
-  (let ((start (eww-beginning-of-field)))
-    (while (and (equal (following-char) ? )
-		(> (point) start))
-      (forward-char -1))
-    (when (> (point) start)
-      (forward-char 1))))
+  (let ((end (or (text-property-any (point) (line-end-position)
+				    'inhibit-read-only nil)
+		 (line-end-position))))
+    (unless (prog1
+		(and (looking-at " *") (>= (match-end 0) end))
+	      (goto-char (if (get-text-property end 'inhibit-read-only)
+			     end (1- end))))
+      (skip-chars-backward " "))))
+
+(defun eww-field-extract-text ()
+  "Return the contents of the input/textarea field where the point is.
+The contents will be divided into a list of two (or three) parts by
+the mark (if exists as either active or inactive in the field) and
+the current position, and returned as the form:
+
+(FLAG (\"TEXT\" ...) (\"TEXT\" ...) ...)
+
+Where FLAG will be non-nil if the mark is behind the current position.
+Each part is a list of text lines; text lines may be nil that means
+a null text; a text line does not end with a newline; assume that
+there is a newline between adjacent text lines."
+  (let* ((form (get-text-property (point) 'eww-form))
+	 (start (or (cdr (assq :start form)) (point-min)))
+	 (end (or (cdr (assq :end form)) (point-max)))
+	 (mk (mark t))
+	 (pos (point))
+	 (from start)
+	 swap opos boundary bound to lines parts)
+    (if (and mk (>= mk start) (<= mk end))
+	(when (setq swap (> mk pos))
+	  (setq mk (prog1 (setq opos pos) (setq pos mk))))
+      (setq mk nil))
+    (setq boundary (or mk pos))
+    (while (< from end)
+      (if (= from boundary)
+	  (progn
+	    (push '(nil) parts)
+	    (if mk
+		(setq mk nil
+		      boundary pos)
+	      (setq boundary end)))
+	(goto-char from)
+	(setq bound (min boundary (line-end-position))
+	      to (or (and form
+			  (text-property-any from bound 'inhibit-read-only nil))
+		     bound))
+	(push (buffer-substring-no-properties from to) lines)
+	(when (or (= to boundary)
+		  (not (setq from (if form
+				      (text-property-not-all
+				       (1+ to) boundary 'inhibit-read-only nil)
+				    (forward-line 1)
+				    (and (bolp) (< (point) boundary)
+					 (point))))))
+	  (goto-char boundary)
+	  (when (or (bolp)
+		    (and form
+			 (not (get-text-property (1- boundary)
+						 'inhibit-read-only))))
+	    (push "" lines))
+	  (push (nreverse lines) parts)
+	  (setq lines nil
+		from boundary)
+	  (if mk
+	      (setq mk nil
+		    boundary pos)
+	    (setq boundary end)))))
+    (goto-char (or opos pos))
+    (if parts
+	(cons swap (if (= pos end)
+		       (nconc (nreverse parts) '((nil)))
+		     (nreverse parts)))
+      `(,swap (nil) (nil) (nil)))))
+
+(defun eww-field-uniline-text ()
+  "Extract text from the current temporary buffer excluding newlines."
+  (let ((pos (point))
+	parts)
+    (while (re-search-forward "\\([\t ]+\\)\n+\\|\n+\\([\t ]+\\)" nil t)
+      (replace-match "\\1\\2"))
+    (goto-char pos)
+    (while (re-search-forward "\n+" nil 'move)
+      (replace-match " "))
+    (skip-chars-backward "\t ")
+    (setq parts (list (list (buffer-substring pos (point)))))
+    (delete-region pos (point-max))
+    (when (setq pos (mark t))
+      (goto-char pos)
+      (while (re-search-forward "\\([\t ]+\\)\n+\\|\n+\\([\t ]+\\)" nil t)
+	(replace-match "\\1\\2"))
+      (goto-char pos)
+      (while (re-search-forward "\n+" nil t)
+	(replace-match " "))
+      (push (list (buffer-substring pos (point-max))) parts)
+      (delete-region pos (point-max)))
+    (goto-char (point-min))
+    (while (re-search-forward "\\([\t ]+\\)\n+\\|\n+\\([\t ]+\\)" nil t)
+      (replace-match "\\1\\2"))
+    (goto-char (point-min))
+    (while (re-search-forward "\n+" nil t)
+      (replace-match " "))
+    (cons (list (buffer-string)) parts)))
+
+(defun eww-field-insert-text (parts &optional swap-point-and-mark)
+  "Insert PARTS, a list of lists of text lines, in the current buffer.
+Put an inactive mark at the beginning of the second part if there are
+tree parts.  Position point at the beginning of the last part.  If
+SWAP-POINT-AND-MARK is non-nil, the point and the mark will be swapped."
+  (let* ((form (get-text-property (point) 'eww-form))
+	 (textareap (equal (plist-get form :type) "textarea"))
+	 (start (cdr (assq :start form)))
+	 (end (cdr (assq :end form)))
+	 mk pos)
+    (if form ;; We are in an eww buffer.
+	(let ((properties (text-properties-at start))
+	      (width (plist-get form :width))
+	      (inhibit-read-only t)
+	      (inhibit-modification-hooks t)
+	      indent lines line from to len)
+	  (unless textareap
+	    (with-temp-buffer
+	      (eww-field-insert-text parts)
+	      (setq parts (eww-field-uniline-text))))
+	  (goto-char start)
+	  (setq indent (current-column))
+	  (while (< (point) end)
+	    (if parts
+		(while (setq lines (pop parts))
+		  (while lines
+		    ;; We are in the beginning of the text line.
+		    (when (setq line (pop lines))
+		      (setq from (point))
+		      (goto-char (or (text-property-any from (line-end-position)
+							'inhibit-read-only nil)
+				     (line-end-position)))
+		      (setq to (cons (current-column) (point-marker)))
+		      (goto-char from)
+		      (unless (equal line "")
+			(insert-before-markers line)
+			(set-text-properties from (point) properties)
+			(setq from (point)))
+		      (unless (or textareap (eq (char-before) ? ))
+			(insert-before-markers " ")
+			(set-text-properties from (point) properties))
+		      (when (> (setq len (- width (current-column) indent)) 0)
+			(set-text-properties
+			 (point) (progn
+				   (insert-before-markers (make-string len ? ))
+				   (point))
+			 properties))
+		      (delete-region (point) (cdr to))
+		      (when (and textareap (eolp))
+			(set-text-properties (point) (1+ (point)) properties))
+		      (if lines
+			  (if (or (= (point) end)
+				  (progn
+				    (forward-line 1)
+				    (>= (point) end)))
+			      (progn
+				(setq from (point))
+				(insert-before-markers
+				 (make-string (car to) ? )
+				 (if (memq (char-after (cdr to)) '(nil ?\n))
+				     "\n" ""))
+				(set-text-properties from (point) properties)
+				(forward-char -1)
+				(move-to-column indent))
+			    (move-to-column indent))
+			(goto-char from)
+			(unless (or (not textareap)
+				    (bolp)
+				    (not (get-text-property
+					  (1- from) 'inhibit-read-only)))
+			  (forward-line 1)
+			  (when (>= (point) end)
+			    (goto-char end)
+			    (insert (make-string (car to) ? ) "\n")
+			    (set-text-properties end (point) properties)
+			    (set-marker end (point)))
+			  (goto-char from)))
+		      (set-marker (cdr to) nil)))
+		  (cond ((cdr parts) (setq mk (point)))
+			(parts (setq pos (point)))))
+	      (setq from (point)) ;; The end of the last text line.
+	      (goto-char (or (text-property-any from (line-end-position)
+						'inhibit-read-only nil)
+			     (line-end-position)))
+	      (setq to (cons (current-column) (point-marker)))
+	      (if textareap
+		  (progn
+		    (goto-char from)
+		    (insert-before-markers
+		     (make-string (max 0 (- (car to) (current-column))) ? ))
+		    (set-text-properties from (point) properties)
+		    (delete-region (point) (cdr to))
+		    (when (eolp)
+		      (set-text-properties (point) (1+ (point)) properties))
+		    (forward-line 1)
+		    (when (< (point) end)
+		      (move-to-column indent)))
+		(skip-chars-backward " " start)
+		(when (>= (setq len (- width
+				       (string-width
+					(buffer-substring start (point)))))
+			  0)
+		  (forward-char len)
+		  (delete-region (point) (cdr to)))
+		(goto-char (cdr to))
+		(unless (eq (char-before) ? )
+		  (insert-before-markers " ")
+		  (set-text-properties (1- (point)) (point) properties)))
+	      (set-marker (cdr to) nil)))
+	  ;; We are in `end' that is the end of the textarea.
+	  (when (and textareap
+		     (setq lines (plist-get form :lines))
+		     (progn
+		       (goto-char pos)
+		       (forward-line 1)
+		       (prog1
+			   (< (point) end)
+			 (goto-char end)))
+		     (< (setq lines (- lines (count-lines start end))) 0))
+	    (forward-line lines)
+	    (when (re-search-forward "\\(?:[^\n ]+[\n ]+\\)*[^\n ]+" end t)
+	      (forward-line 1))
+	    (delete-region (point) end)))
+      ;; We are in a temporary buffer.
+      (while parts
+	(insert (mapconcat #'identity (pop parts) "\n"))
+	(cond ((cdr parts) (setq mk (point)))
+	      (parts (setq pos (point))))))
+    (when mk
+      (when swap-point-and-mark
+	(setq mk (prog1 pos (setq pos mk))))
+      (goto-char mk)
+      (push-mark))
+    (goto-char (if end (min pos (1- end)) pos))))
+
+(defun eww-field-funcall (function &rest args)
+  "Run FUNCTION on the copied field and replace the field with the result.
+ARGS is a list of arguments that will be passed to FUNCTION."
+  (let* ((parts (eww-field-extract-text))
+	 (swap (pop parts))
+	 pos)
+    (unwind-protect
+	(with-temp-buffer
+	  (eww-field-insert-text parts swap)
+	  (setq pos (point-marker))
+	  (goto-char (point-min))
+	  (while (re-search-forward " +$" pos t)
+	    (replace-match ""))
+	  (goto-char pos)
+	  (while (re-search-forward " +$" nil t)
+	    (replace-match ""))
+	  (goto-char pos)
+	  (set-marker pos nil)
+	  (unwind-protect
+	      (apply function args)
+	    (setq pos (point))
+	    (goto-char (point-max))
+	    (skip-chars-backward "\n " pos)
+	    (delete-region (point) (point-max))
+	    (goto-char pos)
+	    (setq parts (cdr (eww-field-extract-text)))))
+      (eww-field-insert-text parts swap)
+      (deactivate-mark))))
+
+(defun eww-field-backward-delete-char-untabify (arg &optional killp)
+  "Delete characters backward, changing tabs into spaces.
+See `backward-delete-char-untabify' for more information."
+  (interactive "*p\nP")
+  (eww-field-funcall #'backward-delete-char-untabify arg killp))
+
+(defun eww-field-delete-backward-char (n &optional killflag)
+  "Delete the previous N characters (following if N is negative).
+See `delete-backward-char' for more information."
+  (interactive "p\nP")
+  (eww-field-funcall #'delete-backward-char n killflag))
+
+(defun eww-field-delete-char (n &optional killflag)
+  "Delete the following N characters (previous if N is negative).
+See `delete-char' for more information."
+  (interactive "p\nP")
+  (eww-field-funcall #'delete-char n killflag))
+
+(defun eww-field-kill-line (&optional arg)
+  "Kill the rest of the current line.  See `kill-line' for more info."
+  (interactive "*P")
+  (eww-field-funcall #'kill-line arg))
+
+(defun eww-field-kill-region (beg end &optional region)
+  "Kill text between point and mark.  See `kill-region' for more info."
+  (interactive (list (mark) (point) 'region))
+  (unless (and beg end)
+    (user-error "The mark is not set now, so there is no region"))
+  (eww-field-funcall #'kill-region beg end region))
+
+(defun eww-field-newline (&optional arg interactive)
+  "Insert a newline, and move to left margin of the new line if it's blank.
+See `newline' for more information."
+  (interactive "*P\np")
+  (eww-field-funcall #'newline arg interactive))
+
+(defun eww-field-open-line (n)
+  "Insert a newline and leave point before it.
+See `open-line' for more information."
+  (interactive "*p")
+  (eww-field-funcall #'open-line n))
+
+(defun eww-field-yank (&optional arg)
+  "Reinsert the last stretch of killed text.  See `yank' for more info."
+  (interactive "*P")
+  (push-mark)
+  (eww-field-funcall #'yank arg))
+
+(defun eww-field-yank-pop (&optional arg)
+  "Replace just-yanked stretch of killed text with a different stretch.
+See `yank-pop' for more infomation."
+  (interactive "*p")
+  (let ((start (eww-beginning-of-field))
+	(mk (mark t)))
+    (unless (and mk (>= mk start) (<= mk (eww-end-of-field)))
+      (goto-char (prog1 (point)
+		   (goto-char start)
+		   (push-mark))))
+    (eww-field-funcall #'yank-pop arg)))
 
 (defun eww-beginning-of-field ()
   (cond
@@ -1099,7 +1437,10 @@
                        (list :eww-form eww-form
                              :value value
                              :type type
-                             :name (dom-attr dom 'name)))
+                             :name (dom-attr dom 'name)
+			     :width width))
+    ;; Enable the major mode keymap on the subsequent gap.
+    (put-text-property start (point) 'rear-nonsticky '(local-map))
     (insert " ")))
 
 (defconst eww-text-input-types '("text" "password" "textarea"
@@ -1109,19 +1450,26 @@
   "List of input types which represent a text input.
 See URL `https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Input'.")
 
-(defun eww-process-text-input (beg end replace-length)
+(defvar eww-field-replace-length nil)
+
+(defun eww-preprocess-text-input (beg end)
+  (setq eww-field-replace-length (string-width (buffer-substring beg end))))
+
+(defun eww-process-text-input (beg end _replace-length)
   (when-let* ((pos (and (< (1+ end) (point-max))
 		        (> (1- end) (point-min))
 		        (cond
+			 ((get-text-property end 'eww-form)
+			  end)
 		         ((get-text-property (1+ end) 'eww-form)
 			  (1+ end))
 		         ((get-text-property (1- end) 'eww-form)
 			  (1- end))))))
     (let* ((form (get-text-property pos 'eww-form))
 	   (properties (text-properties-at pos))
-           (buffer-undo-list t)
 	   (inhibit-read-only t)
-	   (length (- end beg replace-length))
+	   (length (- (string-width (buffer-substring beg end))
+		      eww-field-replace-length))
 	   (type (plist-get form :type)))
       (when (and form
 		 (member type eww-text-input-types))
@@ -1134,6 +1482,8 @@
 		 (1- (line-end-position))
 	       (eww-end-of-field)))
 	    (while (and (> length 0)
+			;; Don't delete space a user enters at (1- eol).
+			(< end (point))
 			(eql (char-after (1- (point))) ? ))
 	      (delete-region (1- (point)) (point))
 	      (cl-decf length))))
@@ -1141,13 +1491,10 @@
 	  ;; Add padding.
 	  (save-excursion
 	    (goto-char end)
-	    (goto-char
-	     (if (equal type "textarea")
-		 (1- (line-end-position))
-	       (1+ (eww-end-of-field))))
-	    (let ((start (point)))
-              (insert (make-string (abs length) ? ))
-	      (set-text-properties start (point) properties))
+	    (if (equal type "textarea")
+		(end-of-line)
+	      (goto-char (1+ (eww-end-of-field))))
+	    (insert-before-markers (make-string (abs length) ? ))
 	    (goto-char (1- end)))))
 	(set-text-properties (cdr (assq :start form))
                              (cdr (assq :end form))
@@ -1166,13 +1513,14 @@
                'display (make-string (length value) ?*)))))))))
 
 (defun eww-tag-textarea (dom)
-  (let ((start (point))
-	(value (or (dom-attr dom 'value) ""))
+  (let ((value (or (dom-attr dom 'value) (dom-text dom)))
 	(lines (string-to-number (or (dom-attr dom 'rows) "10")))
 	(width (string-to-number (or (dom-attr dom 'cols) "10")))
-	end)
+	start end)
     (shr-ensure-newline)
-    (insert value)
+    (setq start (point))
+    (let ((fill-column width))
+      (fill-region start (progn (insert value) (point))))
     (shr-ensure-newline)
     (when (< (count-lines start (point)) lines)
       (dotimes (_ (- lines (count-lines start (point))))
@@ -1181,20 +1529,24 @@
     (goto-char start)
     (while (< (point) end)
       (end-of-line)
-      (let ((pad (- width (- (point) (line-beginning-position)))))
+      (let ((pad (- width (current-column)))) ;; There may be a wide character.
 	(when (> pad 0)
 	  (insert (make-string pad ? ))))
       (add-face-text-property (line-beginning-position)
 			      (point) 'eww-form-textarea)
-      (put-text-property (line-beginning-position) (point) 'inhibit-read-only t)
-      (put-text-property (line-beginning-position) (point)
-			 'local-map eww-textarea-map)
+      (add-text-properties (line-beginning-position) (point)
+			   `(inhibit-read-only t
+			     local-map ,eww-textarea-map
+			     ;; Enable the major mode keymap on newlines.
+			     rear-nonsticky (local-map)))
       (forward-line 1))
     (put-text-property start (point) 'eww-form
 		       (list :eww-form eww-form
 			     :value value
 			     :type "textarea"
-			     :name (dom-attr dom 'name)))))
+			     :name (dom-attr dom 'name)
+			     :lines lines
+			     :width width))))
 
 (defun eww-tag-input (dom)
   (let ((type (downcase (or (dom-attr dom 'type) "text")))
@@ -1366,7 +1718,7 @@
           (nconc props (list (cons :start start)))
           (setq start (next-single-property-change
                        start 'eww-form nil (point-max)))
-          (nconc props (list (cons :end start))))))))
+          (nconc props (list (cons :end (set-marker (make-marker) start)))))))))
 
 (defun eww-input-value (input)
   (let ((type (plist-get input :type))

  reply	other threads:[~2017-11-10  7:57 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-10-20  8:39 bug#28907: 26.0.90; [eww] some problems in input/textarea Katsumi Yamaoka
2017-10-27 13:31 ` Eli Zaretskii
2017-10-29 23:30   ` Katsumi Yamaoka
2017-11-02  7:39     ` Katsumi Yamaoka
2017-11-10  7:57       ` Katsumi Yamaoka [this message]
2017-11-10  8:28         ` Eli Zaretskii
2017-11-10  9:10           ` Katsumi Yamaoka
2017-11-14  8:26         ` Katsumi Yamaoka
2017-11-17  8:42           ` Katsumi Yamaoka
2017-12-13  8:19             ` Katsumi Yamaoka
2017-12-15  9:03               ` Eli Zaretskii
2017-12-15  9:58                 ` Katsumi Yamaoka
2017-12-27 21:12             ` Lars Ingebrigtsen
2018-04-12 22:30               ` Lars Ingebrigtsen

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=b4mfu9mbm70.fsf@jpl.org \
    --to=yamaoka@jpl.org \
    --cc=28907@debbugs.gnu.org \
    --cc=eliz@gnu.org \
    --cc=larsi@gnus.org \
    /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).