#!/usr/bin/env python3
#
# Copyright (C) 2023 Jonathan A. Poritz
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
import argparse
import re
import sys
import warnings
if not sys.warnoptions:
warnings.simplefilter("ignore")
#
# setting up arguments
#
parser = argparse.ArgumentParser(description='Prints layers of headings from an html file such as the "tidy_book.html" produced by OOprep')
parser.add_argument("inputfile", help="File containing html from which to extract outline information.", type=argparse.FileType('r'))
parser.add_argument('-c', '--chapter_nos', help='chapters have numbers, which are used in building the outline numbering', action='store_true')
parser.add_argument('-n', '--numbering', help='print also chapter/section/sub... numbering as it should be', action='store_true')
parser.add_argument('-d', '--dividers', help='print horizontal dividers between blocks at different levels', action='store_true')
parser.add_argument('-t', '--tags', help='print header tags as in the html file', action='store_true')
args = parser.parse_args()
#
# initializing counts of found objects, helpers for output
#
line_no = 0
chap_no = 0
sec_no = 0
ssec_no = 0
sssec_no = 0
ssssec_no = 0
nesting_warnings = 0
tag_warnings = 0
last_level = 0
if args.numbering:
spaces = 3
else:
spaces = 2
def warn(s):
print(f'WARNING: on line {line_no}, with content\n{l}\n{s}')
#
# looping through input file, keeping track of lines which start and end with
# and , also checks for improper levels of heading levels
#
for line in args.inputfile:
line_no += 1
l = line.strip()
if l[:4]=="
":
if l[-5:]!="
":
warn("expecting entire line bracketed in ..
")
if args.tags:
l = l[4:]
elif not args.tags:
l = l[4:-5]
if last_level != 1 and args.dividers:
print("-"*80)
last_level = 1
if args.chapter_nos:
num = l.split()[1]
if num[-1] == ":":
num = num[:-1]
chap_no = int(num)
else:
chap_no += 1
sec_no = 0
ssec_no = 0
sssec_no = 0
ssssec_no = 0
if args.numbering:
print(f'{chap_no:2} {l}')
else:
print(l)
continue
if l[:4]=="":
if l[-5:]!="
":
warn("expecting entire line bracketed in ..
")
if args.tags:
l = l[4:]
elif not args.tags:
l = l[4:-5]
if last_level != 2 and args.dividers:
print(" "*spaces + "-"*(77-spaces))
last_level = 2
if chap_no == 0:
nesting_warnings += 1
warn("Section without enclosing chapter")
sec_no += 1
ssec_no = 0
sssec_no = 0
ssssec_no = 0
if args.numbering:
print(f'{chap_no:2}.{sec_no:2} {l}')
else:
print(" "+l)
continue
if l[:4]=="":
if l[-5:]!="
":
warn("expecting entire line bracketed in ..
")
if args.tags:
l = l[4:]
elif not args.tags:
l = l[4:-5]
if last_level != 3 and args.dividers:
print(" "*spaces*2 + "-"*(77-spaces*2))
last_level = 3
if sec_no == 0:
nesting_warnings += 1
if chap_no == 0:
warn("Subsection without enclosing chapter or section")
else:
warn("Subsection without enclosing section")
ssec_no += 1
sssec_no = 0
ssssec_no = 0
if args.numbering:
print(f'{chap_no:2}.{sec_no:2}.{ssec_no:2} {l}')
else:
print(" "+l)
continue
if l[:4]=="":
if l[-5:]!="
":
warn("expecting entire line bracketed in ..
")
if args.tags:
l = l[4:]
elif not args.tags:
l = l[4:-5]
if last_level != 4 and args.dividers:
print(" "*spaces*3 + "-"*(77-spaces*3))
last_level = 4
if ssec_no ==0:
nesting_warnings += 1
if sec_no == 0:
if chap_no == 0:
warn("Subsubsection without enclosing chapter, section, or subsection")
else:
warn("Subsubsection without enclosing section or subsection")
else:
warn("Subsubsection without enclosing subsection")
sssec_no += 1
ssssec_no = 0
if args.numbering:
print(f'{chap_no:2}.{sec_no:2}.{ssec_no:2}.{sssec_no:2} {l}')
else:
print(" "+l)
continue
if l[:4]=="":
if l[-5:]!="
":
warn("expecting entire line bracketed in ..
")
if args.tags:
l = l[4:]
elif not args.tags:
l = l[4:-5]
if last_level != 5 and args.dividers:
print(" "*spaces*4 + "-"*(77-spaces*4))
last_level = 5
if sssec_no == 0:
nesting_warnings += 1
if ssec_no == 0:
if sec_no == 0:
if chap_no == 0:
warn("Subsubsubsection without enclosing chapter, section, subsection, or subsubsection")
else:
warn("Subsubsubsection without enclosing section, subsection, or subsubsection")
else:
warn("Subsubsubsection without enclosing subsection or subsubsection")
else:
warn("Subsubsubsection without enclosing subsubsection")
ssssec_no += 1
if args.numbering:
print(f'{chap_no:2}.{sec_no:2}.{ssec_no:2}.{sssec_no:2}.{ssssec_no:2} {l}')
else:
print(" "+l)
if nesting_warnings >1:
print(f"Note: there were {nesting_warnings} improperly nested section warnings")
if nesting_warnings == 1:
print(f"Note: there was an improperly nested section warning")