Skip to content

Commit

Permalink
Add the mktoc tool to make a table of content
Browse files Browse the repository at this point in the history
The `mktoc` script is in `dev/tools`. It is mostly in `awk`.
There are 2 test cases in `dev/tools/test/mktoc` with a `Makefile` in
`tools/test`.

I improvised this directory hierarchy; it is not set in stone.
  • Loading branch information
Villetaneuse committed May 14, 2024
1 parent d902193 commit 23027dc
Show file tree
Hide file tree
Showing 6 changed files with 495 additions and 0 deletions.
118 changes: 118 additions & 0 deletions dev/tools/mktoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
#!/bin/sh

usage()
{
cat <<EOF
Usage: mktoc FILE...
Number sections, subsections and subsubsections in coqdoc'ed documented
Coq FILEs.
Also write a Table of content after a line
*** Table of content
if it is present in the file.
The section, subsection and subsubsections have the following format:
(** ** A section *)
(** *** A subsection *)
(** **** A subsubsection *)
It is possible to reuse mktoc on the same file (e.g. to update the numbering and
table of content after some changes).
EOF
}

case $0 in
0)
usage
exit 1
esac

case $1 in
-h | --help)
usage
exit 0
esac

tmptoc=tmptoc$$.tmp
tmpfile=tmp_mktoc_$$.tmp
TOCSTRING='\\*\\*\\* Table of content'

trap "rm -vf $tmptoc $tmpfile" EXIT SIGINT SIGTERM SIGABRT

