Allow captions also on non-floating minted listings

Minted provides for captions only with floating listings. However,
listings always allows captions, and our machinery is geared accordingly.
So, instead of discriminating the floating and non-floating cases,
always allow for captions with minted, too. When minted does not provide
for a caption, we will provide one.
In the child document case the caption will always be before the listing,
while for the inset case the caption will be before the listing if it
is entered as the first line, after the listing otherwise.
This commit is contained in:
Enrico Forestieri 2017-06-10 18:43:23 +02:00
parent f34f0c1db4
commit 3dfa1cb417
3 changed files with 55 additions and 20 deletions

View File

@ -419,6 +419,17 @@ static docstring const rtloutputdblcol_def = from_ascii(
"}\n"
"\\@mparswitchtrue\n");
static docstring const lyxmintcaption_def = from_ascii(
"\\long\\def\\lyxmintcaption[#1]#2{%\n"
" \\ifx#1t\\vskip\\baselineskip\\fi%\n"
" \\refstepcounter{listing}\\noindent%\n"
" \\setbox\\@tempboxa\\hbox{\\listingscaption~\\thelisting: #2}%\n"
" \\ifdim \\wd\\@tempboxa >\\linewidth%\n"
" \\parbox[t]{\\linewidth}{\\unhbox\\@tempboxa}\\else%\n"
" \\hbox to\\linewidth{\\hfil\\box\\@tempboxa\\hfil}\\fi%\n"
" \\ifx#1b\\vskip\\baselineskip\\fi\n"
"}\n");
/////////////////////////////////////////////////////////////////////
//
@ -1491,6 +1502,9 @@ TexString LaTeXFeatures::getMacros() const
if (mustProvide("rtloutputdblcol"))
macros << rtloutputdblcol_def;
if (mustProvide("lyxmintcaption"))
macros << lyxmintcaption_def;
return macros.release();
}

View File

