Generate a table of contents from the comments of a file
Project description
toc
toc - Generate a table of contents from the comments of a file
What is it?
toc
is a command line utility that generates the table of contents of a file from a special kind of comments.
Think it as a tree
for the contents of a file, instead of a directory.
Why should I use it?
Few reasons that you may consider:
- it can make your files understandable in seconds, even if you haven't touched them for a while
- you can jump directly to the section you need to edit, because you know where it's located
- it makes you reflect about the structure of your file, making it more logical
- for software developers, it makes your code base more readable to others
How does it work?
First, you have to write the comments representing the different sections of a file.
Second, you run toc
on that file to turn those comments into a table of contents.
Comments are structured in this way:
┌ comment character ("#", "//", "%", ";", "--", etc. according to the language)
│
│ nesting level ("#" repeated 64, 32, 16, 8 or 4 times) section name
│ ┌──────────────────────────────┴───────────────────────────────┐ ┌────┴────┐
// ################################################################ First level
// ################################ Second level
// ################ Third level
// ######## Fourth level
// #### Fifth level
By running toc filename
, you will read the table of contents of that file
// ┌───────────────────────────────────────────────────────────────┐
// │ Contents of test.c │
// ├───────────────────────────────────────────────────────────────┘
// │
// ├──┐First level
// │ └──┐Second level
// │ └──┐Third level
// │ └──┐Fourth level
// │ └── Fifth level
// │
// └───────────────────────────────────────────────────────────────
How can I use it?
Installation
First, you need Python installed in your system.
Then, you can install toc
by running:
pip install tableofcontents
If you are using Arch or Manjaro Linux, you can install toc directly from the AUR.
Read the table of contents
Let's say you want to structure your javascript file "example.js".
Single line comments in this language start with //
.
You open your file and add these comments where you need them:
#!/usr/bin/env node
// ################################################################ Main section
let Section1 = "Write //, 64 hash characters and the name of section"
// ################################ Nested section
let Section2 = "Write //, 32 hash characters and the name of section"
// ################ Nested section
let Section3 = "Write //, 16 hash characters and the name of section"
// ######## Nested section
let Section4 = "Write //, 8 hash characters and the name of section"
// #### Nested section
let Section5 = "Write //, 4 hash characters and the name of section"
If you run toc example.js
, the program will output the following (stdout):
// ┌───────────────────────────────────────────────────────────────┐
// │ Contents of example.js │
// ├───────────────────────────────────────────────────────────────┘
// │
// ├──┐Main section
// │ └──┐Nested section
// │ └──┐Nested section
// │ └──┐Nested section
// │ └── Nested section
// │
// └───────────────────────────────────────────────────────────────
Embed the table of contents in the original file
If you want to output the toc we just saw to the file, you should run toc -f example.js
and get (stderr):
Adding toc to file example.js
By opening "example.js", the file content will be:
Click to view the original `example.js` with toc
#!/usr/bin/env node
// ┌───────────────────────────────────────────────────────────────┐
// │ Contents of example.js │
// ├───────────────────────────────────────────────────────────────┘
// │
// ├──┐Main section
// │ └──┐Nested section
// │ └──┐Nested section
// │ └──┐Nested section
// │ └── Nested section
// │
// └───────────────────────────────────────────────────────────────
// ################################################################ Main section
let Section1 = "Write //, 64 hash characters and the name of section"
// ################################ Nested section
let Section2 = "Write //, 32 hash characters and the name of section"
// ################ Nested section
let Section3 = "Write //, 16 hash characters and the name of section"
// ######## Nested section
let Section4 = "Write //, 8 hash characters and the name of section"
// #### Nested section
let Section5 = "Write //, 4 hash characters and the name of section"
Notice how toc
recognized the shebang for node
and added the table of contents after it.
If you run again toc -f example.js
, it recognizes that there is no need to update the toc, as no changes have been made.
However, if you add new sections to the file and run again toc -f example.js
, it will update the file accordingly:
Updating toc in file example.js
Click to view the modified `example.js` with toc
#!/usr/bin/env node
// ┌───────────────────────────────────────────────────────────────┐
// │ Contents of example.js │
// ├───────────────────────────────────────────────────────────────┘
// │
// ├──┐Main section
// │ ├──┐New section
// │ │ └── Also New section
// │ ├──┐New section
// │ │ └── Also New section
// │ └──┐Nested section
// │ └──┐Nested section
// │ └──┐Nested section
// │ └── Nested section
// │
// └───────────────────────────────────────────────────────────────
// ################################################################ Main section
let Section_1 = "Write //, 64 hash characters and the name of section"
// ################################ New section
let Section_1_1 = "Write //, 32 hash characters and the name of section"
// ################ Also New section
let Section_1_1_1 = "Write //, 32 hash characters and the name of section"
// ################################ New section
let Section_1_1 = "Write //, 32 hash characters and the name of section"
// ################ Also New section
let Section_1_1_1 = "Write //, 32 hash characters and the name of section"
// ################################ Nested section
let Section_1_2 = "Write //, 32 hash characters and the name of section"
// ################ Nested section
let Section_1_2_3 = "Write //, 16 hash characters and the name of section"
// ######## Nested section
let Section_1_2_4 = "Write //, 8 hash characters and the name of section"
// #### Nested section
let Section_1_2_5 = "Write //, 4 hash characters and the name of section"
Use a custom comment character
But how could toc
recognize that //
is the proper comment character for that file?
Well, thanks to AI[^1] toc
supports most programming and markup languages, from COBOL to Carbon.
In case it doesn't work as expected, you can force the behavior by running toc -c "//" example.xyz
.
Show line numbers
For very long files, it may come in handy to run toc -n example.js
to see the line number of each section, similar to the page numbers in the table of contents of a book:
// ┌───────────────────────────────────────────────────────────────┐
// │ Contents of example.js │
// ├───────────────────────────────────────────────────────────────┘
// │
// ├──┐Main section 19
// │ ├──┐New section 23
// │ │ └── Also New section 27
// │ ├──┐New section 31
// │ │ └── Also New section 35
// │ └──┐Nested section 39
// │ └──┐Nested section 43
// │ └──┐Nested section 47
// │ └── Nested section 51
// │
// └───────────────────────────────────────────────────────────────
Process multiple files
If you feel brave enough, you can run toc
over your entire code base, as its AI[^2] will make it:
- skip directories (see
.
below) - skip non-text files (see
toc.cpython-311.pyc
below) - skip non-existing files
- skip non-readable files
- skip non-writable files
- skip files that don't have suitable "section" comments (see
__init__.py
below) - skip files whose toc is already up-to-date (see
toc.py
below) - only edit files whose toc can be added or updated safely[^3] (see
cli.py
below) - preserve shebangs of edited files
Skipping directory .
Skipping empty "#" toc for ./__init__.py
Skipping directory ./__pycache__
Skipping binary file ./__pycache__/toc.cpython-311.pyc
Skipping replacing same toc in file ./toc.py
Updating toc in file ./cli.py
Skipping replacing same toc in file ./example.js
Additionally, you can run toc -h
for usage info and toc -v
to read the current version
Exceptional file types
For Markdown files, you don't need to write comments, just organize your sections with one or more #
.
For Beancount files, it's the same for Markdown, but you use *
instead.
For CSS files, you have to wrap your //
comments between /*
and */
:
Click to view `example.css`
/*
// ################################################################ Landscape touchscreen
*/
@media (orientation: landscape) and (hover: none) and (pointer: coarse) {
/*
// ################################ Element selectors
*/
body {
background-color: blue;
}
} /* end Landscape touchscreen */
For HTML files, you have to wrap your //
comments between <!--
and -->
:
Click to view `example.html`
<!doctype html>
<html lang="en">
<!--
// ################################################################ Head
-->
<head>
<link rel="stylesheet" href="/assets/css/example.css"/>
<script src="/assets/js/example.js"></script>
</head>
<!--
// ################################################################ Body
-->
<body>
<h1>Title</h1>
</body>
</html>
For OCaml files, you have to wrap your *
comments between (*
and *)
:
Click to view `example.ml`
(*
* ################################################################ Unique section
*)
let () = print_endline "Hello, World!"
How can I contribute?
If you have a suggestion or you found an issue, you can use GitHub issues and pull requests to contribute.
What changed from previous versions?
See CHANGELOG.md
[^1]: No, not really, it's just a match-case statement using the file extension, defaulting to "#" [^2]: Not even, it's just a bunch of if-else and try-excepts statement that may prevent catastrophic damage [^3]: The outdated toc to be replaced is defined as the the first match of a non-greedy regex
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Hashes for tableofcontents-2.1.0-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 769eb478c5658e7bc6e6c290526f34f001f45708155c62c1980db0ef7ed00b41 |
|
MD5 | b336d58114f9cac8f88dd8a3eb9a0427 |
|
BLAKE2b-256 | c8dac8a9d249ec89652ffc03a4dcfb3f9c711e74ac0f98fc3535a3e1f7484b39 |