def tabulateAllSegments(phonoString):
    conClassDict = {}
    vowClassDict = {}
    diphthongs = []
    triphthongs = []
    consonants = []
    vowels = []
    apical_vowels = []

    inputPhons = re.split(r'\s*,\s*', phonoString)

    for phon in inputPhons:
        phoneme = Phoneme(phon, *parsePhon(phon))
        if 'consonant' in phoneme.coreSet:
            consonants.append(phoneme)
            if phoneme.seriesSet:
                classMarker = " & ".join(sorted(phoneme.seriesSet))
            else:
                classMarker = "plain"
            if classMarker in conClassDict:
                conClassDict[classMarker].append(phoneme)
            else:
                conClassDict[classMarker] = []
                conClassDict[classMarker].append(phoneme)
        elif 'vowel' in phoneme.coreSet:
            if 'diphthong' in phoneme.coreSet:
                diphthongs.append(phon)
            elif 'triphthong' in phoneme.coreSet:
                triphthongs.append(phon)
            elif 'apical' in phoneme.coreSet:
                apical_vowels.append(phon)
            else:
                vowels.append(phoneme)
                if phoneme.seriesSet:
                    classMarker = " & ".join(sorted(phoneme.seriesSet))
                else:
                    classMarker = "plain"
                if classMarker in vowClassDict:
                    vowClassDict[classMarker].append(phoneme)
                else:
                    vowClassDict[classMarker] = []
                    vowClassDict[classMarker].append(phoneme)
        else:
            raise ValueError("Neither a vowel nor a consonant: %s" % phon)
    out = StringIO()
    if conClassDict:
        out.write("<h2>Consonants</h2>")
        keys = sorted(conClassDict.keys(), key=lambda x: len(x))
        for key in keys:
            out.write("<h3>" + key[0].upper() + key[1:] + " series:</h3>")
            out.write(convert2HTMLAndSpanify(makeTableCons(conClassDict[key])))
    if vowClassDict:
        out.write("<h2>Vowels</h2>")
        keys = sorted(vowClassDict.keys(), key=lambda x: len(x))
        for key in keys:
            out.write("<h3>" + key[0].upper() + key[1:] + " series:</h3>")
            out.write(convert2HTMLAndSpanify(makeTableVow(vowClassDict[key])))
    if apical_vowels:
        out.write("<h3>Apical vowels:</h3>")
        out.write("<p>" + ", ".join(spanify(el) for el in apical_vowels))
    if diphthongs:
        out.write("<h3>Diphthongs:</h3>")
        out.write("<p>" + ", ".join(spanify(el) for el in diphthongs))
    if triphthongs:
        out.write("<h3>Triphthongs:</h3>")
        out.write("<p>" + ", ".join(spanify(el) for el in triphthongs))
    return out.getvalue()
def tabulateAllSegments(phonoString):
    conClassDict  = {}
    vowClassDict  = {}
    diphthongs    = []
    triphthongs   = []
    consonants    = []
    vowels        = []
    apical_vowels = []

    inputPhons = re.split(r'\s*,\s*', phonoString)

    for phon in inputPhons:
        phoneme = Phoneme(phon, *parsePhon(phon))
        if 'consonant' in phoneme.coreSet:
            consonants.append(phoneme)
            if phoneme.seriesSet:
                classMarker = " & ".join(sorted(phoneme.seriesSet))
            else:
                classMarker = "plain"
            if classMarker in conClassDict:
                conClassDict[classMarker].append(phoneme)
            else:
                conClassDict[classMarker] = []
                conClassDict[classMarker].append(phoneme)
        elif 'vowel' in phoneme.coreSet:
            if 'diphthong' in phoneme.coreSet:
                diphthongs.append(phon)
            elif 'triphthong' in phoneme.coreSet:
                triphthongs.append(phon)
            elif 'apical' in phoneme.coreSet:
                apical_vowels.append(phon)
            else:
                vowels.append(phoneme)
                if phoneme.seriesSet:
                    classMarker = " & ".join(sorted(phoneme.seriesSet))
                else:
                    classMarker = "plain"
                if classMarker in vowClassDict:
                    vowClassDict[classMarker].append(phoneme)
                else:
                    vowClassDict[classMarker] = []
                    vowClassDict[classMarker].append(phoneme)
        else:
            raise ValueError("Neither a vowel nor a consonant: %s" % phon)
    out = StringIO()
    if conClassDict:
        out.write("<h2>Consonants</h2>")
        keys = sorted(conClassDict.keys(), key = lambda x: len(x))
        for key in keys:
            out.write("<h3>" + key[0].upper() + key[1:] + " series:</h3>")
            out.write(convert2HTMLAndSpanify(makeTableCons(conClassDict[key])))
    if vowClassDict:
        out.write("<h2>Vowels</h2>")
        keys = sorted(vowClassDict.keys(), key = lambda x: len(x))
        for key in keys:
            out.write("<h3>" + key[0].upper() + key[1:] + " series:</h3>")
            out.write(convert2HTMLAndSpanify(makeTableVow(vowClassDict[key])))
    if apical_vowels:
        out.write("<h3>Apical vowels:</h3>")
        out.write("<p>" + ", ".join(spanify(el) for el in apical_vowels))
    if diphthongs:
        out.write("<h3>Diphthongs:</h3>")
        out.write("<p>" + ", ".join(spanify(el) for el in diphthongs))
    if triphthongs:
        out.write("<h3>Triphthongs:</h3>")
        out.write("<p>" + ", ".join(spanify(el) for el in triphthongs))
    return out.getvalue()
