discuss@mandoc.bsd.lv
 help / color / mirror / Atom feed
From: Kristaps Dzonsons <kristaps@bsd.lv>
To: discuss@mdocml.bsd.lv
Subject: PATCH: Intra- and inter-document linking.
Date: Thu, 12 Mar 2015 11:51:01 +0900	[thread overview]
Message-ID: <5500FF15.2090108@bsd.lv> (raw)

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

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

Hi folks,

This wraps up an examplenimplementation of `Ix' for mdoc(7) by
extending `Xr' to handle indices made with `Ix'.  In other words,
linking to sections in other manpages.  Enclosed is the patch.

* BACKGROUND

`Ix' is a macro proposal that inserts an anchor at an arbitrary
location in an mdoc(7) document.  There are already two implicit
anchors generated with `Sh' and `Ss'; `Ix' allows for the same.

As with `Sh' and `Ss', `Ix' anchors can be linked with the `Sx' macro.
 In effect, this allows doing things like:

 .Bl -tag -width Ds
 .It Fl b Ar moo
 .Ix -b flag
 This is a flag...
 ...
 .El

Then later:

 The
 .Sx -b flag
 allows us to...

For completeness, I also add an `Lkx' macro that serves to link to
sections in the same document by a different name.  Thus,

 The
 .Lkx "-b flag" "bee flag"
 allows us to...

I actually don't like the `Lkx' and would prefer `Sxx' or something,
but bikeshed bikeshed bikeshed.

`Ix' is nice because it fits with the existing `Sx' model and can
simply be ignored in non-conformant tools like groff(1).  Output modes
/not/ allowing for linkage, such as -Tascii, can simply discard `Ix'
and render the contents of `Sx' as-is.  This is the existing behaviour
when using `Sx' to link to `Sh' and so on.

* INTER-PAGE LINKING

The remaining problem is inter-document linkage.  This can be easily
accomodated by extending `Xr' to accept 1, 2, 3, or 4 arguments:

 .Xr NAME [SECTION [LINK [LINKNAME]]]

So we can have

 .Xr foo
 .Xr foo 1
 .Xr foo 1 NAME
 .Xr foo 1 NAME "name section"

By default, links to other sections can be formatted as "foo(1)
section NAME", but this needs some more consideration because it might
not be a section that's linked.

* PROBLEMS

All of this works beautifully in -Thtml (and can be extended to -Tpdf
and friends).  The problem is in -Tascii, which as it stands can't
support links.  (That's beyond the scope of these patches.)  While we
can get away with `Sx' doing nothing for sections, using `Sx' in
console mode to refer to `Ix' tags is confusing because, well, they
don't exist.

There is, however, a solution.  I don't have a patch for this (yet),
but am working on it.  Essentially, -Tascii knows the exact line and
column of its output.  When we invoke an `Ix', we remember the output
line and column.  Then when we use `Sx', we can refer to the line and
column of the origin.

For example,

Hello
.Ix world
world.
...
...
Link to
.Sx world .

Right now, this produces "Link to world".  Why not make it do "Link to
world [line 23, column 45]"?  This way, we can have arbitrary links in
- -Tascii and quickly jump to the locations in the manpager.

This doesn't do much for `Xr', unfortunately.

Best,

Kristaps
-----BEGIN PGP SIGNATURE-----
Comment: GPGTools - https://gpgtools.org