@ -602,8 +602,11 @@ void InsetInclude::latex(otexstream & os, OutputParams const & runparams) const
// Using listings, it is always possible to have a caption,
// even for non-floats. Using minted, only floats can have a
// caption. So, with minted we use the following strategy.
// If a caption or the float parameter are specified, we
// assume that the listing is floating. In this case, the
// If a caption was specified but the float parameter was not,
// we ourselves add a caption above the listing (because the
// listing comes from a file and might span several pages).
// Otherwise, if float was specified, the floating listing
// environment provided by minted is used. In either case, the
// label parameter is taken as the label by which the float
// can be referenced, otherwise it will have the meaning
// intended by minted. In this last case, the label will
@ -620,7 +623,7 @@ void InsetInclude::latex(otexstream & os, OutputParams const & runparams) const
string caption;
string label;
string placement;
bool isfloat = false;
bool isfloat = lstparams.isFloat();
if (use_minted) {
// Get float placement, language, caption, and
// label, then remove the relative options.
@ -628,7 +631,6 @@ void InsetInclude::latex(otexstream & os, OutputParams const & runparams) const
getVectorFromString(parameters, ",", false);
for (size_t i = 0; i < opts.size(); ++i) {
if (prefixIs(opts[i], "float")) {
isfloat = true;
if (prefixIs(opts[i], "float="))
placement = opts[i].substr(6);
opts.erase(opts.begin() + i--);
@ -636,7 +638,6 @@ void InsetInclude::latex(otexstream & os, OutputParams const & runparams) const
language = opts[i].substr(9);
opts.erase(opts.begin() + i--);
} else if (prefixIs(opts[i], "caption=")) {
isfloat = true;
caption = opts[i].substr(8);
opts.erase(opts.begin() + i--);
} else if (prefixIs(opts[i], "label=")) {
@ -645,7 +646,7 @@ void InsetInclude::latex(otexstream & os, OutputParams const & runparams) const
}
}
if (!label.empty()) {
if (isfloat)
if (isfloat || !caption.empty())
label = trim(label, "{}");
else
opts.push_back("label=" + label);
@ -659,6 +660,11 @@ void InsetInclude::latex(otexstream & os, OutputParams const & runparams) const
if (!placement.empty())
os << '[' << placement << "]";
os << breakln;
} else if (use_minted && !caption.empty()) {
os << breakln << "\\lyxmintcaption[t]{" << caption;
if (!label.empty())
os << "\\label{" << label << "}";
os << "}\n";
}
os << (use_minted ? "\\inputminted" : "\\lstinputlisting");
if (!parameters.empty())
@ -1029,9 +1035,13 @@ void InsetInclude::validate(LaTeXFeatures & features) const
if (isVerbatim(params()))
features.require("verbatim");
else if (isListings(params())) {
if (buffer().params().use_minted)
if (buffer().params().use_minted) {
features.require("minted");
else
string const opts = to_utf8(params()["lstparams"]);
InsetListingsParams lstpars(opts);
if (!lstpars.isFloat() && contains(opts, "caption="))
features.require("lyxmintcaption");
} else
features.require("listings");
}

View File

@ -187,6 +187,9 @@ void InsetListings::latex(otexstream & os, OutputParams const & runparams) const
encoding_switched = true;
}
bool const captionfirst = !isfloat && par->isInset(0)
&& par->getInset(0)->lyxCode() == CAPTION_CODE;
while (par != end) {
pos_type siz = par->size();
bool captionline = false;
@ -277,10 +280,16 @@ void InsetListings::latex(otexstream & os, OutputParams const & runparams) const
}
os << delim << code << delim;
} else if (use_minted) {
OutputParams rp = runparams;
rp.moving_arg = true;
TexString caption = getCaption(rp);
if (isfloat) {
os << breakln << "\\begin{listing}";
if (!float_placement.empty())
os << '[' << float_placement << "]";
} else if (captionfirst && !caption.str.empty()) {
os << breakln << "\\lyxmintcaption[t]{"
<< move(caption) << "}\n";
}
os << breakln << "\\begin{minted}";
if (!param_string.empty())
@ -288,12 +297,12 @@ void InsetListings::latex(otexstream & os, OutputParams const & runparams) const
os << "{" << minted_language << "}\n"
<< code << breakln << "\\end{minted}\n";
if (isfloat) {
OutputParams rp = runparams;
rp.moving_arg = true;
TexString caption = getCaption(rp);
if (!caption.str.empty())
os << "\\caption{" << move(caption) << "}\n";
os << "\\end{listing}\n";
} else if (!captionfirst && !caption.str.empty()) {
os << breakln << "\\lyxmintcaption[b]{"
<< move(caption) << "}";
}
} else {
OutputParams rp = runparams;
@ -427,9 +436,7 @@ bool InsetListings::getStatus(Cursor & cur, FuncRequest const & cmd,
return true;
case LFUN_CAPTION_INSERT: {
// the inset outputs at most one caption
bool const use_minted = buffer().params().use_minted;
if (params().isInline() || getCaptionInset() ||
(use_minted && !params().isFloat())) {
if (params().isInline() || getCaptionInset()) {
status.setEnabled(false);
return true;
}
@ -452,14 +459,18 @@ docstring const InsetListings::buttonLabel(BufferView const & bv) const
void InsetListings::validate(LaTeXFeatures & features) const
{
if (buffer().params().use_minted)
features.require("minted");
else
features.require("listings");
features.useInsetLayout(getLayout());
string param_string = params().params();
if (param_string.find("\\color") != string::npos)
features.require("color");
if (buffer().params().use_minted) {
features.require("minted");
OutputParams rp = features.runparams();
if (!params().isFloat() && !getCaption(rp).str.empty())
features.require("lyxmintcaption");
} else {
features.require("listings");
if (contains(param_string, "\\color"))
features.require("color");
}
InsetCaptionable::validate(features);
}