def create_parser(self):
        """Create the CLI parser."""
        parser = argparse.ArgumentParser(
            description=PROGRAM_DESCRIPTION,
            formatter_class=argparse.RawDescriptionHelpFormatter,
            epilog=textwrap.dedent(PROGRAM_EPILOG))

        parser.add_argument(
            'filename',
            metavar='FILE_NAME',
            nargs='*',
            help='the I/O file name')

        subparsers = parser.add_subparsers(
            dest='parser', title='markdown parser')
        subparsers.required = True

        # github + cmark + gitlab + commonmarker.
        github = subparsers.add_parser(
            'github',
            aliases=['cmark', 'gitlab', 'commonmarker'],
            description='Use Commonmark rules to generate an output. If no \
                         option is selected, the default output will be an \
                         unordered list with the respective default values \
                         as listed below')
        megroup = github.add_mutually_exclusive_group()
        megroup.add_argument(
            '-u',
            '--unordered-list-marker',
            choices=md_parser['github']['list']['unordered']['bullet_markers'],
            nargs='?',
            const=md_parser['github']['list']['unordered']['default_marker'],
            help='set the marker and enables unordered list. Defaults to ' +
            md_parser['github']['list']['unordered']['default_marker'])
        megroup.add_argument(
            '-o',
            '--ordered-list-marker',
            choices=md_parser['github']['list']['ordered']['closing_markers'],
            nargs='?',
            const=md_parser['github']['list']['ordered']
            ['default_closing_marker'],
            help='set the marker and enables ordered lists. Defaults to ' +
            md_parser['github']['list']['ordered']['default_closing_marker'])
        github.add_argument(
            '-l',
            '--header-levels',
            choices=[
                str(i)
                for i in range(1, md_parser['github']['header']['max_levels'] +
                               1)
            ],
            nargs='?',
            const=str(md_parser['github']['header']['default_keep_levels']),
            help='set the maximum level of headers to be considered as part \
                  of the TOC. Defaults to ' + str(
                md_parser['github']['header']['default_keep_levels']))
        github.set_defaults(
            header_levels=md_parser['github']['header']['default_keep_levels'])

        # Redcarpet.
        redcarpet = subparsers.add_parser(
            'redcarpet',
            description='Use Redcarpet rules to generate an output. If no \
                         option is selected, the default output will be an \
                         unordered list with the respective default values \
                         as listed below. Gitlab rules are the same as \
                         Redcarpet except that conflicts are avoided with \
                         duplicate headers.')

        megroup = redcarpet.add_mutually_exclusive_group()
        megroup.add_argument(
            '-u',
            '--unordered-list-marker',
            choices=md_parser['redcarpet']['list']['unordered']
            ['bullet_markers'],
            nargs='?',
            const=md_parser['redcarpet']['list']['unordered']
            ['default_marker'],
            help='set the marker and enables unordered list. Defaults to ' +
            md_parser['redcarpet']['list']['unordered']['default_marker'])
        megroup.add_argument(
            '-o',
            '--ordered-list-marker',
            choices=md_parser['redcarpet']['list']['ordered']
            ['closing_markers'],
            nargs='?',
            const=md_parser['redcarpet']['list']['ordered']
            ['default_closing_marker'],
            help='set the marker and enables ordered lists. Defaults to ' +
            md_parser['redcarpet']['list']['ordered']['default_closing_marker']
        )
        redcarpet.add_argument(
            '-l',
            '--header-levels',
            choices=[
                str(i) for i in range(
                    1, md_parser['redcarpet']['header']['max_levels'] + 1)
            ],
            nargs='?',
            const=str(md_parser['redcarpet']['header']['default_keep_levels']),
            help='set the maximum level of headers to be considered as part \
                  of the TOC. Defaults to ' + str(
                md_parser['redcarpet']['header']['default_keep_levels']))
        redcarpet.set_defaults(header_levels=md_parser['redcarpet']['header']
                               ['default_keep_levels'])

        c_or_i = parser.add_mutually_exclusive_group()
        c_or_i.add_argument(
            '-c',
            '--no-list-coherence',
            action='store_true',
            help='avoids checking for TOC list coherence')
        c_or_i.add_argument(
            '-i',
            '--no-indentation',
            action='store_true',
            help='avoids adding indentations to the TOC')

        parser.add_argument(
            '-l',
            '--no-links',
            action='store_true',
            help='avoids adding links to the TOC')
        parser.add_argument(
            '-m',
            '--toc-marker',
            metavar='TOC_MARKER',
            help='set the string to be used as the marker for positioning the \
                  table of contents. Defaults to ' +
            common_defaults['toc_marker'])
        parser.add_argument(
            '-p',
            '--in-place',
            action='store_true',
            help='overwrite the input file')
        parser.add_argument(
            '-v',
            '--version',
            action='version',
            version=VERSION_NAME + ' ' + VERSION_NUMBER)

        parser.set_defaults(toc_marker=common_defaults['toc_marker'])
        parser.set_defaults(func=CliToApi().write_toc)

        return parser