commit 68109443f3738b89574cfc82bc30b14e0c31a8be
Author: Guillaume Munch <[email protected]>
Date: Sun Jan 8 21:57:02 2017 +0100
Implement AddToToc for paragraph layouts
Enables table of Theorems & Definitions
---
src/Paragraph.cpp | 6 ++--
src/Paragraph.h | 4 +-
src/Text.cpp | 47 ++++++++++++++++++++++++++++++++------
src/Text.h | 13 ++++++++--
src/TocBackend.cpp | 2 +-
src/TocBackend.h | 9 ++++---
src/insets/InsetFlex.cpp | 3 +-
src/insets/InsetText.cpp | 56 +++++++++++++++++++++++++++++++++++++++++++--
src/insets/InsetText.h | 7 +++++
9 files changed, 122 insertions(+), 25 deletions(-)
diff --git a/src/Paragraph.cpp b/src/Paragraph.cpp
index ba101e4..6d50f27 100644
--- a/src/Paragraph.cpp
+++ b/src/Paragraph.cpp
@@ -3333,11 +3333,11 @@ docstring Paragraph::asString(pos_type beg, pos_type
end, int options, const Out
void Paragraph::forOutliner(docstring & os, size_t const maxlen,
- bool const shorten)
const
+ bool const shorten, bool const label) const
{
size_t tmplen = shorten ? maxlen + 1 : maxlen;
- if (!d->params_.labelString().empty())
- os += d->params_.labelString() + ' ';
+ if (label && !labelString().empty())
+ os += labelString() + ' ';
for (pos_type i = 0; i < size() && os.length() < tmplen; ++i) {
if (isDeleted(i))
continue;
diff --git a/src/Paragraph.h b/src/Paragraph.h
index 2133d8c..813640e 100644
--- a/src/Paragraph.h
+++ b/src/Paragraph.h
@@ -181,8 +181,8 @@ public:
int options = AS_STR_NONE,
const OutputParams *runparams = 0) const;
///
- void forOutliner(docstring &, size_t const maxlen,
- bool const shorten = true) const;
+ void forOutliner(docstring &, size_t maxlen, bool shorten = true,
+ bool label = true) const;
///
void write(std::ostream &, BufferParams const &,
diff --git a/src/Text.cpp b/src/Text.cpp
index 8e0d1be..8d08baa 100644
--- a/src/Text.cpp
+++ b/src/Text.cpp
@@ -240,6 +240,21 @@ bool Text::isFirstInSequence(pit_type par_offset) const
}
+pit_type Text::lastInSequence(pit_type pit) const
+{
+ depth_type const depth = pars_[pit].getDepth();
+ pit_type newpit = pit;
+
+ while (size_t(newpit + 1) < pars_.size() &&
+ (pars_[newpit + 1].getDepth() > depth ||
+ (pars_[newpit + 1].getDepth() == depth &&
+ pars_[newpit + 1].layout() == pars_[pit].layout())))
+ ++newpit;
+
+ return newpit;
+}
+
+
int Text::getTocLevel(pit_type par_offset) const
{
Paragraph const & par = pars_[par_offset];
@@ -2042,20 +2057,36 @@ docstring Text::asString(pit_type beg, pit_type end,
int options) const
void Text::shortenForOutliner(docstring & str, size_t const maxlen)
{
support::truncateWithEllipsis(str, maxlen);
- docstring::iterator it = str.begin();
- docstring::iterator end = str.end();
- for (; it != end; ++it)
- if ((*it) == L'\n' || (*it) == L'\t')
- (*it) = L' ';
+ for (char_type & c : str)
+ if (c == L'\n' || c == L'\t')
+ c = L' ';
}
void Text::forOutliner(docstring & os, size_t const maxlen,
- bool const shorten) const
+ bool const shorten) const
+{
+ pit_type end = pars_.size() - 1;
+ if (0 <= end && !pars_[0].labelString().empty())
+ os += pars_[0].labelString() + ' ';
+ forOutliner(os, maxlen, 0, end, shorten);
+}
+
+
+void Text::forOutliner(docstring & os, size_t const maxlen,
+ pit_type pit_start, pit_type pit_end,
+ bool const shorten) const
{
size_t tmplen = shorten ? maxlen + 1 : maxlen;
- for (size_t i = 0; i != pars_.size() && os.length() < tmplen; ++i)
- pars_[i].forOutliner(os, tmplen, false);
+ pit_type end = min(size_t(pit_end), pars_.size() - 1);
+ bool first = true;
+ for (pit_type i = pit_start; i <= end && os.length() < tmplen; ++i) {
+ if (!first)
+ os += ' ';
+ // This function lets the first label be treated separately
+ pars_[i].forOutliner(os, tmplen, false, !first);
+ first = false;
+ }
if (shorten)
shortenForOutliner(os, maxlen);
}
diff --git a/src/Text.h b/src/Text.h
index bdf2169..f49c8e2 100644
--- a/src/Text.h
+++ b/src/Text.h
@@ -130,9 +130,13 @@ public:
/// Appends a possibly abbreviated representation of our text to \param
os,
/// where \param maxlen defines the maximum size of \param os. If \param
- /// shorten is true, then os is shortened as above
- void forOutliner(docstring & os, size_t const maxlen,
- bool const shorten = true) const;
+ /// shorten is true, then os is shortened as above.
+ void forOutliner(docstring & os, size_t maxlen, bool shorten = true)
const;
+ /// Appends a possibly abbreviated representation of our text, from
+ /// start to end, to \param os, where \param maxlen defines the
+ /// maximum size of \param os. Omits the label of the first paragraph.
+ void forOutliner(docstring & os, size_t maxlen, pit_type start,
pit_type end,
+ bool shorten = true) const;
/// insert a character at cursor position
/// FIXME: replace Cursor with DocIterator.
@@ -329,6 +333,9 @@ public:
pit_type outerHook(pit_type pit) const;
/// Is it the first par with same depth and layout?
bool isFirstInSequence(pit_type pit) const;
+ /// Return the last paragraph with same depth and layout, or a strictly
+ /// greater depth
+ pit_type lastInSequence(pit_type pit) const;
/// Is this paragraph in the table of contents?
int getTocLevel(pit_type pit) const;
/// Get the font of the "environment" of paragraph \p par_offset in \p
pars.
diff --git a/src/TocBackend.cpp b/src/TocBackend.cpp
index f490c35..6c7c1f9 100644
--- a/src/TocBackend.cpp
+++ b/src/TocBackend.cpp
@@ -200,7 +200,7 @@ void TocBuilder::argumentItem(docstring const & arg_str)
TocItem & item = (*toc_)[stack_.top().pos];
docstring const & str = item.str();
string const & delim =
- str.empty() ? "" : stack_.top().is_captioned ? ", " : ": ";
+ (str.empty() || !stack_.top().is_captioned) ? "" : ", ";
item.str(str + from_ascii(delim) + arg_str);
stack_.top().is_captioned = true;
}
diff --git a/src/TocBackend.h b/src/TocBackend.h
index b851d68..08754b9 100644
--- a/src/TocBackend.h
+++ b/src/TocBackend.h
@@ -56,6 +56,7 @@ enum TocType {
MATH_MACRO,//"math-macro"
EXTERNAL,//"external"
SENSELESS,//"senseless"
+ USER_DEFINED,//any value defined in the layouts
TOC_TYPE_COUNT
}
*/
@@ -119,16 +120,16 @@ private:
class TocBuilder
{
public:
- TocBuilder(std::shared_ptr<Toc> const toc);
- /// When entering a float or flex (AddToToc)
+ TocBuilder(std::shared_ptr<Toc> toc);
+ /// When entering a float or flex or paragraph (with AddToToc)
void pushItem(DocIterator const & dit, docstring const & s,
bool output_active, bool is_captioned = false);
/// When encountering a float caption
void captionItem(DocIterator const & dit, docstring const & s,
bool output_active);
- /// When encountering an argument (isTocCaption)
+ /// When encountering an argument (with isTocCaption) for flex or
paragraph
void argumentItem(docstring const & arg_str);
- /// When exiting a float or flex
+ /// When exiting a float or flex or paragraph
void pop();
private:
TocBuilder(){}
diff --git a/src/insets/InsetFlex.cpp b/src/insets/InsetFlex.cpp
index 05cbb29..ee3b7c8 100644
--- a/src/insets/InsetFlex.cpp
+++ b/src/insets/InsetFlex.cpp
@@ -175,7 +175,8 @@ void InsetFlex::addToToc(DocIterator const & cpit, bool
output_active,
// Cursor inside the inset
DocIterator pit = cpit;
pit.push_back(CursorSlice(const_cast<InsetFlex &>(*this)));
- b.pushItem(pit, getLabel(), output_active);
+ docstring const label = getLabel();
+ b.pushItem(pit, label + (label.empty() ? "" : ": "),
output_active);
// Proceed with the rest of the inset.
InsetCollapsable::addToToc(cpit, output_active, utype);
if (layout.isTocCaption()) {
diff --git a/src/insets/InsetText.cpp b/src/insets/InsetText.cpp
index 607f7f5..db6b744 100644
--- a/src/insets/InsetText.cpp
+++ b/src/insets/InsetText.cpp
@@ -851,13 +851,29 @@ void InsetText::iterateForToc(DocIterator const & cdit,
bool output_active,
// can't hurt too much to do it again
bool const doing_output = output_active && producesOutput();
- // For each paragraph, traverse its insets and let them add
- // their toc items
+ // For each paragraph,
+ // * Add a toc item for the paragraph if it is AddToToc--merging
adjacent
+ // paragraphs as needed.
+ // * Traverse its insets and let them add their toc items
+ // * Compute the main table of contents (this is hardcoded)
+ // * Add the list of changes
ParagraphList const & pars = paragraphs();
pit_type pend = paragraphs().size();
+ // Record pairs {start,end} of where a toc item was opened for a
paragraph
+ // and where it must be closed
+ stack<pair<pit_type, pit_type>> addtotoc_stack;
+
for (pit_type pit = 0; pit != pend; ++pit) {
Paragraph const & par = pars[pit];
dit.pit() = pit;
+ dit.pos() = 0;
+
+ // Custom AddToToc in paragraph layouts (i.e. theorems)
+ if (par.layout().addToToc() && text().isFirstInSequence(pit)) {
+ pit_type end = openAddToTocForParagraph(pit, dit,
output_active);
+ addtotoc_stack.push({pit, end});
+ }
+
// if we find an optarg, we'll save it for use later.
InsetText const * arginset = 0;
InsetList::const_iterator it = par.insetList().begin();
@@ -870,7 +886,16 @@ void InsetText::iterateForToc(DocIterator const & cdit,
bool output_active,
if (inset.lyxCode() == ARG_CODE)
arginset = inset.asInsetText();
}
- // now the toc entry for the paragraph
+
+ // End custom AddToToc in paragraph layouts
+ while (!addtotoc_stack.empty() && addtotoc_stack.top().second
== pit) {
+ // execute the closing function
+ closeAddToTocForParagraph(addtotoc_stack.top().first,
+ addtotoc_stack.top().second);
+ addtotoc_stack.pop();
+ }
+
+ // now the toc entry for the paragraph in the main table of
contents
int const toclevel = text().getTocLevel(pit);
if (toclevel != Layout::NOT_IN_TOC && toclevel >= min_toclevel)
{
// insert this into the table of contents
@@ -895,6 +920,31 @@ void InsetText::iterateForToc(DocIterator const & cdit,
bool output_active,
}
+pit_type InsetText::openAddToTocForParagraph(pit_type pit,
+ DocIterator const & dit,
+ bool output_active) const
+{
+ Paragraph const & par = paragraphs()[pit];
+ TocBuilder & b = buffer().tocBackend().builder(par.layout().tocType());
+ docstring const label = par.labelString();
+ b.pushItem(dit, label + (label.empty() ? "" : " "), output_active);
+ return text().lastInSequence(pit);
+}
+
+
+void InsetText::closeAddToTocForParagraph(pit_type start, pit_type end) const
+{
+ Paragraph const & par = paragraphs()[start];
+ TocBuilder & b = buffer().tocBackend().builder(par.layout().tocType());
+ if (par.layout().isTocCaption()) {
+ docstring str;
+ text().forOutliner(str, TOC_ENTRY_LENGTH, start, end);
+ b.argumentItem(str);
+ }
+ b.pop();
+}
+
+
bool InsetText::notifyCursorLeaves(Cursor const & old, Cursor & cur)
{
if (buffer().isClean())
diff --git a/src/insets/InsetText.h b/src/insets/InsetText.h
index 5bc7c52..8c647fb 100644
--- a/src/insets/InsetText.h
+++ b/src/insets/InsetText.h
@@ -223,6 +223,13 @@ protected:
void iterateForToc(DocIterator const & cdit, bool output_active,
UpdateType utype) const;
private:
+ /// Open the toc item for paragraph pit. Returns the paragraph index
where
+ /// it should end.
+ pit_type openAddToTocForParagraph(pit_type pit,
+ DocIterator const & dit,
+ bool output_active) const;
+ /// Close a toc item opened in start and closed in end
+ void closeAddToTocForParagraph(pit_type start, pit_type end) const;
///
bool drawFrame_;
///