2019 Jan 07 By itops_admin 0 comment

I am quite a documents aficionado, I take care to make sure any of my projects are well documented and easy to be used in the future, for others and me too – we all forget what we did a year ago especially the small details – that is why I feel the most important part of a project is the documentations.

My favorite document style right now is MarkDown, why is that? well:

  • MarkDown is text base meant it can be read (info only) by anyone anywhere without the need for a specific software (although missing a lot of format related stuff like tables).
  • The capabilities of MarkDown regarding code segments and links is very easy to perform and the result is easy to read.
  • The text based give us easy version control use for the documentations + using bitbucket/github/gitlab you can easily save your entire documentation with structure with easy access.
  • It is already widely used in opensource and provided high quality documentations
  • Writing the document is easy and fast – My mouse does not need to move to click buttons or I need to remember multiple key combinations to remember how to do something – all is in the syntax.

At this point you might say: “But wait there are better…” – and I will not argue with you – every one with what he likes and prefer (and off curse depend on the needs)

But there is on thing that is missing from markdown is TOC (Table Of Content).
For some unknown reason phrasing engines like github does not provide TOC automatically like you can in any Wiki or Word Document.

So how can you mitigate this issues?

Well there are several solutions out there:

But wait – what if you don’t have access to any of that?
What if you can’t install any software or use and editor?
For example working with a client computer and not your own – or working on a server to document stuff (another good reason to use MarkDown)
What do you do in a situation like that?

The question above was the one that occupied me so I wrote a very mall program using bash – which will be almost anywhere you look and be (ok ok not windows – unless you have windows 10 with WSL)

So I wrote this little script to generate the TOC in bash:

#!/bin/bash

MD_FILE=$1

CODE_SEGMENT=1; cat $MD_FILE | while read line
               do
                   TRIMMED_LINE=`echo $line | sed 's/^[ \t]*//;s/[ \t]*$//'` ; # Get the line without spaces at the begining or the end
                   if [[ $TRIMMED_LINE == "#"* ]]                               # Finding all the lines starting with #
                   then
                       if [[ $CODE_SEGMENT -eq 1 ]]                             # Making sure the # isn't part of code segment
                       then
                           echo $line | sed 's/^[ \t]*//;s/[ \t]*$//' ;         # Print the line without start and end spaces
                       fi
                   else
                       if [[ $TRIMMED_LINE == "\`\`\`"* ]]                      # This If toggle between code segment and regular segment
                           then
                               CODE_SEGMENT=$(($CODE_SEGMENT^1))
                           fi
                   fi
               done | grep "^#" | while read line
                                  do
                                      echo -n $line |sed -e "s/[^#]//g" | sed "s/#/  /g" | head -c -2; # Print Spaces based on the amount of # - 2 spaces for each # and remove the head 2 spaces
                                      echo -n "*" ;                                                    # Print the * so this will be list
                                      echo -n " [";                                                    # Start markdown link syntax
                                      echo -n $line |tr -d "#"|sed "s/^ //g"|sed "s/\r//g"|sed "s/\n//g"; # Print the line without # in the biggining | trimming the space in the begining | remove new line
                                      echo -n "](#" ;                                                      # Continue markdown link syntax
                                      echo -n $line | tr -d "#"| tr -d "-" | sed "s/\r//g"|sed "s/\n//g" | sed 's/^[ \t]*//;s/[ \t]*$//'| sed 's/ \+/ /g' | tr " " "-" ; # for more info See below
                                      echo ")";
                                  done;

# Detailed information about the last line:
#
#                         echo -n $line |   # Print the line without new line at the end
#                            tr -d "#"|     # Remove all "#" Characters
#                            tr -d "-" |    # Remove all - characters (links does not support them)
#                            sed "s/\r//g"|sed "s/\n//g" |  # Remove the newline in the line
#                            sed 's/^[ \t]*//;s/[ \t]*$//'|  # Remove all start end end spaces
#                            sed 's/ \+/ /g' |            # Trim all multiple spaces to only one
#                            tr " " "-" ;                     # Replace all the spaces with "-" (markdown link needs this)"

As you can see in the code it uses only the very basic commands so no matter in which unix based system you are probably gonna be ok with that.

To sweeten the deal I’ve also created oneliner so you can use it in the field with only copy paste

CODE_SEGMENT=1; cat <MD_FILE_NAME> | while read line; do TRIMMED_LINE=`echo $line | sed 's/^[ \t]*//;s/[ \t]*$//'` ; if [[ $TRIMMED_LINE == "#"* ]]; then if [[ $CODE_SEGMENT -eq 1 ]]; then echo $line | sed 's/^[ \t]*//;s/[ \t]*$//' ; fi else if [[ $TRIMMED_LINE == "\`\`\`"* ]]; then CODE_SEGMENT=$(($CODE_SEGMENT^1)); fi; fi; done | grep "^#" | while read line; do echo -n $line |sed -e "s/[^#]//g" | sed "s/#/  /g" | head -c -2; echo -n "*" ; echo -n " ["; echo -n $line |tr -d "#"|sed "s/^ //g"|sed "s/\r//g"|sed "s/\n//g"; echo -n "](#" ; echo -n $line | tr -d "#"| tr -d "-" | sed "s/\r//g"|sed "s/\n//g" | sed 's/^[ \t]*//;s/[ \t]*$//'| sed 's/ \+/ /g' | tr " " "-" ; echo ")"; done;

(Just remember to change <MD_FILE_NAME> with the name of the MD file)

 

 

Here is an example:

~$ cat Text.md
# Header 1
## Sub Header 1
## Sub Header 2
### Sub Sub Header 1
# Header 2
```
# Some Comment in the the code
```
### Sub Sub Header 2

~$ CODE_SEGMENT=1; cat Text.md | while read line; do TRIMMED_LINE=`echo $line | sed 's/^[ \t]*//;s/[ \t]*$//'` ; if [[ $TRIMMED_LINE == "#"* ]]; then if [[ $CODE_SEGMENT -eq 1 ]]; then echo $line | sed 's/^[ \t]*//;s
/[ \t]*$//' ; fi else if [[ $TRIMMED_LINE == "\`\`\`"* ]]; then CODE_SEGMENT=$(($CODE_SEGMENT^1)); fi; fi; done | grep "^#" | while read line; do echo -n $line |sed -e "s/[^#]//g" | sed "s/#/  /g" | head -c -2; echo -n "*" ; echo -n " ["
; echo -n $line |tr -d "#"|sed "s/^ //g"|sed "s/\r//g"|sed "s/\n//g"; echo -n "](#" ; echo -n $line | tr -d "#"| tr -d "-" | sed "s/\r//g"|sed "s/\n//g" | sed 's/^[ \t]*//;s/[ \t]*$//'| sed 's/ \+/ /g' | tr " " "-" ; echo ")"; done;
* [Header 1](#Header-1)
  * [Sub Header 1](#Sub-Header-1)
  * [Sub Header 2](#Sub-Header-2)
    * [Sub Sub Header 1](#Sub-Sub-Header-1)
* [Header 2](#Header-2)
    * [Sub Sub Header 2](#Sub-Sub-Header-2)

See in the example above that the script ignore comments in code segments.

 

Now next time you stuck and need to create a document without any way to use normal software you are one liner away from TOC in MarkDown

Leave a Reply

Your email address will not be published. Required fields are marked *