* bug#36392: (info "(elisp)Writing Emacs Primitives") might need some clarifications @ 2019-06-26 11:31 Stefan Kangas 2019-06-26 13:09 ` Basil L. Contovounesios 0 siblings, 1 reply; 7+ messages in thread From: Stefan Kangas @ 2019-06-26 11:31 UTC (permalink / raw) To: 36392 As a beginner on Emacs Internals, I've been reading: (info "(elisp)Writing Emacs Primitives") I hope that you find the following observations useful: 1. "If the primitive accepts a fixed maximum number of Lisp arguments, there must be one C argument for each Lisp argument, and each argument must be of type ‘Lisp_Object’. ... If the primitive has no upper limit on the number of Lisp arguments, it must have exactly two C arguments: the first is the number of Lisp arguments, and the second is the address of a block containing their values." The example given is DEFUN( "or", ...) This function has no upper limit on the number of Lisp arguments, but still has only ONE argument. Unless I'm missing something, this contradicts the statement above that "it must have exactly TWO C arguments" (my emphasis). 2. "Although the garbage collector does not reclaim objects reachable from C ‘Lisp_Object’ stack variables, it may move non-object components of an object, such as string contents; so functions that access non-object components must take care to refetch their addresses after performing Lisp evaluation." I don't think this is very clear. What is non-object components? How would I refetch their addresses? How is this relevant to the topic at hand? I suggest that the above two points are clarified in the manual somehow. Thanks, Stefan Kangas ^ permalink raw reply [flat|nested] 7+ messages in thread
* bug#36392: (info "(elisp)Writing Emacs Primitives") might need some clarifications 2019-06-26 11:31 bug#36392: (info "(elisp)Writing Emacs Primitives") might need some clarifications Stefan Kangas @ 2019-06-26 13:09 ` Basil L. Contovounesios 2019-06-26 15:14 ` Eli Zaretskii 0 siblings, 1 reply; 7+ messages in thread From: Basil L. Contovounesios @ 2019-06-26 13:09 UTC (permalink / raw) To: Stefan Kangas; +Cc: 36392 [-- Attachment #1: Type: text/plain, Size: 46 bytes --] tags 36392 + patch severity 36392 minor quit [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: 0001-Clarify-update-elisp-Writing-Emacs-Primitives.patch --] [-- Type: text/x-diff, Size: 9501 bytes --] From 3d85d73858fe0c126277d04db8b99eeb9f09d672 Mon Sep 17 00:00:00 2001 From: "Basil L. Contovounesios" <contovob@tcd.ie> Date: Wed, 26 Jun 2019 13:05:51 +0100 Subject: [PATCH] Clarify & update (elisp) Writing Emacs Primitives * doc/lispref/internals.texi (Writing Emacs Primitives): Replace outdated For listing with current Fwhile, so that the subsequent paragraph on maybe_quit still applies. Reconcile other code listings with their current source. Fix indentation of sample DEFUN argument lists. Replace ... with @dots{}. Fix argument list of Ffoo example. Describe UNEVALLED special forms as taking a single argument. (bug#36392) --- doc/lispref/internals.texi | 112 ++++++++++++++++++------------------- 1 file changed, 55 insertions(+), 57 deletions(-) diff --git a/doc/lispref/internals.texi b/doc/lispref/internals.texi index cfeb492af4..34dfb3924e 100644 --- a/doc/lispref/internals.texi +++ b/doc/lispref/internals.texi @@ -695,38 +695,36 @@ Writing Emacs Primitives C macros. The only way to really understand how to write new C code is to read the source, but we can explain some things here. - An example of a special form is the definition of @code{or}, from + An example of a special form is the definition of @code{while}, from @file{eval.c}. (An ordinary function would have the same general appearance.) @smallexample @group -DEFUN ("or", For, Sor, 0, UNEVALLED, 0, - doc: /* Eval args until one of them yields non-nil, then return -that value. -The remaining args are not evalled at all. -If all args return nil, return nil. +DEFUN ("while", Fwhile, Swhile, 1, UNEVALLED, 0, + doc: /* If TEST yields non-nil, eval BODY... and repeat. +The order of execution is thus TEST, BODY, TEST, BODY and so on +until TEST returns nil. @end group @group -usage: (or CONDITIONS...) */) +usage: (while TEST BODY...) */) (Lisp_Object args) @{ - Lisp_Object val = Qnil; + Lisp_Object test, body; @end group @group - while (CONSP (args)) + test = XCAR (args); + body = XCDR (args); + while (!NILP (eval_sub (test))) @{ - val = eval_sub (XCAR (args)); - if (!NILP (val)) - break; - args = XCDR (args); maybe_quit (); + prog_ignore (body); @} @end group @group - return val; + return Qnil; @} @end group @end smallexample @@ -742,14 +740,14 @@ Writing Emacs Primitives @table @var @item lname This is the name of the Lisp symbol to define as the function name; in -the example above, it is @code{or}. +the example above, it is @code{while}. @item fname This is the C function name for this function. This is the name that is used in C code for calling the function. The name is, by convention, @samp{F} prepended to the Lisp name, with all dashes (@samp{-}) in the Lisp name changed to underscores. Thus, to call -this function from C code, call @code{For}. +this function from C code, call @code{Fwhile}. @item sname This is a C variable name to use for a structure that holds the data for @@ -761,7 +759,7 @@ Writing Emacs Primitives @item min This is the minimum number of arguments that the function requires. The -function @code{or} allows a minimum of zero arguments. +function @code{while} allows a minimum of one argument. @item max This is the maximum number of arguments that the function accepts, if @@ -775,21 +773,20 @@ Writing Emacs Primitives @cindex interactive specification in primitives @item interactive This is an interactive specification, a string such as might be used -as the argument of @code{interactive} in a Lisp function -(@pxref{Using Interactive}). In the case -of @code{or}, it is 0 (a null pointer), indicating that @code{or} -cannot be called interactively. A value of @code{""} indicates a -function that should receive no arguments when called interactively. -If the value begins with a @samp{"(}, the string is evaluated as a -Lisp form. For example: +as the argument of @code{interactive} in a Lisp function (@pxref{Using +Interactive}). In the case of @code{while}, it is @code{0} (a null +pointer), indicating that @code{while} cannot be called interactively. +A value of @code{""} indicates a function that should receive no +arguments when called interactively. If the value begins with a +@samp{"(}, the string is evaluated as a Lisp form. For example: @example @group -DEFUN ("foo", Ffoo, Sfoo, 0, UNEVALLED, 0 +DEFUN ("foo", Ffoo, Sfoo, 0, 3, "(list (read-char-by-name \"Insert character: \")\ (prefix-numeric-value current-prefix-arg)\ - t))", - doc: /* @dots{} */) + t)", + doc: /* @dots{} */) @end group @end example @@ -826,8 +823,8 @@ Writing Emacs Primitives @example @group DEFUN ("bar", Fbar, Sbar, 0, UNEVALLED, 0 - doc: /* @dots{} */ - attributes: @var{attr1} @var{attr2} @dots{}) + doc: /* @dots{} */ + attributes: @var{attr1} @var{attr2} @dots{}) @end group @end example @@ -863,20 +860,23 @@ Writing Emacs Primitives arguments, there must be one C argument for each Lisp argument, and each argument must be of type @code{Lisp_Object}. (Various macros and functions for creating values of type @code{Lisp_Object} are declared -in the file @file{lisp.h}.) If the primitive has no upper limit on -the number of Lisp arguments, it must have exactly two C arguments: -the first is the number of Lisp arguments, and the second is the -address of a block containing their values. These have types -@code{int} and @w{@code{Lisp_Object *}} respectively. Since -@code{Lisp_Object} can hold any Lisp object of any data type, you -can determine the actual data type only at run time; so if you want -a primitive to accept only a certain type of argument, you must check -the type explicitly using a suitable predicate (@pxref{Type Predicates}). +in the file @file{lisp.h}.) If the primitive is a special form, it +must accept a Lisp list containing its unevaluated Lisp arguments as a +single argument of type @code{Lisp_Object}. If the primitive has no +upper limit on the number of evaluated Lisp arguments, it must have +exactly two C arguments: the first is the number of Lisp arguments, +and the second is the address of a block containing their values. +These have types @code{ptrdiff_t} and @w{@code{Lisp_Object *}}, +respectively. Since @code{Lisp_Object} can hold any Lisp object of +any data type, you can determine the actual data type only at run +time; so if you want a primitive to accept only a certain type of +argument, you must check the type explicitly using a suitable +predicate (@pxref{Type Predicates}). @cindex type checking internals @cindex garbage collection protection @cindex protect C variables from garbage collection - Within the function @code{For} itself, the local variable + Within the function @code{Fwhile} itself, the local variable @code{args} refers to objects controlled by Emacs's stack-marking garbage collector. Although the garbage collector does not reclaim objects reachable from C @code{Lisp_Object} stack variables, it may @@ -890,9 +890,8 @@ Writing Emacs Primitives Note the call to @code{maybe_quit} inside the loop: this function checks whether the user pressed @kbd{C-g}, and if so, aborts the processing. You should do that in any loop that can potentially -require a large number of iterations; in this case, the list of -arguments could be very long. This increases Emacs responsiveness and -improves user experience. +require a large number of iterations. This increases Emacs +responsiveness and improves user experience. You must not use C initializers for static or global variables unless the variables are never written once Emacs is dumped. These variables @@ -957,9 +956,9 @@ Writing Emacs Primitives @smallexample @group DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p, - Scoordinates_in_window_p, 2, 2, 0, - doc: /* Return non-nil if COORDINATES are in WINDOW. - ... + Scoordinates_in_window_p, 2, 2, 0, + doc: /* Return non-nil if COORDINATES are in WINDOW. + @dots{} @end group @group or `right-margin' is returned. */) @@ -972,43 +971,42 @@ Writing Emacs Primitives @end group @group - CHECK_LIVE_WINDOW (window); - w = XWINDOW (window); + w = decode_live_window (window); f = XFRAME (w->frame); CHECK_CONS (coordinates); lx = Fcar (coordinates); ly = Fcdr (coordinates); - CHECK_NUMBER_OR_FLOAT (lx); - CHECK_NUMBER_OR_FLOAT (ly); - x = FRAME_PIXEL_X_FROM_CANON_X (f, lx) + FRAME_INTERNAL_BORDER_WIDTH(f); - y = FRAME_PIXEL_Y_FROM_CANON_Y (f, ly) + FRAME_INTERNAL_BORDER_WIDTH(f); + CHECK_NUMBER (lx); + CHECK_NUMBER (ly); + x = FRAME_PIXEL_X_FROM_CANON_X (f, lx) + FRAME_INTERNAL_BORDER_WIDTH (f); + y = FRAME_PIXEL_Y_FROM_CANON_Y (f, ly) + FRAME_INTERNAL_BORDER_WIDTH (f); @end group @group switch (coordinates_in_window (w, x, y)) @{ - case ON_NOTHING: /* NOT in window at all. */ + case ON_NOTHING: return Qnil; @end group - ... + @dots{} @group - case ON_MODE_LINE: /* In mode line of window. */ + case ON_MODE_LINE: return Qmode_line; @end group - ... + @dots{} @group - case ON_SCROLL_BAR: /* On scroll-bar of window. */ + case ON_VERTICAL_SCROLL_BAR: /* Historically we are supposed to return nil in this case. */ return Qnil; @end group @group default: - abort (); + emacs_abort (); @} @} @end group -- 2.20.1 [-- Attachment #3: Type: text/plain, Size: 1814 bytes --] Stefan Kangas <stefan@marxist.se> writes: > As a beginner on Emacs Internals, I've been reading: > > (info "(elisp)Writing Emacs Primitives") > > I hope that you find the following observations useful: > > 1. "If the primitive accepts a fixed maximum number of Lisp > arguments, there must be one C argument for each Lisp argument, > and each argument must be of type ‘Lisp_Object’. ... If the > primitive has no upper limit on the number of Lisp arguments, it > must have exactly two C arguments: the first is the number of Lisp > arguments, and the second is the address of a block containing > their values." > > The example given is DEFUN( "or", ...) > > This function has no upper limit on the number of Lisp arguments, but > still has only ONE argument. Unless I'm missing something, this > contradicts the statement above that "it must have exactly TWO C > arguments" (my emphasis). Indeed, this is because For is a special form (with UNEVALLED args). Compare it with the definition for Fapply (with MANY args) in the same file, and see the macros DEFUN_ARGS_UNEVALLED and DEFUN_ARGS_MANY in lisp.h. Does the attached patch, suitable for either master or emacs-26, help clarify this? > 2. "Although the garbage collector does not reclaim objects reachable > from C ‘Lisp_Object’ stack variables, it may move non-object > components of an object, such as string contents; so functions > that access non-object components must take care to refetch their > addresses after performing Lisp evaluation." > > I don't think this is very clear. What is non-object components? How > would I refetch their addresses? How is this relevant to the topic at > hand? I don't know about this. Thanks, -- Basil ^ permalink raw reply related [flat|nested] 7+ messages in thread
* bug#36392: (info "(elisp)Writing Emacs Primitives") might need some clarifications 2019-06-26 13:09 ` Basil L. Contovounesios @ 2019-06-26 15:14 ` Eli Zaretskii 2019-06-26 18:20 ` Basil L. Contovounesios 0 siblings, 1 reply; 7+ messages in thread From: Eli Zaretskii @ 2019-06-26 15:14 UTC (permalink / raw) To: Basil L. Contovounesios; +Cc: stefan, 36392 > From: "Basil L. Contovounesios" <contovob@tcd.ie> > Date: Wed, 26 Jun 2019 14:09:03 +0100 > Cc: 36392@debbugs.gnu.org > > >From 3d85d73858fe0c126277d04db8b99eeb9f09d672 Mon Sep 17 00:00:00 2001 > From: "Basil L. Contovounesios" <contovob@tcd.ie> > Date: Wed, 26 Jun 2019 13:05:51 +0100 > Subject: [PATCH] Clarify & update (elisp) Writing Emacs Primitives > > * doc/lispref/internals.texi (Writing Emacs Primitives): Replace > outdated For listing with current Fwhile, so that the subsequent > paragraph on maybe_quit still applies. Reconcile other code > listings with their current source. Fix indentation of sample DEFUN > argument lists. Replace ... with @dots{}. Fix argument list of > Ffoo example. Describe UNEVALLED special forms as taking a single > argument. (bug#36392) Hmm... I admit that I don't understand the rationale for these changes. Why replace the example? It's a useful example, and I see nothing wrong with it per se. The actual code doesn't have maybe_quit anymore, but so what? I don't think we should chace every change in the sources with our examples in the manual. > @@ -863,20 +860,23 @@ Writing Emacs Primitives > arguments, there must be one C argument for each Lisp argument, and > each argument must be of type @code{Lisp_Object}. (Various macros and > functions for creating values of type @code{Lisp_Object} are declared > -in the file @file{lisp.h}.) If the primitive has no upper limit on > -the number of Lisp arguments, it must have exactly two C arguments: > -the first is the number of Lisp arguments, and the second is the > -address of a block containing their values. These have types > -@code{int} and @w{@code{Lisp_Object *}} respectively. Since > -@code{Lisp_Object} can hold any Lisp object of any data type, you > -can determine the actual data type only at run time; so if you want > -a primitive to accept only a certain type of argument, you must check > -the type explicitly using a suitable predicate (@pxref{Type Predicates}). > +in the file @file{lisp.h}.) If the primitive is a special form, it > +must accept a Lisp list containing its unevaluated Lisp arguments as a > +single argument of type @code{Lisp_Object}. If the primitive has no > +upper limit on the number of evaluated Lisp arguments, it must have > +exactly two C arguments: the first is the number of Lisp arguments, > +and the second is the address of a block containing their values. > +These have types @code{ptrdiff_t} and @w{@code{Lisp_Object *}}, > +respectively. Since @code{Lisp_Object} can hold any Lisp object of > +any data type, you can determine the actual data type only at run > +time; so if you want a primitive to accept only a certain type of > +argument, you must check the type explicitly using a suitable > +predicate (@pxref{Type Predicates}). > @cindex type checking internals This part sounds OK to me, and is probably more than enough to fix the issue at hand. > - case ON_NOTHING: /* NOT in window at all. */ > + case ON_NOTHING: This seems a change for the worst? > > 2. "Although the garbage collector does not reclaim objects reachable > > from C ‘Lisp_Object’ stack variables, it may move non-object > > components of an object, such as string contents; so functions > > that access non-object components must take care to refetch their > > addresses after performing Lisp evaluation." > > > > I don't think this is very clear. What is non-object components? How > > would I refetch their addresses? How is this relevant to the topic at > > hand? > > I don't know about this. I clarified that. Thanks. ^ permalink raw reply [flat|nested] 7+ messages in thread
* bug#36392: (info "(elisp)Writing Emacs Primitives") might need some clarifications 2019-06-26 15:14 ` Eli Zaretskii @ 2019-06-26 18:20 ` Basil L. Contovounesios 2019-06-26 18:34 ` Eli Zaretskii 0 siblings, 1 reply; 7+ messages in thread From: Basil L. Contovounesios @ 2019-06-26 18:20 UTC (permalink / raw) To: Eli Zaretskii; +Cc: stefan, 36392 Eli Zaretskii <eliz@gnu.org> writes: >> From: "Basil L. Contovounesios" <contovob@tcd.ie> >> Date: Wed, 26 Jun 2019 14:09:03 +0100 >> Cc: 36392@debbugs.gnu.org >> >> >From 3d85d73858fe0c126277d04db8b99eeb9f09d672 Mon Sep 17 00:00:00 2001 >> From: "Basil L. Contovounesios" <contovob@tcd.ie> >> Date: Wed, 26 Jun 2019 13:05:51 +0100 >> Subject: [PATCH] Clarify & update (elisp) Writing Emacs Primitives >> >> * doc/lispref/internals.texi (Writing Emacs Primitives): Replace >> outdated For listing with current Fwhile, so that the subsequent >> paragraph on maybe_quit still applies. Reconcile other code >> listings with their current source. Fix indentation of sample DEFUN >> argument lists. Replace ... with @dots{}. Fix argument list of >> Ffoo example. Describe UNEVALLED special forms as taking a single >> argument. (bug#36392) > > Hmm... I admit that I don't understand the rationale for these > changes. > > Why replace the example? It's a useful example, and I see nothing > wrong with it per se. The actual code doesn't have maybe_quit > anymore, but so what? I don't think we should chace every change in > the sources with our examples in the manual. Indeed there's nothing wrong with the current example, and I don't feel too strongly about the change. Fwhile just happens to be a conveniently similar special form that is better represented by the paragraph on maybe_quit (not just because Fwhile currently calls maybe_quit, but also because it epitomises the need for maybe_quit). Do you prefer not to switch the example to Fwhile? >> @@ -863,20 +860,23 @@ Writing Emacs Primitives >> arguments, there must be one C argument for each Lisp argument, and >> each argument must be of type @code{Lisp_Object}. (Various macros and >> functions for creating values of type @code{Lisp_Object} are declared >> -in the file @file{lisp.h}.) If the primitive has no upper limit on >> -the number of Lisp arguments, it must have exactly two C arguments: >> -the first is the number of Lisp arguments, and the second is the >> -address of a block containing their values. These have types >> -@code{int} and @w{@code{Lisp_Object *}} respectively. Since >> -@code{Lisp_Object} can hold any Lisp object of any data type, you >> -can determine the actual data type only at run time; so if you want >> -a primitive to accept only a certain type of argument, you must check >> -the type explicitly using a suitable predicate (@pxref{Type Predicates}). >> +in the file @file{lisp.h}.) If the primitive is a special form, it >> +must accept a Lisp list containing its unevaluated Lisp arguments as a >> +single argument of type @code{Lisp_Object}. If the primitive has no >> +upper limit on the number of evaluated Lisp arguments, it must have >> +exactly two C arguments: the first is the number of Lisp arguments, >> +and the second is the address of a block containing their values. >> +These have types @code{ptrdiff_t} and @w{@code{Lisp_Object *}}, >> +respectively. Since @code{Lisp_Object} can hold any Lisp object of >> +any data type, you can determine the actual data type only at run >> +time; so if you want a primitive to accept only a certain type of >> +argument, you must check the type explicitly using a suitable >> +predicate (@pxref{Type Predicates}). >> @cindex type checking internals > > This part sounds OK to me, and is probably more than enough to fix the > issue at hand. Indeed, thanks. >> - case ON_NOTHING: /* NOT in window at all. */ >> + case ON_NOTHING: > > This seems a change for the worst? I'll bring back the comments. >> > 2. "Although the garbage collector does not reclaim objects reachable >> > from C ‘Lisp_Object’ stack variables, it may move non-object >> > components of an object, such as string contents; so functions >> > that access non-object components must take care to refetch their >> > addresses after performing Lisp evaluation." >> > >> > I don't think this is very clear. What is non-object components? How >> > would I refetch their addresses? How is this relevant to the topic at >> > hand? >> >> I don't know about this. > > I clarified that. Thanks, -- Basil ^ permalink raw reply [flat|nested] 7+ messages in thread
* bug#36392: (info "(elisp)Writing Emacs Primitives") might need some clarifications 2019-06-26 18:20 ` Basil L. Contovounesios @ 2019-06-26 18:34 ` Eli Zaretskii 2019-06-26 21:29 ` Basil L. Contovounesios 0 siblings, 1 reply; 7+ messages in thread From: Eli Zaretskii @ 2019-06-26 18:34 UTC (permalink / raw) To: Basil L. Contovounesios; +Cc: stefan, 36392 > From: "Basil L. Contovounesios" <contovob@tcd.ie> > Cc: stefan@marxist.se, 36392@debbugs.gnu.org > Date: Wed, 26 Jun 2019 19:20:25 +0100 > > Do you prefer not to switch the example to Fwhile? Yes, I think we should just describe UNEVAL, so that the example doesn't confuse. Thanks. ^ permalink raw reply [flat|nested] 7+ messages in thread
* bug#36392: (info "(elisp)Writing Emacs Primitives") might need some clarifications 2019-06-26 18:34 ` Eli Zaretskii @ 2019-06-26 21:29 ` Basil L. Contovounesios 2019-06-27 1:01 ` Stefan Kangas 0 siblings, 1 reply; 7+ messages in thread From: Basil L. Contovounesios @ 2019-06-26 21:29 UTC (permalink / raw) To: Eli Zaretskii; +Cc: stefan, 36392-done tags 36392 fixed close 36392 26.3 quit Eli Zaretskii <eliz@gnu.org> writes: >> From: "Basil L. Contovounesios" <contovob@tcd.ie> >> Cc: stefan@marxist.se, 36392@debbugs.gnu.org >> Date: Wed, 26 Jun 2019 19:20:25 +0100 >> >> Do you prefer not to switch the example to Fwhile? > > Yes, I think we should just describe UNEVAL, so that the example > doesn't confuse. Okay, I pushed a more measured patch to emacs-26[1]. Stefan, do these patches address your concerns, or do you think further clarification is required? [1: 8b775c30ad]: Clarify & update (elisp) Writing Emacs Primitives 2019-06-26 22:16:52 +0100 https://git.savannah.gnu.org/cgit/emacs.git/commit/?id=8b775c30adaad63a4838e911d6c02e55a4269c4e Thanks, -- Basil ^ permalink raw reply [flat|nested] 7+ messages in thread
* bug#36392: (info "(elisp)Writing Emacs Primitives") might need some clarifications 2019-06-26 21:29 ` Basil L. Contovounesios @ 2019-06-27 1:01 ` Stefan Kangas 0 siblings, 0 replies; 7+ messages in thread From: Stefan Kangas @ 2019-06-27 1:01 UTC (permalink / raw) To: Basil L. Contovounesios; +Cc: 36392 Basil L. Contovounesios <contovob@tcd.ie> writes: > [...] Stefan, do these > patches address your concerns, or do you think further clarification is > required? Absolutely, these changes makes things much clearer. Thank you both for fixing this so promptly. Best regards, Stefan Kangas ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2019-06-27 1:01 UTC | newest] Thread overview: 7+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2019-06-26 11:31 bug#36392: (info "(elisp)Writing Emacs Primitives") might need some clarifications Stefan Kangas 2019-06-26 13:09 ` Basil L. Contovounesios 2019-06-26 15:14 ` Eli Zaretskii 2019-06-26 18:20 ` Basil L. Contovounesios 2019-06-26 18:34 ` Eli Zaretskii 2019-06-26 21:29 ` Basil L. Contovounesios 2019-06-27 1:01 ` Stefan Kangas
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.