for f; do
# First pass to get the numbering right and write the TOC in a temporary file
>"$tmptoc"
awk -v "tmp=$tmptoc" '
function spaces(num_spaces) {
res = "";
for (i = 0; i < num_spaces; i++)
res = " " res;
return res;
}
function remove_numbering() {
if ($3 ~ /^[0-9.]+$/)
$3 = "";
gsub(/[[:blank:]]+/, " ");
}
BEGIN {
nb_levels = 0;
}
/^\(\*\*[[:blank:]]+\*\*+/ {
remove_numbering()
level = length($2) - 1;
if (level > nb_levels)
nb_levels = level
numbering[level - 1]++;
for (i = level; i < nb_levels; i++)
numbering[i] = 0
title = $3;
for (i = 4; i < NF; i++)
title = title " " $i
if (level == 1) {
item = numbering[level - 1] ".";
} else {
item = numbering[0];
for (i = 1; i < level; i++)
item = item "." numbering[i]
}
printf("(** %s %s %s *)\n", $2, item, title);
printf("%s- %s %s\n", spaces(2 * (level - 1)), item, title) >>tmp
next
}
1
' <"$f" >"$tmpfile"

mv "$tmpfile" "$f"

# Second pass to write the TOC
awk -v "tmp=$tmptoc" -v "tocstring=$TOCSTRING" '
function spaces(num_spaces) {
res = "";
for (i = 0; i < num_spaces; i++)
res = " " res;
return res;
}
$0 ~ tocstring {
# we need to save the indentation level
match($0, /^ */);
indent = RLENGTH;
print $0;
# next line(s) should be empty, we also skip any previous TOC
do {
getline
} while ($0 ~ /^ *$/ || $0 ~ /^ *- [0-9][0-9.]+/);
# now we need to dump the new TOC
printf("\n");
while (getline line <tmp) {
printf("%s%s\n", spaces(indent), line)
}
printf("\n");
}
1
' <"$f" >"$tmpfile"

mv "$tmpfile" "$f"
done
14 changes: 14 additions & 0 deletions dev/tools/test/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
all: test-mkdoc

test-mkdoc:
if [ -d mktoc/out ]; then rm -r mktoc/out; fi
mkdir mktoc/out
cp mktoc/example1.v mktoc/example2.v mktoc/out
../mktoc mktoc/out/example1.v mktoc/out/example2.v
@diff mktoc/out/example1.v mktoc/expected/example1.v || \
printf "test-mkdoc example1.v FAILED\n" 1>&2 && \
printf "test-mkdoc example1.v SUCCEEDED\n" 1>&2
@diff mktoc/out/example2.v mktoc/expected/example2.v || \
printf "test-mkdoc example2.v FAILED\n" 1>&2 && \
printf "test-mkdoc example2.v SUCCEEDED\n" 1>&2
rm -r mktoc/out
83 changes: 83 additions & 0 deletions dev/tools/test/mktoc/example1.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
(** * Test file 1 for mktoc
*** Table of content
Here is some random text we hope will remain after mktoc.
*** Some other part of this tutorial's header
*)

(** In this tutorial, we are going to search for lemmas, mostly about natural
numbers.
We already have all lemmas and definitions from the prelude ([Coq.Init]),
and we require the library file [Coq.Arith.PeanoNat] which adds hundreds
of new constants.
*)

From Coq Require Import PeanoNat.

(** ** 42. Basic [Search] queries *)

(** In its most basic form, one searches for lemmas or definitions containing
- a given constant, eg [Nat.add], or [nat]
- a given string to be part of the identifier
- a given notation
*)

(** Search all lemmas where the type [nat] and the operators (_ * _) and
(_ + _) occur. *)
Search nat (_ + _) (_ * _). (* still too much *)

(** ** 3.3.5 More sophisticated patterns *)

(** Some text *)

(** ** Filter results by logical kind and or syntax in queries *)

(** We can also [Search] for a constant defined with a specific keyword.
For instance, the following lists all [Lemma]s whose names contain "add"
and types contain [0]: *)
Search "add" 0 is:Lemma.

(** ** 10.1 Disambiguating strings in Search queries *)

(** *** Some subsection *)

(** **** 2 Some subsubsection *)

(** We have seen two different usages of strings in search queries, namely,
searching for constants whose name contains the string, such as: *)
Search "comm".

(** **** 42 Another one *)

(** or, search for constants whose type contain a notation, such as: *)
Search "||".
Search "+".

(** *** A Great subsection *)

(** **** A subsubsection ! *)

(** We have seen two different usages of strings in search queries, namely,
searching for constants whose name contains the string, such as: *)
Search "comm".

(** **** Another subsubsection *)

(** With some text inside *)

(** **** Yet another subsubsection *)

(** So, what really happens here?
Blah, blah, ... *)

(** ** Searching for constants with given hypotheses (parameters) or conclusions (return type) *)

(** Finally the [head] keyword is just a shorthand for [headconcl] or [headhyp]: *)
Search head:"<->".

(** ** 0.0.0 Searching inside or outside a specific module *)

(** We hope mktoc works. *)
88 changes: 88 additions & 0 deletions dev/tools/test/mktoc/example2.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
(** * Test file 1 for mktoc with a garbage TOC to remove
*** Table of content
- 1. This
- 1.1 That
- 1.2 One
- 2. A
- 2.1 B
- 2.2 C
*** Some other part of this tutorial's header
*)

(** In this tutorial, we are going to search for lemmas, mostly about natural
numbers.
We already have all lemmas and definitions from the prelude ([Coq.Init]),
and we require the library file [Coq.Arith.PeanoNat] which adds hundreds
of new constants.
*)

From Coq Require Import PeanoNat.

(** ** 42. Basic [Search] queries *)

(** In its most basic form, one searches for lemmas or definitions containing
- a given constant, eg [Nat.add], or [nat]
- a given string to be part of the identifier
- a given notation
*)

(** Search all lemmas where the type [nat] and the operators (_ * _) and
(_ + _) occur. *)
Search nat (_ + _) (_ * _). (* still too much *)

(** ** 3.3.5 More sophisticated patterns *)

(** Some text *)

(** ** Filter results by logical kind and or syntax in queries *)

(** We can also [Search] for a constant defined with a specific keyword.
For instance, the following lists all [Lemma]s whose names contain "add"
and types contain [0]: *)
Search "add" 0 is:Lemma.

(** ** 10.1 Disambiguating strings in Search queries *)

(** *** Some subsection *)

(** **** 2 Some subsubsection *)

(** We have seen two different usages of strings in search queries, namely,
searching for constants whose name contains the string, such as: *)
Search "comm".

(** **** 42 Another one *)

(** or, search for constants whose type contain a notation, such as: *)
Search "||".
Search "+".

(** *** A Great subsection *)

(** **** A subsubsection ! *)

(** We have seen two different usages of strings in search queries, namely,
searching for constants whose name contains the string, such as: *)
Search "comm".

(** **** Another subsubsection *)

(** With some text inside *)

(** **** Yet another subsubsection *)

(** So, what really happens here?
Blah, blah, ... *)

(** ** Searching for constants with given hypotheses (parameters) or conclusions (return type) *)

(** Finally the [head] keyword is just a shorthand for [headconcl] or [headhyp]: *)
Search head:"<->".

(** ** 0.0.0 Searching inside or outside a specific module *)

(** We hope mktoc works. *)
Loading

0 comments on commit 23027dc

Please sign in to comment.