InsetIndex: refactor IndexEntry to be a full-fledged class, hiding its implementation details better than before.

This commit is contained in:
Thibaut Cuvelier 2022-04-25 03:09:02 +02:00
parent f86c7994a5
commit 4a62c08e61
2 changed files with 108 additions and 103 deletions

View File

@ -89,31 +89,6 @@
Index tests Index tests
\end_layout \end_layout
\begin_layout Standard
\begin_inset Index idx
range none
pageformat default
status open
\begin_layout Plain Layout
Primary
\begin_inset IndexMacro subindex
status open
\begin_layout Plain Layout
Secondary
\end_layout
\end_inset
\end_layout
\end_inset
\end_layout
\begin_layout Standard \begin_layout Standard
Text Text
\begin_inset Index idx \begin_inset Index idx
@ -300,5 +275,16 @@ Tertiary
. .
\end_layout \end_layout
\begin_layout Standard
\begin_inset CommandInset index_print
LatexCommand printindex
type "idx"
name "Index"
\end_inset
\end_layout
\end_body \end_body
\end_document \end_document

View File

@ -1237,88 +1237,113 @@ bool InsetPrintIndex::hasSettings() const
namespace { namespace {
void parseItem(docstring & s, bool for_output)
{
// this does not yet check for escaped things
size_type loc = s.find(from_ascii("@"));
if (loc != string::npos) {
if (for_output)
s.erase(0, loc + 1);
else
s.erase(loc);
}
loc = s.find(from_ascii("|"));
if (loc != string::npos)
s.erase(loc);
}
void extractSubentries(docstring const & entry, docstring & main,
docstring & sub1, docstring & sub2)
{
if (entry.empty())
return;
size_type const loc = entry.find(from_ascii(" ! "));
if (loc == string::npos)
main = entry;
else {
main = trim(entry.substr(0, loc));
size_t const locend = loc + 3;
size_type const loc2 = entry.find(from_ascii(" ! "), locend);
if (loc2 == string::npos) {
sub1 = trim(entry.substr(locend));
} else {
sub1 = trim(entry.substr(locend, loc2 - locend));
sub2 = trim(entry.substr(loc2 + 3));
}
}
}
struct IndexEntry struct IndexEntry
{ {
IndexEntry() IndexEntry() = default;
{}
IndexEntry(docstring const & s, DocIterator const & d) IndexEntry(docstring const & s, DocIterator const & d, bool for_output = false)
: dit(d) : dit_(d)
{ {
extractSubentries(s, main, sub, subsub); extractSubentries(s);
parseItem(main, false); parseItem(main_, for_output);
parseItem(sub, false); parseItem(sub_, for_output);
parseItem(subsub, false); parseItem(subsub_, for_output);
} }
bool equal(IndexEntry const & rhs) const bool equal(IndexEntry const & rhs) const
{ {
return main == rhs.main && sub == rhs.sub && subsub == rhs.subsub; return main_ == rhs.main_ && sub_ == rhs.sub_ && subsub_ == rhs.subsub_;
} }
bool same_sub(IndexEntry const & rhs) const bool same_sub(IndexEntry const & rhs) const
{ {
return main == rhs.main && sub == rhs.sub; return main_ == rhs.main_ && sub_ == rhs.sub_;
} }
bool same_main(IndexEntry const & rhs) const bool same_main(IndexEntry const & rhs) const
{ {
return main == rhs.main; return main_ == rhs.main_;
} }
docstring main; const Paragraph & innerParagraph() const
docstring sub; {
docstring subsub; return dit_.innerParagraph();
DocIterator dit; }
const docstring & main() const
{
return main_;
}
const docstring & sub() const
{
return sub_;
}
const docstring & subsub() const
{
return subsub_;
}
const DocIterator & dit() const
{
return dit_;
}
private:
void parseItem(docstring & s, bool for_output)
{
// this does not yet check for escaped things
size_type loc = s.find(from_ascii("@"));
if (loc != string::npos) {
if (for_output)
s.erase(0, loc + 1);
else
s.erase(loc);
}
loc = s.find(from_ascii("|"));
if (loc != string::npos)
s.erase(loc);
}
void extractSubentries(docstring const & entry)
{
if (entry.empty())
return;
size_type const loc = entry.find(from_ascii(" ! "));
if (loc == string::npos)
main_ = entry;
else {
main_ = trim(entry.substr(0, loc));
size_t const locend = loc + 3;
size_type const loc2 = entry.find(from_ascii(" ! "), locend);
if (loc2 == string::npos) {
sub_ = trim(entry.substr(locend));
} else {
sub_ = trim(entry.substr(locend, loc2 - locend));
subsub_ = trim(entry.substr(loc2 + 3));
}
}
}
private:
docstring main_;
docstring sub_;
docstring subsub_;
DocIterator dit_;
friend bool operator<(IndexEntry const & lhs, IndexEntry const & rhs);
}; };
bool operator<(IndexEntry const & lhs, IndexEntry const & rhs) bool operator<(IndexEntry const & lhs, IndexEntry const & rhs)
{ {
int comp = compare_no_case(lhs.main, rhs.main); int comp = compare_no_case(lhs.main_, rhs.main_);
if (comp == 0) if (comp == 0)
comp = compare_no_case(lhs.sub, rhs.sub); comp = compare_no_case(lhs.sub_, rhs.sub_);
if (comp == 0) if (comp == 0)
comp = compare_no_case(lhs.subsub, rhs.subsub); comp = compare_no_case(lhs.subsub_, rhs.subsub_);
return (comp < 0); return comp < 0;
} }
} // namespace } // namespace
@ -1384,7 +1409,7 @@ docstring InsetPrintIndex::xhtml(XMLStream &, OutputParams const & op) const
IndexEntry last; IndexEntry last;
int entry_number = -1; int entry_number = -1;
for (; eit != een; ++eit) { for (; eit != een; ++eit) {
Paragraph const & par = eit->dit.innerParagraph(); Paragraph const & par = eit->innerParagraph();
if (entry_number == -1 || !eit->equal(last)) { if (entry_number == -1 || !eit->equal(last)) {
if (entry_number != -1) { if (entry_number != -1) {
// not the first time through the loop, so // not the first time through the loop, so
@ -1434,21 +1459,15 @@ docstring InsetPrintIndex::xhtml(XMLStream &, OutputParams const & op) const
ours.for_toc = true; ours.for_toc = true;
par.simpleLyXHTMLOnePar(buffer(), entstream, ours, dummy); par.simpleLyXHTMLOnePar(buffer(), entstream, ours, dummy);
// these will contain XHTML versions of the main entry, etc // these will contain XHTML versions of the main entry, etc.
// remember that everything will already have been escaped, // remember that everything will already have been escaped,
// so we'll need to use NextRaw() during output. // so we'll need to use NextRaw() during output.
docstring main; IndexEntry xhtml_entry = IndexEntry(ent.str(), eit->dit(), true);
docstring sub;
docstring subsub;
extractSubentries(ent.str(), main, sub, subsub);
parseItem(main, true);
parseItem(sub, true);
parseItem(subsub, true);
if (level == 3) { if (level == 3) {
// another subsubentry // another subsubentry
xs << xml::StartTag("li", "class='subsubentry'") xs << xml::StartTag("li", "class='subsubentry'")
<< XMLStream::ESCAPE_NONE << subsub; << XMLStream::ESCAPE_NONE << xhtml_entry.subsub();
} else if (level == 2) { } else if (level == 2) {
// there are two ways we can be here: // there are two ways we can be here:
// (i) we can actually be inside a sub-entry already and be about // (i) we can actually be inside a sub-entry already and be about
@ -1460,15 +1479,15 @@ docstring InsetPrintIndex::xhtml(XMLStream &, OutputParams const & op) const
// only in the latter case do we need to output the new sub-entry. // only in the latter case do we need to output the new sub-entry.
// note that in this case, too, though, the sub-entry might already // note that in this case, too, though, the sub-entry might already
// have a sub-sub-entry. // have a sub-sub-entry.
if (eit->sub != last.sub) if (eit->sub() != last.sub())
xs << xml::StartTag("li", "class='subentry'") xs << xml::StartTag("li", "class='subentry'")
<< XMLStream::ESCAPE_NONE << sub; << XMLStream::ESCAPE_NONE << xhtml_entry.sub();
if (!subsub.empty()) { if (!xhtml_entry.subsub().empty()) {
// it's actually a subsubentry, so we need to start that list // it's actually a subsubentry, so we need to start that list
xs << xml::CR() xs << xml::CR()
<< xml::StartTag("ul", "class='subsubentry'") << xml::StartTag("ul", "class='subsubentry'")
<< xml::StartTag("li", "class='subsubentry'") << xml::StartTag("li", "class='subsubentry'")
<< XMLStream::ESCAPE_NONE << subsub; << XMLStream::ESCAPE_NONE << xhtml_entry.subsub();
level = 3; level = 3;
} }
} else { } else {
@ -1482,21 +1501,21 @@ docstring InsetPrintIndex::xhtml(XMLStream &, OutputParams const & op) const
// only in the latter case do we need to output the new main entry. // only in the latter case do we need to output the new main entry.
// note that in this case, too, though, the main entry might already // note that in this case, too, though, the main entry might already
// have a sub-entry, or even a sub-sub-entry. // have a sub-entry, or even a sub-sub-entry.
if (eit->main != last.main) if (eit->main() != last.main())
xs << xml::StartTag("li", "class='main'") << main; xs << xml::StartTag("li", "class='main'") << xhtml_entry.main();
if (!sub.empty()) { if (!xhtml_entry.sub().empty()) {
// there's a sub-entry, too // there's a sub-entry, too
xs << xml::CR() xs << xml::CR()
<< xml::StartTag("ul", "class='subentry'") << xml::StartTag("ul", "class='subentry'")
<< xml::StartTag("li", "class='subentry'") << xml::StartTag("li", "class='subentry'")
<< XMLStream::ESCAPE_NONE << sub; << XMLStream::ESCAPE_NONE << xhtml_entry.sub();
level = 2; level = 2;
if (!subsub.empty()) { if (!xhtml_entry.subsub().empty()) {
// and a sub-sub-entry // and a sub-sub-entry
xs << xml::CR() xs << xml::CR()
<< xml::StartTag("ul", "class='subsubentry'") << xml::StartTag("ul", "class='subsubentry'")
<< xml::StartTag("li", "class='subsubentry'") << xml::StartTag("li", "class='subsubentry'")
<< XMLStream::ESCAPE_NONE << subsub; << XMLStream::ESCAPE_NONE << xhtml_entry.subsub();
level = 3; level = 3;
} }
} }