Fix bug #11104. Activate refstyle support for InsetMathRef.

At the moment, there is no support for plurals and capitalization.
A long comment explains why. Support could be added for that without
a format change.
This commit is contained in:
Richard Kimberly Heck 2021-01-05 17:25:27 -05:00
parent 79a21be5c3
commit cf07d4825f
10 changed files with 191 additions and 48 deletions

View File

@ -3993,6 +3993,40 @@ def revert_hrquotes(document):
document.body[i] = "\\begin_inset Quotes ard" document.body[i] = "\\begin_inset Quotes ard"
def convert_math_refs(document):
i = 0
while True:
i = find_token(document.body, "\\begin_inset Formula", i)
if i == -1:
break
j = find_end_of_inset(document.body, i)
if j == -1:
document.warning("Can't find end of inset at line %d of body!" % i)
i += 1
continue
while i < j:
document.body[i] = document.body[i].replace("\\prettyref", "\\formatted")
i += 1
def revert_math_refs(document):
i = 0
while True:
i = find_token(document.body, "\\begin_inset Formula", i)
if i == -1:
break
j = find_end_of_inset(document.body, i)
if j == -1:
document.warning("Can't find end of inset at line %d of body!" % i)
i += 1
continue
while i < j:
document.body[i] = document.body[i].replace("\\formatted", "\\prettyref")
if "\\labelonly" in document.body[i]:
document.body[i] = re.sub("\\\\labelonly{([^}]+?)}", "\\1", document.body[i])
i += 1
## ##
# Conversion hub # Conversion hub
# #
@ -4054,10 +4088,12 @@ convert = [
[597, [convert_libertinus_rm_fonts]], [597, [convert_libertinus_rm_fonts]],
[598, []], [598, []],
[599, []], [599, []],
[600, []] [600, []],
[601, [convert_math_refs]]
] ]
revert = [[598, [revert_hrquotes]], revert = [[599, [revert_math_refs]],
[598, [revert_hrquotes]],
[598, [revert_nopagebreak]], [598, [revert_nopagebreak]],
[597, [revert_docbook_table_output]], [597, [revert_docbook_table_output]],
[596, [revert_libertinus_rm_fonts,revert_libertinus_sftt_fonts]], [596, [revert_libertinus_rm_fonts,revert_libertinus_sftt_fonts]],

View File

@ -145,13 +145,14 @@ void GuiRef::enableView(bool enable)
void GuiRef::enableBoxes() void GuiRef::enableBoxes()
{ {
QString const reftype = QString const reftype =
typeCO->itemData(typeCO->currentIndex()).toString(); typeCO->itemData(typeCO->currentIndex()).toString();
bool const isFormatted = (reftype == "formatted"); bool const isFormatted = (reftype == "formatted");
bool const isLabelOnly = (reftype == "labelonly"); bool const isLabelOnly = (reftype == "labelonly");
bool const usingRefStyle = buffer().params().use_refstyle; bool const usingRefStyle = buffer().params().use_refstyle;
pluralCB->setEnabled(isFormatted && usingRefStyle); bool const intext = bufferview()->cursor().inTexted();
capsCB->setEnabled(isFormatted && usingRefStyle); pluralCB->setEnabled(intext && isFormatted && usingRefStyle);
noprefixCB->setEnabled(isLabelOnly); capsCB->setEnabled(intext && isFormatted && usingRefStyle);
noprefixCB->setEnabled(intext && isLabelOnly);
} }
@ -324,11 +325,8 @@ void GuiRef::updateContents()
typeCO->addItem(qt_("on page <page>"), "vpageref"); typeCO->addItem(qt_("on page <page>"), "vpageref");
typeCO->addItem(qt_("<reference> on page <page>"), "vref"); typeCO->addItem(qt_("<reference> on page <page>"), "vref");
typeCO->addItem(qt_("Textual reference"), "nameref"); typeCO->addItem(qt_("Textual reference"), "nameref");
if (bufferview()->cursor().inTexted()) { typeCO->addItem(qt_("Formatted reference"), "formatted");
typeCO->addItem(qt_("Formatted reference"), "formatted"); typeCO->addItem(qt_("Label only"), "labelonly");
typeCO->addItem(qt_("Label only"), "labelonly");
} else
typeCO->addItem(qt_("Formatted reference"), "prettyref");
referenceED->setText(toqstr(params_["reference"])); referenceED->setText(toqstr(params_["reference"]));

View File

@ -174,16 +174,6 @@ bool InsetRef::getStatus(Cursor & cur, FuncRequest const & cmd,
} }
namespace {
void capitalize(docstring & s) {
char_type t = uppercase(s[0]);
s[0] = t;
}
} // namespace
// the ref argument is the label name we are referencing. // the ref argument is the label name we are referencing.
// we expect ref to be in the form: pfx:suffix. // we expect ref to be in the form: pfx:suffix.
// //
@ -199,7 +189,8 @@ void capitalize(docstring & s) {
// label, thus: \prettyref{pfx:suffix}. // label, thus: \prettyref{pfx:suffix}.
// //
docstring InsetRef::getFormattedCmd(docstring const & ref, docstring InsetRef::getFormattedCmd(docstring const & ref,
docstring & label, docstring & prefix, docstring const & caps) const docstring & label, docstring & prefix, bool use_refstyle,
bool use_caps)
{ {
static docstring const defcmd = from_ascii("\\ref"); static docstring const defcmd = from_ascii("\\ref");
static docstring const prtcmd = from_ascii("\\prettyref"); static docstring const prtcmd = from_ascii("\\prettyref");
@ -216,11 +207,12 @@ docstring InsetRef::getFormattedCmd(docstring const & ref,
if (prefix.empty()) { if (prefix.empty()) {
// we have ":xxxx" // we have ":xxxx"
LYXERR0("Label `" << ref << "' contains nothign before `:'.");
label = ref; label = ref;
return defcmd; return defcmd;
} }
if (!buffer().params().use_refstyle) { if (!use_refstyle) {
// \prettyref uses the whole label // \prettyref uses the whole label
label = ref; label = ref;
return prtcmd; return prtcmd;
@ -237,8 +229,8 @@ docstring InsetRef::getFormattedCmd(docstring const & ref,
return defcmd; return defcmd;
} }
} }
if (caps == "true") { if (use_caps) {
capitalize(prefix); prefix = support::capitalize(prefix);
} }
return from_ascii("\\") + prefix + from_ascii("ref"); return from_ascii("\\") + prefix + from_ascii("ref");
} }
@ -261,7 +253,7 @@ void InsetRef::latex(otexstream & os, OutputParams const & rp) const
if (rp.inulemcmd > 0) if (rp.inulemcmd > 0)
os << "\\mbox{"; os << "\\mbox{";
if (cmd == "eqref" && buffer().params().use_refstyle) { if (buffer().params().use_refstyle && cmd == "eqref") {
// we advertise this as printing "(n)", so we'll do that, at least // we advertise this as printing "(n)", so we'll do that, at least
// for refstyle, since refstlye's own \eqref prints, by default, // for refstyle, since refstlye's own \eqref prints, by default,
// "equation n". if one wants \eqref, one can get it by using a // "equation n". if one wants \eqref, one can get it by using a
@ -271,10 +263,12 @@ void InsetRef::latex(otexstream & os, OutputParams const & rp) const
else if (cmd == "formatted") { else if (cmd == "formatted") {
docstring label; docstring label;
docstring prefix; docstring prefix;
bool const use_caps = getParam("caps") == "true";
bool const use_plural = getParam("plural") == "true";
docstring const fcmd = docstring const fcmd =
getFormattedCmd(data, label, prefix, getParam("caps")); getFormattedCmd(data, label, prefix, use_caps);
os << fcmd; os << fcmd;
if (buffer().params().use_refstyle && getParam("plural") == "true") if (buffer().params().use_refstyle && use_plural)
os << "[s]"; os << "[s]";
os << '{' << label << '}'; os << '{' << label << '}';
} }
@ -542,9 +536,11 @@ void InsetRef::validate(LaTeXFeatures & features) const
docstring const data = getEscapedLabel(features.runparams()); docstring const data = getEscapedLabel(features.runparams());
docstring label; docstring label;
docstring prefix; docstring prefix;
bool const use_refstyle = buffer().params().use_refstyle;
bool const use_caps = getParam("caps") == "true";
docstring const fcmd = docstring const fcmd =
getFormattedCmd(data, label, prefix, getParam("caps")); getFormattedCmd(data, label, prefix, use_refstyle, use_caps);
if (buffer().params().use_refstyle) { if (use_refstyle) {
features.require("refstyle"); features.require("refstyle");
if (prefix == "cha") if (prefix == "cha")
features.addPreambleSnippet(from_ascii("\\let\\charef=\\chapref")); features.addPreambleSnippet(from_ascii("\\let\\charef=\\chapref"));

View File

@ -90,6 +90,13 @@ public:
//@} //@}
/// ///
bool outputActive() const { return active_; } bool outputActive() const { return active_; }
/// \return the command for a formatted reference to ref
/// \param label we're cross-referencing
/// \param argument for reference command
/// \param prefix of the label (before :)
/// Also used by InsetMathRef
static docstring getFormattedCmd(docstring const & ref, docstring & label,
docstring & prefix, bool use_refstyle, bool use_caps = false);
protected: protected:
/// ///
@ -110,12 +117,6 @@ private:
/// \return the label with things that need to be escaped escaped /// \return the label with things that need to be escaped escaped
docstring getEscapedLabel(OutputParams const &) const; docstring getEscapedLabel(OutputParams const &) const;
/// \return the command for a formatted reference to ref
/// \param label we're cross-referencing
/// \param argument for reference command
/// \param prefix of the label (before :)
docstring getFormattedCmd(docstring const & ref, docstring & label,
docstring & prefix, docstring const & caps) const;
/// ///
mutable docstring screen_label_; mutable docstring screen_label_;

View File

@ -12,6 +12,7 @@
#include "InsetMathRef.h" #include "InsetMathRef.h"
#include "BufferParams.h"
#include "BufferView.h" #include "BufferView.h"
#include "Buffer.h" #include "Buffer.h"
#include "Cursor.h" #include "Cursor.h"
@ -21,14 +22,18 @@
#include "LyX.h" #include "LyX.h"
#include "MathData.h" #include "MathData.h"
#include "MathFactory.h" #include "MathFactory.h"
#include "MathStream.h"
#include "MathSupport.h" #include "MathSupport.h"
#include "ParIterator.h" #include "ParIterator.h"
#include "xml.h" #include "xml.h"
#include "insets/InsetCommand.h" #include "insets/InsetCommand.h"
#include "insets/InsetRef.h"
#include "support/debug.h" #include "support/debug.h"
#include "support/gettext.h" #include "support/gettext.h"
#include "support/lstrings.h"
#include "support/textutils.h"
#include <ostream> #include <ostream>
@ -75,7 +80,9 @@ void InsetMathRef::doDispatch(Cursor & cur, FuncRequest & cmd)
MathData ar; MathData ar;
if (createInsetMath_fromDialogStr(cmd.argument(), ar)) { if (createInsetMath_fromDialogStr(cmd.argument(), ar)) {
cur.recordUndo(); cur.recordUndo();
Buffer & buf = buffer();
*this = *ar[0].nucleus()->asRefInset(); *this = *ar[0].nucleus()->asRefInset();
setBuffer(buf);
break; break;
} }
} }
@ -170,11 +177,24 @@ docstring const InsetMathRef::screenLabel() const
void InsetMathRef::validate(LaTeXFeatures & features) const void InsetMathRef::validate(LaTeXFeatures & features) const
{ {
// This really should not happen here but does.
if (!buffer_) {
LYXERR0("Unassigned buffer_ in InsetMathRef::write!");
LYXERR0("LaTeX output may be wrong!");
}
bool const use_refstyle =
buffer_ && buffer().params().use_refstyle;
if (commandname() == "vref" || commandname() == "vpageref") if (commandname() == "vref" || commandname() == "vpageref")
features.require("varioref"); features.require("varioref");
else if (commandname() == "prettyref") else if (commandname() == "formatted") {
features.require("prettyref"); if (use_refstyle)
else if (commandname() == "eqref") features.require("refstyle");
else
features.require("prettyref");
}
// if eqref is used with refstyle, we do our own output
else if (commandname() == "eqref" && use_refstyle)
features.require("amsmath"); features.require("amsmath");
else if (commandname() == "nameref") else if (commandname() == "nameref")
features.require("nameref"); features.require("nameref");
@ -240,14 +260,99 @@ void InsetMathRef::changeTarget(docstring const & target)
} }
void InsetMathRef::write(TeXMathStream & os) const
{
docstring const & cmd = commandname();
// This should not happen, but of course it does
if (!buffer_) {
LYXERR0("Unassigned buffer_ in InsetMathRef::write!");
LYXERR0("LaTeX output may be wrong!");
}
bool const use_refstyle =
buffer_ && buffer().params().use_refstyle;
bool special_case = cmd == "formatted" ||
cmd == "labelonly" ||
(cmd == "eqref" && use_refstyle);
// are we writing to the LyX file or not in a special case?
if (!os.latex() || !special_case) {
// if so, then this is easy
InsetMathCommand::write(os);
return;
}
// we need to translate 'formatted' to prettyref or refstyle-type
// commands and just output the label with labelonly
// most of this is borrowed from InsetRef and should be kept in
// sync with that.
ModeSpecifier specifier(os, currentMode(), lockedMode(), asciiOnly());
MathEnsurer ensurer(os, false);
if (use_refstyle && cmd == "eqref") {
// we advertise this as printing "(n)", so we'll do that, at least
// for refstyle, since refstlye's own \eqref prints, by default,
// "equation n". if one wants \eqref, one can get it by using a
// formatted label in this case.
os << '(' << from_ascii("\\ref{") << cell(0) << from_ascii("})");
}
else if (cmd == "formatted") {
if (!use_refstyle)
os << "\\prettyref{" << cell(0) << "}";
else {
odocstringstream ods;
// get the label we are referencing
for (auto const & d : cell(0)) {
ods << d;
}
docstring const ref = ods.str();
/*
At the moment, the 'plural' and 'caps' options will
not work here. The reason is that we handle these as
'internal' LyX argumemts, but those are not handled by
InsetCommandParams::getCommand, which is what is used
in createInsetMath_fromDialogStr to interpret the data
coming from the dialog.
If this is fixed, then what follows will get the info
we need.
Fixing it, I think, would mean sub-classing
InsetCommandParams to InsetRefParams, and the overriding
getCommand.
*******************************************************
// reset
ods.str(docstring());
ods.clear();
// get the options from the optional argument
for (auto const & d : cell(1))
ods << d;
docstring const options = ods.str();
bool const caps = support::contains(options, 'C');
bool const plural = support::contains(options, 's');
*/
docstring label;
docstring prefix;
docstring const fcmd =
InsetRef::getFormattedCmd(ref, label, prefix, true);
os << fcmd;
//if (plural)
// os << "[s]";
os << '{' << label << '}';
}
}
else if (cmd == "labelonly") {
// noprefix does not work here, for reasons given above.
os << cell(0);
}
}
InsetMathRef::ref_type_info InsetMathRef::types[] = { InsetMathRef::ref_type_info InsetMathRef::types[] = {
{ from_ascii("ref"), from_ascii(N_("Standard[[mathref]]")), from_ascii(N_("Ref: "))}, { from_ascii("ref"), from_ascii(N_("Standard[[mathref]]")), from_ascii(N_("Ref: "))},
{ from_ascii("eqref"), from_ascii(N_("Equation")), from_ascii(N_("EqRef: "))}, { from_ascii("eqref"), from_ascii(N_("Equation")), from_ascii(N_("EqRef: "))},
{ from_ascii("pageref"), from_ascii(N_("Page Number")), from_ascii(N_("Page: "))}, { from_ascii("pageref"), from_ascii(N_("Page Number")), from_ascii(N_("Page: "))},
{ from_ascii("vpageref"), from_ascii(N_("Textual Page Number")), from_ascii(N_("TextPage: "))}, { from_ascii("vpageref"), from_ascii(N_("Textual Page Number")), from_ascii(N_("TextPage: "))},
{ from_ascii("vref"), from_ascii(N_("Standard+Textual Page")), from_ascii(N_("Ref+Text: "))}, { from_ascii("vref"), from_ascii(N_("Standard+Textual Page")), from_ascii(N_("Ref+Text: "))},
{ from_ascii("prettyref"), from_ascii(N_("PrettyRef")), from_ascii(N_("FormatRef: "))}, { from_ascii("formatted"), from_ascii(N_("PrettyRef")), from_ascii(N_("FormatRef: "))},
{ from_ascii("nameref"), from_ascii(N_("Reference to Name")), from_ascii(N_("NameRef: "))}, { from_ascii("nameref"), from_ascii(N_("Reference to Name")), from_ascii(N_("NameRef: "))},
{ from_ascii("labelonly"), from_ascii(N_("Label Only")), from_ascii(N_("Label Only: "))},
{ from_ascii(""), from_ascii(""), from_ascii("") } { from_ascii(""), from_ascii(""), from_ascii("") }
}; };

View File

@ -29,7 +29,7 @@ public:
/// ///
void updateBuffer(ParIterator const &, UpdateType, bool const deleted = false) override; void updateBuffer(ParIterator const &, UpdateType, bool const deleted = false) override;
/// ///
//void write(TeXMathStream & os) const override; void write(TeXMathStream & os) const override;
/// ///
void infoize(odocstream & os) const override; void infoize(odocstream & os) const override;
/// ///
@ -62,10 +62,6 @@ public:
}; };
static ref_type_info types[]; static ref_type_info types[];
/// ///
static int getType(docstring const & name);
///
static docstring const & getName(int type);
///
docstring const getTarget() const; docstring const getTarget() const;
/// ///
InsetCode lyxCode() const override { return MATH_REF_CODE; } InsetCode lyxCode() const override { return MATH_REF_CODE; }

View File

@ -1546,7 +1546,8 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags,
else if (t.cs() == "ref" || t.cs() == "eqref" || t.cs() == "prettyref" else if (t.cs() == "ref" || t.cs() == "eqref" || t.cs() == "prettyref"
|| t.cs() == "nameref" || t.cs() == "pageref" || t.cs() == "nameref" || t.cs() == "pageref"
|| t.cs() == "vpageref" || t.cs() == "vref") { || t.cs() == "vpageref" || t.cs() == "vref"
|| t.cs() == "formatted" || t.cs() == "labelonly") {
cell->push_back(MathAtom(new InsetMathRef(buf, t.cs()))); cell->push_back(MathAtom(new InsetMathRef(buf, t.cs())));
docstring const opt = parse_verbatim_option(); docstring const opt = parse_verbatim_option();
docstring const ref = parse_verbatim_item(); docstring const ref = parse_verbatim_item();

View File

@ -543,6 +543,14 @@ docstring const uppercase(docstring const & a)
} }
docstring capitalize(docstring const & s) {
docstring ret = s;
char_type t = uppercase(ret[0]);
ret[0] = t;
return ret;
}
string const ascii_lowercase(string const & a) string const ascii_lowercase(string const & a)
{ {
string tmp(a); string tmp(a);

View File

@ -181,6 +181,8 @@ docstring const token(docstring const & a, char_type delim, int n);
int tokenPos(std::string const & a, char delim, std::string const & tok); int tokenPos(std::string const & a, char delim, std::string const & tok);
int tokenPos(docstring const & a, char_type delim, docstring const & tok); int tokenPos(docstring const & a, char_type delim, docstring const & tok);
///
docstring capitalize(docstring const & s);
/// Substitute all \a oldchar with \a newchar /// Substitute all \a oldchar with \a newchar
std::string const subst(std::string const & a, char oldchar, char newchar); std::string const subst(std::string const & a, char oldchar, char newchar);

View File

@ -32,8 +32,8 @@ extern char const * const lyx_version_info;
// Do not remove the comment below, so we get merge conflict in // Do not remove the comment below, so we get merge conflict in
// independent branches. Instead add your own. // independent branches. Instead add your own.
#define LYX_FORMAT_LYX 600 // spitz: hungarian quote style #define LYX_FORMAT_LYX 601 // rkh: refstyle in math
#define LYX_FORMAT_TEX2LYX 600 #define LYX_FORMAT_TEX2LYX 601
#if LYX_FORMAT_TEX2LYX != LYX_FORMAT_LYX #if LYX_FORMAT_TEX2LYX != LYX_FORMAT_LYX
#ifndef _MSC_VER #ifndef _MSC_VER