iQIcBAEBCgAGBQJVAP8VAAoJEMT2SUY9XBES7A8QAIbH4nUAzZwf05As7tKiOW+u
YV9kHedKZjgYWPX6MgUwGyl+MRwqdVcT+Xx/LPhJtXsnzBGwd+1CsKsAZFTfi7rr
dyB3ZupSf3ZF89X+aRn3MpY8A+7XiKUm/seXZFLtB/u7rMRnEP0TVJF1oWF6V5oW
fLAQvuq7Aw5HkPj1nscUSQO6pQx/xpYozgZ5R8E3aBSN7DRFj/6U6784C7AlIia8
IKrnvp4WJVYulDgwADxQE0SgxOfeIT+aDDIqGCy3gqfIeH1xsgiXHsB+IJQkgsLT
lxnw3blrPnDoEcYaUu0/u+i57z+Q+REbPYgkNENp7lZaHqopovY/lX2nZCmacyOE
yMONC9E7vLvnPVikyNfz2V6FXG3hb76m1HBxtPCcTZnn25uzbUI3Ha+N8pyMEL77
6tV+H7G8/ffkoS9UBXODyXETGqjCLG09L24k+iiIKuamEfaQcyHY46p8Nyo+TpH9
LES3RsquRUIdz96yK4kbLH964x8juU6fdCkZ8cR5iPYb+SdUz6RkmBAChlFHYPjB
3W/sEr+aw3AOsghaNwUznSCeNx9Ag492U0nIwPOeeUaWG9k68/Jd7mbcuy8avPLP
7F1O9j+g7mugmhHCcaIkPlsfbgwhtWmbmbPVGAqDgalzccxPA/0UyOsZ3/lGRy/t
hgOknxeuWPvk7B4vlC14
=cGAE
-----END PGP SIGNATURE-----