def processInventory(idiomName, phonoString, with_title):
    """A function that takes a string of comma separated phonemes and returns a <div>."""

    # Classifying phonemes:
    # 0. Vowels vs. consonants
    # 1. Vowels:
    # 1.1. Monophthongs — with any combinations of secondary features.
    # Every combination of series-forming secondary features serves as a key in the dictionary.
    # All entries for this key are put into a separate table. The same procedure is applied to vowels.
    # 1.2. Diphthongs
    # 1.3. Triphthongs
    # 2. Consonants — with any combinations of secondary features.

    # print(idiomName) # For finding bugs in descriptions.

    # if idiomName.startswith("Santali"):
    #     print(phonoString)

    conClassDict = {}
    vowClassDict = {}
    diphthongs = []
    triphthongs = []
    consonants = []
    vowels = []
    apical_vowels = []

    inputPhons = re.split(r'\s*,\s*', phonoString)

    for phon in inputPhons:
        phoneme = Phoneme(phon, *parsePhon(phon))
        if 'consonant' in phoneme.coreSet:
            consonants.append(phoneme)
            if phoneme.seriesSet:
                classMarker = " & ".join(sorted(phoneme.seriesSet))
            else:
                classMarker = "plain"
            if classMarker in conClassDict:
                conClassDict[classMarker].append(phoneme)
            else:
                conClassDict[classMarker] = []
                conClassDict[classMarker].append(phoneme)
        elif 'vowel' in phoneme.coreSet:
            if 'diphthong' in phoneme.coreSet:
                diphthongs.append(phon)
            elif 'triphthong' in phoneme.coreSet:
                triphthongs.append(phon)
            elif 'apical' in phoneme.coreSet:
                apical_vowels.append(phon)
            else:
                vowels.append(phoneme)
                if phoneme.seriesSet:
                    classMarker = " & ".join(sorted(phoneme.seriesSet))
                else:
                    classMarker = "plain"
                if classMarker in vowClassDict:
                    vowClassDict[classMarker].append(phoneme)
                else:
                    vowClassDict[classMarker] = []
                    vowClassDict[classMarker].append(phoneme)
        else:
            raise ValueError("Neither a vowel nor a consonant: %s" % phon)

    out = StringIO()
    if with_title:
        out.write('<div class="phono_tables"><h3>%s</h3>' %
                  (idiomName.split('#')[0]))
    if conClassDict:
        out.write("<h4>Consonants</h4>")
        keys = sorted(conClassDict.keys(), key=lambda x: len(x))
        for key in keys:
            out.write("<h5>" + key[0].upper() + key[1:] + " series:</h5>")
            out.write(convert2HTML(makeTableCons(conClassDict[key])))
    if vowClassDict:
        out.write("<h4>Vowels</h4>")
        keys = sorted(vowClassDict.keys(), key=lambda x: len(x))
        for key in keys:
            out.write("<h5>" + key[0].upper() + key[1:] + " series:</h5>")
            out.write(convert2HTML(makeTableVow(vowClassDict[key])))
    if apical_vowels:
        out.write("<h5>Apical vowels:</h5>")
        out.write("<p>" + ", ".join(str(el) for el in apical_vowels))
    if diphthongs:
        out.write("<h5>Diphthongs:</h5>")
        out.write("<p>" + ", ".join(str(el) for el in diphthongs))
    if triphthongs:
        out.write("<h5>Triphthongs:</h5>")
        out.write("<p>" + ", ".join(str(el) for el in triphthongs))
    if with_title:
        out.write('</div>')

    return out.getvalue()
