From: David Kastrup <dak@gnu.org>
Subject: Summary of changes to replace.el and search.c
Date: 22 Jun 2004 14:39:19 +0200 [thread overview]
Message-ID: <x5isdjhimg.fsf@lola.goethe.zz> (raw)
[-- Attachment #1: Type: text/plain, Size: 2655 bytes --]
Ok, I _think_ I have the stuff more or less covered by now. Here is
the gist of what I think it does:
you can go back to earlier changes and non-changes with ^. You'll get
highlighting for the changed or unchanged region as proper.
Replacements and stuff for the _current_ match will still work out
even if you edit in between (by using markers to save the match-data),
but if you edit before _previous_ changes, you'll get into trouble
(the change _history_ does not use markers for efficiency reasons).
All markers (or at least the significant majority) get destroyed
explicitly, so there should be no marker-induced delays apparent.
Editing of _regexp_ replacement strings (I can't with good conscience
make \? do something special in non-regexp replacements) can happen
with \?.
The current version should not be significantly slower than
previously, with possibly one exception: when doing massive
replacements with map-query-replace-regexp, each replacement will get
scanned for possibly occuring \? strings _each_ time. Since
map-query-replace-regexp is probably not the most frequent function to
use, I doubt this is very relevant, though.
Please check out the patches: I had to make several changes to
search.c which had, as far as I am concerned, several bugs and needed
amendments of the save-data structures, too.
\? is not yet documented. I _think_ it makes a nice addition. The
way it works also makes it abundantly clear that one should enter
explicitly backslash-quoted strings as answer to \?, since one is
editing the replacement string.
Here are the patches for src/search.c and lisp/replace.el against
current CVS. Note that the changes, including API change of
match-data t, that I have done to search.c is strictly bugfix
material: the previous behavior was inconsistent and partly wrong.
Whether or not people want \? in the current form in the code, the
changes in search.c are necessary also to get replace.el work
correctly even in its previous form.
That is not to say that I am convinced the new code is bugfree: I am
convinced it is necessary, and I became exposed to this necessity by
working on replace.el. So please take a double careful look at the
changes in search.c: they affect _a_ _lot_ possibly, and I am
particularly not certain that the garbage collector and general Lisp
machinery will be fine with saving last_thing_searched (which can be a
buffer) away the way I do. I am a doctor, not an engine... I mean,
I am a C programmer, not Lisp, no a Lisp... whatever. I don't have a
clue about the C aspects of Emacs' Lisp machine.
Even if people don't check this out, I'll check it in eventually.
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: Type: text/x-patch, Size: 6386 bytes --]
Index: search.c
===================================================================
RCS file: /cvsroot/emacs/emacs/src/search.c,v
retrieving revision 1.180
diff -c -r1.180 search.c
--- search.c 21 Jun 2004 03:24:25 -0000 1.180
+++ search.c 22 Jun 2004 12:28:39 -0000
@@ -2589,15 +2589,20 @@
/* Adjust search data for this change. */
{
int oldend = search_regs.end[sub];
+ int oldstart = search_regs.start[sub];
int change = newpoint - search_regs.end[sub];
int i;
for (i = 0; i < search_regs.num_regs; i++)
{
- if (search_regs.start[i] > oldend)
+ if (search_regs.start[i] >= oldend)
search_regs.start[i] += change;
- if (search_regs.end[i] > oldend)
+ else if (search_regs.start[i] > oldstart)
+ search_regs.start[i] = oldstart;
+ if (search_regs.end[i] >= oldend)
search_regs.end[i] += change;
+ else if (search_regs.end[i] > oldstart)
+ search_regs.end[i] = oldstart;
}
}
@@ -2666,8 +2671,11 @@
if the last match was on a buffer; integers or nil if a string was matched.
Use `store-match-data' to reinstate the data in this list.
-If INTEGERS (the optional first argument) is non-nil, always use integers
-\(rather than markers) to represent buffer positions.
+If INTEGERS (the optional first argument) is non-nil, always use
+integers \(rather than markers) to represent buffer positions. In
+this case, and if the last match was in a buffer, the buffer will get
+stored as one additional element at the end of the list.
+
If REUSE is a list, reuse it as part of the value. If REUSE is long enough
to hold all the values, and if INTEGERS is non-nil, no consing is done.
@@ -2684,10 +2692,10 @@
prev = Qnil;
- data = (Lisp_Object *) alloca ((2 * search_regs.num_regs)
+ data = (Lisp_Object *) alloca ((2 * search_regs.num_regs + 1)
* sizeof (Lisp_Object));
- len = -1;
+ len = 0;
for (i = 0; i < search_regs.num_regs; i++)
{
int start = search_regs.start[i];
@@ -2714,22 +2722,29 @@
/* last_thing_searched must always be Qt, a buffer, or Qnil. */
abort ();
- len = i;
+ len = 2*(i+1);
}
else
data[2 * i] = data [2 * i + 1] = Qnil;
}
+ if (BUFFERP(last_thing_searched)
+ && ! NILP (integers))
+ {
+ XSETBUFFER(data[len], last_thing_searched);
+ len++;
+ }
+
/* If REUSE is not usable, cons up the values and return them. */
if (! CONSP (reuse))
- return Flist (2 * len + 2, data);
+ return Flist (len, data);
/* If REUSE is a list, store as many value elements as will fit
into the elements of REUSE. */
for (i = 0, tail = reuse; CONSP (tail);
i++, tail = XCDR (tail))
{
- if (i < 2 * len + 2)
+ if (i < len)
XSETCAR (tail, data[i]);
else
XSETCAR (tail, Qnil);
@@ -2738,8 +2753,8 @@
/* If we couldn't fit all value elements into REUSE,
cons up the rest of them and add them to the end of REUSE. */
- if (i < 2 * len + 2)
- XSETCDR (prev, Flist (2 * len + 2 - i, data + i));
+ if (i < len)
+ XSETCDR (prev, Flist (len - i, data + i));
return reuse;
}
@@ -2760,8 +2775,8 @@
if (!CONSP (list) && !NILP (list))
list = wrong_type_argument (Qconsp, list);
- /* Unless we find a marker with a buffer in LIST, assume that this
- match data came from a string. */
+ /* Unless we find a marker with a buffer or an explicit buffer
+ in LIST, assume that this match data came from a string. */
last_thing_searched = Qt;
/* Allocate registers if they don't already exist. */
@@ -2792,42 +2807,49 @@
search_regs.num_regs = length;
}
- }
- for (i = 0; i < search_regs.num_regs; i++)
- {
- marker = Fcar (list);
- if (NILP (marker))
- {
- search_regs.start[i] = -1;
- list = Fcdr (list);
- }
- else
- {
- int from;
+ for (i = 0; i < length; i++)
+ {
+ marker = Fcar (list);
+ if (NILP (marker))
+ {
+ search_regs.start[i] = -1;
+ list = Fcdr (list);
+ }
+ else
+ {
+ int from;
+
+ if (MARKERP (marker))
+ {
+ if (XMARKER (marker)->buffer == 0)
+ XSETFASTINT (marker, 0);
+ else
+ XSETBUFFER (last_thing_searched, XMARKER (marker)->buffer);
+ }
+
+ CHECK_NUMBER_COERCE_MARKER (marker);
+ from = XINT (marker);
+ list = Fcdr (list);
+
+ marker = Fcar (list);
+ if (MARKERP (marker) && XMARKER (marker)->buffer == 0)
+ XSETFASTINT (marker, 0);
+
+ CHECK_NUMBER_COERCE_MARKER (marker);
+ search_regs.start[i] = from;
+ search_regs.end[i] = XINT (marker);
+ }
+ list = Fcdr (list);
+ }
- if (MARKERP (marker))
- {
- if (XMARKER (marker)->buffer == 0)
- XSETFASTINT (marker, 0);
- else
- XSETBUFFER (last_thing_searched, XMARKER (marker)->buffer);
- }
+ for (; i < search_regs.num_regs; i++)
+ search_regs.start[i] = -1;
+ }
- CHECK_NUMBER_COERCE_MARKER (marker);
- from = XINT (marker);
- list = Fcdr (list);
-
- marker = Fcar (list);
- if (MARKERP (marker) && XMARKER (marker)->buffer == 0)
- XSETFASTINT (marker, 0);
-
- CHECK_NUMBER_COERCE_MARKER (marker);
- search_regs.start[i] = from;
- search_regs.end[i] = XINT (marker);
- }
- list = Fcdr (list);
- }
+ if (CONSP(list) && BUFFERP(XCAR(list))) {
+ XSETBUFFER(last_thing_searched, XCAR(list));
+ }
return Qnil;
}
@@ -2836,6 +2858,7 @@
during the execution of a sentinel or filter. */
static int search_regs_saved;
static struct re_registers saved_search_regs;
+static Lisp_Object saved_last_thing_searched;
/* Called from Flooking_at, Fstring_match, search_buffer, Fstore_match_data
if asynchronous code (filter or sentinel) is running. */
@@ -2847,6 +2870,8 @@
saved_search_regs.num_regs = search_regs.num_regs;
saved_search_regs.start = search_regs.start;
saved_search_regs.end = search_regs.end;
+ saved_last_thing_searched = last_thing_searched;
+ last_thing_searched = Qnil;
search_regs.num_regs = 0;
search_regs.start = 0;
search_regs.end = 0;
@@ -2869,7 +2894,8 @@
search_regs.num_regs = saved_search_regs.num_regs;
search_regs.start = saved_search_regs.start;
search_regs.end = saved_search_regs.end;
-
+ last_thing_searched = saved_last_thing_searched;
+ saved_last_thing_searched = Qnil;
search_regs_saved = 0;
}
}
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: Type: text/x-patch, Size: 15910 bytes --]
*** replace.el 17 Jun 2004 16:36:17 +0200 1.173
--- replace.el 21 Jun 2004 22:57:28 +0200
***************
*** 95,100 ****
--- 95,120 ----
(setq to (read-from-minibuffer (format "%s %s with: " string from)
nil nil nil
query-replace-to-history-variable from t)))
+ (when (and regexp-flag
+ (string-match "\\(\\`\\|[^\\]\\)\\(\\\\\\\\\\)*\\\\[,#]" to))
+ (let (pos list char)
+ (while (string-match "\\(\\`\\|[^\\]\\)\\(\\\\\\\\\\)*\\\\[,#]" to)
+ (setq pos (match-end 0))
+ (push (substring to 0 (- pos 2)) list)
+ (setq char (aref to (1- pos))
+ to (substring to pos))
+ (cond ((eq char ?\#)
+ (push '(number-to-string replace-count) list))
+ ((eq char ?\,)
+ (setq pos (read-from-string to))
+ (push `(replace-quote ,(car pos)) list)
+ (setq to (substring to (cdr pos))))))
+ (setq to (nreverse (delete "" (cons to list)))))
+ (replace-match-string-symbols to)
+ (setq to (cons 'replace-eval-replacement
+ (if (> (length to) 1)
+ (cons 'concat to)
+ (car to)))))
(list from to current-prefix-arg)))
(defun query-replace (from-string to-string &optional delimited start end)
***************
*** 183,221 ****
(interactive
(let ((common
(query-replace-read-args "Query replace regexp" t)))
! (list
! (nth 0 common)
! (if (string-match "\\(\\`\\|[^\\]\\)\\(\\\\\\\\\\)*\\\\[,#]"
! (nth 1 common))
! (let ((to-string (nth 1 common)) pos to-expr char prompt)
! (while (string-match
! "\\(\\`\\|[^\\]\\)\\(\\\\\\\\\\)*\\\\[,#]"
! to-string)
! (setq pos (match-end 0))
! (push (substring to-string 0 (- pos 2)) to-expr)
! (setq char (aref to-string (1- pos))
! to-string (substring to-string pos))
! (cond ((eq char ?\#)
! (push '(number-to-string replace-count) to-expr))
! ((eq char ?\,)
! (setq pos (read-from-string to-string))
! (push `(replace-quote ,(car pos)) to-expr)
! (setq to-string (substring to-string (cdr pos))))))
! (setq to-expr (nreverse (delete "" (cons to-string to-expr))))
! (replace-match-string-symbols to-expr)
! (cons 'replace-eval-replacement
! (if (> (length to-expr) 1)
! (cons 'concat to-expr)
! (car to-expr))))
! (nth 1 common))
! (nth 2 common)
! ;; These are done separately here
! ;; so that command-history will record these expressions
! ;; rather than the values they had this time.
! (if (and transient-mark-mode mark-active)
! (region-beginning))
! (if (and transient-mark-mode mark-active)
! (region-end)))))
(perform-replace regexp to-string t t delimited nil nil start end))
(define-key esc-map [?\C-%] 'query-replace-regexp)
--- 203,217 ----
(interactive
(let ((common
(query-replace-read-args "Query replace regexp" t)))
! (list (nth 0 common) (nth 1 common) (nth 2 common)
! ;; These are done separately here
! ;; so that command-history will record these expressions
! ;; rather than the values they had this time.
! (if (and transient-mark-mode mark-active)
! (region-beginning))
! (if (and transient-mark-mode mark-active)
! (region-end)))))
!
(perform-replace regexp to-string t t delimited nil nil start end))
(define-key esc-map [?\C-%] 'query-replace-regexp)
***************
*** 1115,1120 ****
--- 1111,1159 ----
(aset data 2 (if (consp next) next (aref data 3))))))
(car (aref data 2)))
+ (defun replace-match-data (integers reuse &optional new)
+ "Like `match-data', but markers in REUSE get invalidated.
+ If NEW is non-NIL, it is set and returned instead of fresh data,
+ but coerced to the correct value of INTEGERS."
+ (or (and new
+ (progn
+ (set-match-data new)
+ (and (eq new reuse)
+ (eq (null integers) (markerp (car reuse)))
+ new)))
+ (match-data integers
+ (prog1 reuse
+ (while reuse
+ (if (markerp (car reuse))
+ (set-marker (car reuse) nil))
+ (setq reuse (cdr reuse)))))))
+
+ (defun replace-match-maybe-edit (newtext fixedcase literal noedit match-data)
+ "Make a replacement with `replace-match', editing `\\?'.
+ NEXTEXT, FIXEDCASE, LITERAL are just passed on. If NOEDIT is true, no
+ check for `\\?' is made to save time. MATCH-DATA is used for the
+ replacement. In case editing is done, it is changed to use markers.
+
+ The return value is non-NIL if there has been no `\\?' or NOEDIT was
+ passed in. If LITERAL is set, no checking is done, anyway."
+ (unless (or literal noedit)
+ (setq noedit t)
+ (while (string-match "\\(\\`\\|[^\\]\\)\\(\\\\\\\\\\)*\\(\\\\\\?\\)"
+ newtext)
+ (setq newtext
+ (read-input "Edit replacement string: "
+ (prog1
+ (cons
+ (replace-match "" t t newtext 3)
+ (1+ (match-beginning 3)))
+ (setq match-data
+ (replace-match-data
+ nil match-data match-data))))
+ noedit nil)))
+ (set-match-data match-data)
+ (replace-match newtext fixedcase literal)
+ noedit)
+
(defun perform-replace (from-string replacements
query-flag regexp-flag delimited-flag
&optional repeat-count map start end)
***************
*** 1145,1150 ****
--- 1184,1190 ----
(search-string from-string)
(real-match-data nil) ; the match data for the current match
(next-replacement nil)
+ (noedit nil)
(keep-going t)
(stack nil)
(replace-count 0)
***************
*** 1201,1207 ****
(setq real-match-data
(if (consp match-again)
(progn (goto-char (nth 1 match-again))
! match-again)
(and (or match-again
;; MATCH-AGAIN non-nil means we
;; accept an adjacent match. If
--- 1241,1249 ----
(setq real-match-data
(if (consp match-again)
(progn (goto-char (nth 1 match-again))
! (replace-match-data t
! real-match-data
! match-again))
(and (or match-again
;; MATCH-AGAIN non-nil means we
;; accept an adjacent match. If
***************
*** 1217,1223 ****
(funcall search-function search-string limit t)
;; For speed, use only integers and
;; reuse the list used last time.
! (match-data t real-match-data)))))
;; Optionally ignore matches that have a read-only property.
(unless (and query-replace-skip-read-only
(text-property-not-all
--- 1259,1265 ----
(funcall search-function search-string limit t)
;; For speed, use only integers and
;; reuse the list used last time.
! (replace-match-data t real-match-data)))))
;; Optionally ignore matches that have a read-only property.
(unless (and query-replace-skip-read-only
(text-property-not-all
***************
*** 1249,1264 ****
(set-match-data real-match-data)
(setq next-replacement
(funcall (car replacements) (cdr replacements)
! replace-count)))
(if (not query-flag)
(let ((inhibit-read-only query-replace-skip-read-only))
! (set-match-data real-match-data)
! (replace-match next-replacement nocasify literal)
! (setq replace-count (1+ replace-count)))
(undo-boundary)
(let (done replaced key def)
;; Loop reading commands until one of them sets done,
! ;; which means it has finished handling this occurrence.
(while (not done)
(set-match-data real-match-data)
(replace-highlight (match-beginning 0) (match-end 0))
--- 1291,1313 ----
(set-match-data real-match-data)
(setq next-replacement
(funcall (car replacements) (cdr replacements)
! replace-count)
! noedit nil))
(if (not query-flag)
(let ((inhibit-read-only query-replace-skip-read-only))
! (setq noedit
! (replace-match-maybe-edit
! next-replacement nocasify literal
! noedit real-match-data)
! replace-count (1+ replace-count)))
(undo-boundary)
(let (done replaced key def)
;; Loop reading commands until one of them sets done,
! ;; which means it has finished handling this
! ;; occurrence. Any command that sets `done' should
! ;; leave behind proper match data for the stack.
! ;; Commands not setting `done' need to adjust
! ;; `real-match-data'.
(while (not done)
(set-match-data real-match-data)
(replace-highlight (match-beginning 0) (match-end 0))
***************
*** 1290,1326 ****
((eq def 'backup)
(if stack
(let ((elt (pop stack)))
! (goto-char (car elt))
! (setq replaced (eq t (cdr elt)))
! (or replaced
! (set-match-data (cdr elt))))
(message "No previous match")
(ding 'no-terminate)
(sit-for 1)))
((eq def 'act)
(or replaced
! (progn
! (replace-match next-replacement nocasify literal)
! (setq replace-count (1+ replace-count))))
(setq done t replaced t))
((eq def 'act-and-exit)
(or replaced
! (progn
! (replace-match next-replacement nocasify literal)
! (setq replace-count (1+ replace-count))))
(setq keep-going nil)
(setq done t replaced t))
((eq def 'act-and-show)
(if (not replaced)
! (progn
! (replace-match next-replacement nocasify literal)
! (setq replace-count (1+ replace-count))
! (setq replaced t))))
((eq def 'automatic)
(or replaced
! (progn
! (replace-match next-replacement nocasify literal)
! (setq replace-count (1+ replace-count))))
(setq done t query-flag nil replaced t))
((eq def 'skip)
(setq done t))
--- 1339,1387 ----
((eq def 'backup)
(if stack
(let ((elt (pop stack)))
! (goto-char (nth 0 elt))
! (setq replaced (nth 1 elt)
! real-match-data
! (replace-match-data
! t real-match-data
! (nth 2 elt))))
(message "No previous match")
(ding 'no-terminate)
(sit-for 1)))
((eq def 'act)
(or replaced
! (setq noedit
! (replace-match-maybe-edit
! next-replacement nocasify literal
! noedit real-match-data)
! replace-count (1+ replace-count)))
(setq done t replaced t))
((eq def 'act-and-exit)
(or replaced
! (setq noedit
! (replace-match-maybe-edit
! next-replacement nocasify literal
! noedit real-match-data)
! replace-count (1+ replace-count)))
(setq keep-going nil)
(setq done t replaced t))
((eq def 'act-and-show)
(if (not replaced)
! (setq noedit
! (replace-match-maybe-edit
! next-replacement nocasify literal
! noedit real-match-data)
! replace-count (1+ replace-count)
! real-match-data (replace-match-data
! t real-match-data)
! replaced t)))
((eq def 'automatic)
(or replaced
! (setq noedit
! (replace-match-maybe-edit
! next-replacement nocasify literal
! noedit real-match-data)
! replace-count (1+ replace-count)))
(setq done t query-flag nil replaced t))
((eq def 'skip)
(setq done t))
***************
*** 1328,1363 ****
(recenter nil))
((eq def 'edit)
(let ((opos (point-marker)))
(goto-char (match-beginning 0))
(save-excursion
- (funcall search-function search-string limit t)
- (setq real-match-data (match-data)))
- (save-excursion
(save-window-excursion
(recursive-edit)))
(goto-char opos))
- (set-match-data real-match-data)
;; Before we make the replacement,
;; decide whether the search string
;; can match again just after this match.
(if (and regexp-flag nonempty-match)
(setq match-again (and (looking-at search-string)
(match-data)))))
-
;; Edit replacement.
((eq def 'edit-replacement)
! (setq next-replacement
(read-input "Edit replacement string: "
! next-replacement))
! (or replaced
! (replace-match next-replacement nocasify literal))
(setq done t))
((eq def 'delete-and-edit)
! (delete-region (match-beginning 0) (match-end 0))
! (set-match-data
! (prog1 (match-data)
! (save-excursion (recursive-edit))))
(setq replaced t))
;; Note: we do not need to treat `exit-prefix'
;; specially here, since we reread
--- 1389,1432 ----
(recenter nil))
((eq def 'edit)
(let ((opos (point-marker)))
+ (setq real-match-data (replace-match-data
+ nil real-match-data
+ real-match-data))
(goto-char (match-beginning 0))
(save-excursion
(save-window-excursion
(recursive-edit)))
(goto-char opos))
;; Before we make the replacement,
;; decide whether the search string
;; can match again just after this match.
(if (and regexp-flag nonempty-match)
(setq match-again (and (looking-at search-string)
(match-data)))))
;; Edit replacement.
((eq def 'edit-replacement)
! (setq real-match-data (replace-match-data
! nil real-match-data
! real-match-data)
! next-replacement
(read-input "Edit replacement string: "
! next-replacement)
! noedit nil)
! (if replaced
! (set-match-data real-match-data)
! (setq noedit
! (replace-match-maybe-edit
! next-replacement nocasify literal noedit
! real-match-data)
! replaced t))
(setq done t))
((eq def 'delete-and-edit)
! (replace-match "" t t)
! (setq real-match-data (replace-match-data
! nil real-match-data))
! (replace-dehighlight)
! (save-excursion (recursive-edit))
(setq replaced t))
;; Note: we do not need to treat `exit-prefix'
;; specially here, since we reread
***************
*** 1372,1381 ****
;; Record previous position for ^ when we move on.
;; Change markers to numbers in the match data
;; since lots of markers slow down editing.
! (setq stack
! (cons (cons (point)
! (or replaced (match-data t)))
! stack))))))
;; The code preventing adjacent regexp matches in the condition
;; of the while-loop above will haven taken us one character
--- 1441,1452 ----
;; Record previous position for ^ when we move on.
;; Change markers to numbers in the match data
;; since lots of markers slow down editing.
! (push (list (point) replaced
! (if replaced
! (list (match-beginning 0)
! (match-end 0))
! (match-data t)))
! stack)))))
;; The code preventing adjacent regexp matches in the condition
;; of the while-loop above will haven taken us one character
***************
*** 1405,1418 ****
(defun replace-highlight (start end)
(and query-replace-highlight
! (progn
! (or replace-overlay
! (progn
! (setq replace-overlay (make-overlay start end))
! (overlay-put replace-overlay 'face
! (if (facep 'query-replace)
! 'query-replace 'region))))
! (move-overlay replace-overlay start end (current-buffer)))))
;;; arch-tag: 16b4cd61-fd40-497b-b86f-b667c4cf88e4
;;; replace.el ends here
--- 1476,1487 ----
(defun replace-highlight (start end)
(and query-replace-highlight
! (if replace-overlay
! (move-overlay replace-overlay start end (current-buffer))
! (setq replace-overlay (make-overlay start end))
! (overlay-put replace-overlay 'face
! (if (facep 'query-replace)
! 'query-replace 'region)))))
;;; arch-tag: 16b4cd61-fd40-497b-b86f-b667c4cf88e4
;;; replace.el ends here
[-- Attachment #4: Type: text/plain, Size: 52 bytes --]
--
David Kastrup, Kriemhildstr. 15, 44793 Bochum
[-- Attachment #5: Type: text/plain, Size: 142 bytes --]
_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel
reply other threads:[~2004-06-22 12:39 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
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
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=x5isdjhimg.fsf@lola.goethe.zz \
--to=dak@gnu.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 external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.