[-- Attachment #2: index.patch --]
[-- Type: text/plain, Size: 12791 bytes --]

? .DS_Store
? Makefile.local
? cgi.h
? config.h
? config.log
? configure.local
? foo.7
? foo.7.html
? foo.html
? index.patch
? linking.patch
? machine.diff
? tbl.patch
? tbl2.patch
Index: html.c
===================================================================
RCS file: /home/cvs/mdocml/mdocml/html.c,v
retrieving revision 1.185
diff -u -p -r1.185 html.c
--- html.c	21 Jan 2015 20:33:25 -0000	1.185
+++ html.c	12 Mar 2015 02:49:07 -0000
@@ -707,7 +707,8 @@ buffmt_includes(struct html *h, const ch
 }
 
 void
-buffmt_man(struct html *h, const char *name, const char *sec)
+buffmt_man(struct html *h, const char *name, 
+	const char *sec, const char *index)
 {
 	const char	*p, *pp;
 
@@ -731,6 +732,10 @@ buffmt_man(struct html *h, const char *n
 	}
 	if (pp)
 		bufcat(h, pp);
+	if (NULL != index) {
+		bufcat(h, "#index-");
+		bufcat_id(h, index);
+	}
 }
 
 void
@@ -752,7 +757,12 @@ bufcat_id(struct html *h, const char *sr
 {
 
 	/* Cf. <http://www.w3.org/TR/html4/types.html#h-6.2>. */
-
-	while ('\0' != *src)
-		bufcat_fmt(h, "%.2x", *src++);
+	for ( ; '\0' != *src; src++) {
+		if (isalnum((unsigned int)*src))
+			bufncat(h, src, 1);
+		else if (' ' == *src)
+			bufncat(h, "_", 1);
+		else
+			bufcat_fmt(h, "%.2x", *src);
+	}
 }
Index: html.h
===================================================================
RCS file: /home/cvs/mdocml/mdocml/html.h,v
retrieving revision 1.70
diff -u -p -r1.70 html.h
--- html.h	2 Dec 2014 10:08:06 -0000	1.70
+++ html.h	12 Mar 2015 02:49:08 -0000
@@ -171,7 +171,7 @@ void		  bufcat_style(struct html *,
 void		  bufcat_su(struct html *, const char *,
 			const struct roffsu *);
 void		  bufinit(struct html *);
-void		  buffmt_man(struct html *,
+void		  buffmt_man(struct html *, const char *, 
 			const char *, const char *);
 void		  buffmt_includes(struct html *, const char *);
 
Index: mdoc.7
===================================================================
RCS file: /home/cvs/mdocml/mdocml/mdoc.7,v
retrieving revision 1.252
diff -u -p -r1.252 mdoc.7
--- mdoc.7	23 Feb 2015 13:31:04 -0000	1.252
+++ mdoc.7	12 Mar 2015 02:49:08 -0000
@@ -440,6 +440,8 @@ in the alphabetical
 .El
 .Ss Sections and cross references
 .Bl -column "Brq, Bro, Brc" description
+.It Sx \&Ix Ta index anchor (one line)
+.It Sx \&Lkx Ta internal cross reference to an index
 .It Sx \&Sh Ta section header (one line)
 .It Sx \&Ss Ta subsection header (one line)
 .It Sx \&Sx Ta internal cross reference to a section or subsection
@@ -510,6 +512,7 @@ in the alphabetical
 .Bl -column "Brq, Bro, Brc" description
 .It Sx \&An Ta author name (>0 arguments)
 .It Sx \&Lk Ta hyperlink: Ar uri Op Ar name
+.It Sx \&Lkx Ta index: Ar index Op Ar name
 .It Sx \&Mt Ta Do mailto Dc hyperlink: Ar address
 .It Sx \&Cd Ta kernel configuration declaration (>0 arguments)
 .It Sx \&Ad Ta memory address (>0 arguments)
@@ -1854,6 +1857,18 @@ will preserve the semicolon whitespace e
 .Pp
 See also
 .Sx \&Bl .
+.Ss \&Ix
+Specify an index point with an arbitrary name.
+The argument is not printed.
+Its syntax is as follows:
+.Pp
+.Dl Pf \. Ix Ar index
+.Pp
+An index is an anchor within a document.
+It can be accessed with
+.Sx \&Lkx
+and
+.Sx \&Sx .
 .Ss \&Lb
 Specify a library.
 The syntax is as follows:
@@ -1905,6 +1920,25 @@ Examples:
 .Pp
 See also
 .Sx \&Mt .
+.Ss \&Lkx
+Formats an index link.
+If invoked without arguments, is the same as
+.Sx \&Sx .
+Its syntax is as follows:
+.Pp
+.Dl Pf \. Sx \&Lkx Ar index Op Ar name
+.Pp
+Examples:
+.Bd -literal -offset indent
+\&.Ix foobar
+Some text here.
+\&.Lkx foobar \(dqGo to the above link\(dq
+.Ed
+.Pp
+See also
+.Sx \&Ix
+and
+.Sx \&Sx .
 .Ss \&Lp
 Synonym for
 .Sx \&Pp .
@@ -2705,18 +2739,31 @@ Link to another manual
 .Pq Qq cross-reference .
 Its syntax is as follows:
 .Pp
-.D1 Pf \. Sx \&Xr Ar name Op section
+.D1 Pf \. Sx \&Xr Ar name Op section Op index Op index_name
 .Pp
 Cross reference the
 .Ar name
 and
 .Ar section
-number of another man page;
-omitting the section number is rarely useful.
+number of another man page.
+.Pq Omitting the section number is rarely useful.
+If
+.Ar index
+is specified, the link is to a position specified with
+.Ss \&Ix ,
+.Ss \&Sh ,
+or
+.Ss \&Ss .
+If
+.Ar index_name
+is used as well, it is printed instead of
+.Ar index ,
+which is used purely as the index location.
 .Pp
 Examples:
 .Dl \&.Xr mandoc 1
 .Dl \&.Xr mandoc 1 \&;
+.Dl \&.Xr mandoc 1 "SEE ALSO"
 .Dl \&.Xr mandoc 1 \&Ns s behaviour
 .Ss \&br
 Emits a line-break.
Index: mdoc.c
===================================================================
RCS file: /home/cvs/mdocml/mdocml/mdoc.c,v
retrieving revision 1.238
diff -u -p -r1.238 mdoc.c
--- mdoc.c	12 Feb 2015 13:00:52 -0000	1.238
+++ mdoc.c	12 Mar 2015 02:49:09 -0000
@@ -61,10 +61,12 @@ const	char *const __mdoc_macronames[MDOC
 	"Fo",		"Fc",		"Oo",		"Oc",
 	"Bk",		"Ek",		"Bt",		"Hf",
 	"Fr",		"Ud",		"Lb",		"Lp",
-	"Lk",		"Mt",		"Brq",		"Bro",
+	"Lk",		"Lkx",		
+	"Mt",		"Brq",		"Bro",
 	"Brc",		"%C",		"Es",		"En",
 	"Dx",		"%Q",		"br",		"sp",
-	"%U",		"Ta",		"ll",		"text",
+	"%U",		"Ta",		"ll",		"Ix",
+	"text",
 	};
 
 const	char *const __mdoc_argnames[MDOC_ARG_MAX] = {
Index: mdoc.h
===================================================================
RCS file: /home/cvs/mdocml/mdocml/mdoc.h,v
retrieving revision 1.136
diff -u -p -r1.136 mdoc.h
--- mdoc.h	12 Feb 2015 12:24:33 -0000	1.136
+++ mdoc.h	12 Mar 2015 02:49:09 -0000
@@ -126,6 +126,7 @@ enum	mdoct {
 	MDOC_Lb,
 	MDOC_Lp,
 	MDOC_Lk,
+	MDOC_Lkx,
 	MDOC_Mt,
 	MDOC_Brq,
 	MDOC_Bro,
@@ -140,6 +141,7 @@ enum	mdoct {
 	MDOC__U,
 	MDOC_Ta,
 	MDOC_ll,
+	MDOC_Ix,
 	MDOC_MAX
 };
 
Index: mdoc_html.c
===================================================================
RCS file: /home/cvs/mdocml/mdocml/mdoc_html.c,v
retrieving revision 1.226
diff -u -p -r1.226 mdoc_html.c
--- mdoc_html.c	3 Mar 2015 21:11:34 -0000	1.226
+++ mdoc_html.c	12 Mar 2015 02:49:10 -0000
@@ -92,6 +92,7 @@ static	int		  mdoc_ic_pre(MDOC_ARGS);
 static	int		  mdoc_igndelim_pre(MDOC_ARGS);
 static	int		  mdoc_in_pre(MDOC_ARGS);
 static	int		  mdoc_it_pre(MDOC_ARGS);
+static	int		  mdoc_ix_pre(MDOC_ARGS);
 static	int		  mdoc_lb_pre(MDOC_ARGS);
 static	int		  mdoc_li_pre(MDOC_ARGS);
 static	int		  mdoc_lk_pre(MDOC_ARGS);
@@ -231,6 +232,7 @@ static	const struct htmlmdoc mdocs[MDOC_
 	{mdoc_lb_pre, NULL}, /* Lb */
 	{mdoc_pp_pre, NULL}, /* Lp */
 	{mdoc_lk_pre, NULL}, /* Lk */
+	{mdoc_lk_pre, NULL}, /* Lkx */
 	{mdoc_mt_pre, NULL}, /* Mt */
 	{mdoc_quote_pre, mdoc_quote_post}, /* Brq */
 	{mdoc_quote_pre, mdoc_quote_post}, /* Bro */
@@ -245,6 +247,7 @@ static	const struct htmlmdoc mdocs[MDOC_
 	{mdoc__x_pre, mdoc__x_post}, /* %U */
 	{NULL, NULL}, /* Ta */
 	{mdoc_skip_pre, NULL}, /* ll */
+	{mdoc_ix_pre, NULL}, /* Ix */
 };
 
 static	const char * const lists[LIST_MAX] = {
@@ -538,6 +541,25 @@ mdoc_root_pre(MDOC_ARGS)
 }
 
 static int
+mdoc_ix_pre(MDOC_ARGS)
+{
+	struct htmlpair	 tag;
+
+	bufinit(h);
+	bufcat(h, "index-");
+
+	for (n = n->child; n && MDOC_TEXT == n->type; ) {
+		bufcat_id(h, n->string);
+		if (NULL != (n = n->next))
+			bufcat_id(h, " ");
+	}
+
+	PAIR_ID_INIT(&tag, h->buf);
+	print_otag(h, TAG_A, 1, &tag);
+	return(0);
+}
+
+static int
 mdoc_sh_pre(MDOC_ARGS)
 {
 	struct htmlpair	 tag;
@@ -556,7 +578,7 @@ mdoc_sh_pre(MDOC_ARGS)
 	}
 
 	bufinit(h);
-	bufcat(h, "x");
+	bufcat(h, "index-");
 
 	for (n = n->child; n && MDOC_TEXT == n->type; ) {
 		bufcat_id(h, n->string);
@@ -586,7 +608,7 @@ mdoc_ss_pre(MDOC_ARGS)
 		return(1);
 
 	bufinit(h);
-	bufcat(h, "x");
+	bufcat(h, "index-");
 
 	for (n = n->child; n && MDOC_TEXT == n->type; ) {
 		bufcat_id(h, n->string);
@@ -696,33 +718,56 @@ static int
 mdoc_xr_pre(MDOC_ARGS)
 {
 	struct htmlpair	 tag[2];
+	const char	*name, *sec, *index, *desc;
+	struct tag	*t;
 
-	if (NULL == n->child)
+	if (NULL == (n = n->child))
 		return(0);
 
+	name = n->string;
+	sec = desc = index = NULL;
+	if (NULL != n->next) {
+		sec = n->next->string;
+		if (NULL != n->next->next) {
+			index = desc = n->next->next->string;
+			if (NULL != n->next->next->next)
+				desc = n->next->next->next->string;
+		}
+	}
+
 	PAIR_CLASS_INIT(&tag[0], "link-man");
 
 	if (h->base_man) {
-		buffmt_man(h, n->child->string,
-		    n->child->next ?
-		    n->child->next->string : NULL);
+		buffmt_man(h, name, sec, NULL);
 		PAIR_HREF_INIT(&tag[1], h->buf);
-		print_otag(h, TAG_A, 2, tag);
+		t = print_otag(h, TAG_A, 2, tag);
 	} else
-		print_otag(h, TAG_A, 1, tag);
+		t = print_otag(h, TAG_A, 1, tag);
 
-	n = n->child;
-	print_text(h, n->string);
+	print_text(h, name);
 
-	if (NULL == (n = n->next))
-		return(0);
+	if (NULL != index) {
+		h->flags |= HTML_NOSPACE;
+		print_text(h, "(");
+		h->flags |= HTML_NOSPACE;
+		print_text(h, index);
+		h->flags |= HTML_NOSPACE;
+		print_text(h, ")");
+	}
+
+	if (NULL != desc) {
+		print_tagq(h, t);
+		h->flags |= HTML_NOSPACE;
+		print_text(h, ", section");
+		if (h->base_man) {
+			buffmt_man(h, name, sec, index);
+			PAIR_HREF_INIT(&tag[1], h->buf);
+			print_otag(h, TAG_A, 2, tag);
+		} else
+			print_otag(h, TAG_A, 1, tag);
+		print_text(h, desc);
+	}
 
-	h->flags |= HTML_NOSPACE;
-	print_text(h, "(");
-	h->flags |= HTML_NOSPACE;
-	print_text(h, n->string);
-	h->flags |= HTML_NOSPACE;
-	print_text(h, ")");
 	return(0);
 }
 
@@ -1104,7 +1149,7 @@ mdoc_sx_pre(MDOC_ARGS)
 	struct htmlpair	 tag[2];
 
 	bufinit(h);
-	bufcat(h, "#x");
+	bufcat(h, "#index-");
 
 	for (n = n->child; n; ) {
 		bufcat_id(h, n->string);
@@ -1592,14 +1637,23 @@ static int
 mdoc_lk_pre(MDOC_ARGS)
 {
 	struct htmlpair	 tag[2];
+	enum mdoct	 type = n->tok;
 
 	if (NULL == (n = n->child))
 		return(0);
 
 	assert(MDOC_TEXT == n->type);
 
-	PAIR_CLASS_INIT(&tag[0], "link-ext");
-	PAIR_HREF_INIT(&tag[1], n->string);
+	if (MDOC_Lkx == type) {
+		PAIR_CLASS_INIT(&tag[0], "link-int");
+		bufinit(h);
+		bufcat(h, "#index-");
+		bufcat_id(h, n->string);
+		PAIR_HREF_INIT(&tag[1], h->buf);
+	} else  {
+		PAIR_CLASS_INIT(&tag[0], "link-ext");
+		PAIR_HREF_INIT(&tag[1], n->string);
+	}
 
 	print_otag(h, TAG_A, 2, tag);
 
Index: mdoc_macro.c
===================================================================
RCS file: /home/cvs/mdocml/mdocml/mdoc_macro.c,v
retrieving revision 1.183
diff -u -p -r1.183 mdoc_macro.c
--- mdoc_macro.c	12 Feb 2015 12:24:33 -0000	1.183
+++ mdoc_macro.c	12 Mar 2015 02:49:10 -0000
@@ -180,6 +180,7 @@ const	struct mdoc_macro __mdoc_macros[MD
 	{ in_line, 0 }, /* Lb */
 	{ in_line_eoln, 0 }, /* Lp */
 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Lk */
+	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Lkx */
 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Mt */
 	{ blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Brq */
 	{ blk_part_exp, MDOC_CALLABLE | MDOC_PARSED |
@@ -196,6 +197,7 @@ const	struct mdoc_macro __mdoc_macros[MD
 	{ in_line_eoln, 0 }, /* %U */
 	{ phrase_ta, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Ta */
 	{ in_line_eoln, MDOC_PROLOGUE }, /* ll */
+	{ in_line_eoln, MDOC_JOIN }, /* Ix */
 };
 
 const	struct mdoc_macro * const mdoc_macros = __mdoc_macros;
@@ -1288,9 +1290,10 @@ in_line_argn(MACRO_PROT_ARGS)
 	case MDOC_Bx:
 		/* FALLTHROUGH */
 	case MDOC_Es:
-		/* FALLTHROUGH */
-	case MDOC_Xr:
 		maxargs = 2;
+		break;
+	case MDOC_Xr:
+		maxargs = 4;
 		break;
 	default:
 		maxargs = 1;
Index: mdoc_term.c
===================================================================
RCS file: /home/cvs/mdocml/mdocml/mdoc_term.c,v
retrieving revision 1.313
diff -u -p -r1.313 mdoc_term.c
--- mdoc_term.c	6 Mar 2015 15:48:52 -0000	1.313
+++ mdoc_term.c	12 Mar 2015 02:49:11 -0000
@@ -232,6 +232,7 @@ static	const struct termact termacts[MDO
 	{ NULL, termp_lb_post }, /* Lb */
 	{ termp_sp_pre, NULL }, /* Lp */
 	{ termp_lk_pre, NULL }, /* Lk */
+	{ termp_lk_pre, NULL }, /* Lkx */
 	{ termp_under_pre, NULL }, /* Mt */
 	{ termp_quote_pre, termp_quote_post }, /* Brq */
 	{ termp_quote_pre, termp_quote_post }, /* Bro */
@@ -246,6 +247,7 @@ static	const struct termact termacts[MDO
 	{ NULL, termp____post }, /* %U */
 	{ NULL, NULL }, /* Ta */
 	{ termp_ll_pre, NULL }, /* ll */
+	{ termp_skip_pre, NULL }, /* Ix */
 };
 
 
@@ -1257,6 +1259,16 @@ termp_xr_pre(DECL_ARGS)
 	p->flags |= TERMP_NOSPACE;
 	term_word(p, ")");
 
+	if (NULL == (n = n->next)) 
+		return(0);
+	
+	p->flags |= TERMP_NOSPACE;
+	term_word(p, " section");
+	if (NULL != n->next)
+		term_word(p, n->next->string);
+	else
+		term_word(p, n->string);
+
 	return(0);
 }
 
@@ -2174,6 +2186,9 @@ termp_lk_pre(DECL_ARGS)
 	if (NULL == (link = n->child))
 		return(0);
 
+	if (NULL != link->next)
+		link = link->next;
+
 	if (NULL != (descr = link->next)) {
 		term_fontpush(p, TERMFONT_UNDER);
 		while (NULL != descr) {
@@ -2188,7 +2203,6 @@ termp_lk_pre(DECL_ARGS)
 	term_fontpush(p, TERMFONT_BOLD);
 	term_word(p, link->string);
 	term_fontpop(p);
-
 	return(0);
 }
 

                 reply	other threads:[~2015-03-12  2:51 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=5500FF15.2090108@bsd.lv \
    --to=kristaps@bsd.lv \
    --cc=discuss@mdocml.bsd.lv \
    /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.
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 NNTP newsgroup(s).