def processInventory(idiomName, phonoString, with_title):
    """A function that takes a string of comma separated phonemes and returns a <div>."""

    # Classifying phonemes: 
    # 0. Vowels vs. consonants
    # 1. Vowels:
    # 1.1. Monophthongs — with any combinations of secondary features.
    # Every combination of series-forming secondary features serves as a key in the dictionary.
    # All entries for this key are put into a separate table. The same procedure is applied to vowels.
    # 1.2. Diphthongs
    # 1.3. Triphthongs
    # 2. Consonants — with any combinations of secondary features.

    # print(idiomName) # For finding bugs in descriptions.

    # if idiomName.startswith("Santali"):
    #     print(phonoString)

    conClassDict  = {}
    vowClassDict  = {}
    diphthongs    = []
    triphthongs   = []
    consonants    = []
    vowels        = []
    apical_vowels = []

    inputPhons = re.split(r'\s*,\s*', phonoString)

    for phon in inputPhons:
        phoneme = Phoneme(phon, *parsePhon(phon))
        if 'consonant' in phoneme.coreSet:
            consonants.append(phoneme)
            if phoneme.seriesSet:
                classMarker = " & ".join(sorted(phoneme.seriesSet))
            else:
                classMarker = "plain"
            if classMarker in conClassDict:
                conClassDict[classMarker].append(phoneme)
            else:
                conClassDict[classMarker] = []
                conClassDict[classMarker].append(phoneme)
        elif 'vowel' in phoneme.coreSet:
            if 'diphthong' in phoneme.coreSet:
                diphthongs.append(phon)
            elif 'triphthong' in phoneme.coreSet:
                triphthongs.append(phon)
            elif 'apical' in phoneme.coreSet:
                apical_vowels.append(phon)
            else:
                vowels.append(phoneme)
                if phoneme.seriesSet:
                    classMarker = " & ".join(sorted(phoneme.seriesSet))
                else:
                    classMarker = "plain"
                if classMarker in vowClassDict:
                    vowClassDict[classMarker].append(phoneme)
                else:
                    vowClassDict[classMarker] = []
                    vowClassDict[classMarker].append(phoneme)
        else:
            raise ValueError("Neither a vowel nor a consonant: %s" % phon)

    out = StringIO()
    if with_title:
        out.write('<div class="phono_tables"><h3>%s</h3>' % (idiomName.split('#')[0]))
    if conClassDict:
        out.write("<h4>Consonants</h4>")
        keys = sorted(conClassDict.keys(), key = lambda x: len(x))
        for key in keys:
            out.write("<h5>" + key[0].upper() + key[1:] + " series:</h5>")
            out.write(convert2HTML(makeTableCons(conClassDict[key])))
    if vowClassDict:
        out.write("<h4>Vowels</h4>")
        keys = sorted(vowClassDict.keys(), key = lambda x: len(x))
        for key in keys:
            out.write("<h5>" + key[0].upper() + key[1:] + " series:</h5>")
            out.write(convert2HTML(makeTableVow(vowClassDict[key])))
    if apical_vowels:
        out.write("<h5>Apical vowels:</h5>")
        out.write("<p>" + ", ".join(str(el) for el in apical_vowels))
    if diphthongs:
        out.write("<h5>Diphthongs:</h5>")
        out.write("<p>" + ", ".join(str(el) for el in diphthongs))
    if triphthongs:
        out.write("<h5>Triphthongs:</h5>")
        out.write("<p>" + ", ".join(str(el) for el in triphthongs))
    if with_title:
        out.write('</div>')

    return out.getvalue()