Enable InsetQuote in verbatim and Hebrew

In this context, the inset outputs straight quotes in LaTeX.

File format change.

Fixes: #7309
This commit is contained in:
Juergen Spitzmueller 2016-12-10 11:53:42 +01:00
parent 096cfb2a12
commit e8c932ff84
9 changed files with 139 additions and 41 deletions

View File

@ -11,6 +11,11 @@ adjustments are made to tex2lyx and bugs are fixed in lyx2lyx.
-----------------------
2016-12-10 Jürgen Spitzmüller <spitz@lyx.org>
* Format incremented to 517: InsetQuote now works in verbatim
and Hebrew. On reversion, it is replaced by straight quotes
in these contexts.
2016-12-07 Günter Milde <milde@lyx.org>
* Format incremented to 516: Removed \inputenc value "pt254"

View File

@ -25,13 +25,14 @@ import sys, os
# Uncomment only what you need to import, please.
from parser_tools import find_end_of#, find_token, find_tokens, \
from parser_tools import find_end_of, find_token_backwards#,
# find_token, find_tokens, \
# find_token_exact, find_end_of_inset, find_end_of_layout, \
# find_token_backwards, is_in_inset, get_value, get_quoted_value, \
# is_in_inset, get_value, get_quoted_value, \
# del_token, check_token, get_option_value, get_bool_value
from parser_tools import find_token, find_end_of_inset, get_value, \
get_bool_value
get_bool_value, get_containing_layout
from lyx2lyx_tools import add_to_preamble, put_cmd_in_ert
# get_ert, lyx2latex, \
@ -492,6 +493,67 @@ def revert_syriac(document):
"\\end_layout", ""]
def revert_quotes(document):
" Revert Quote Insets in verbatim or Hebrew context to plain quotes "
# First handle verbatim insets
i = 0
j = 0
while i < len(document.body):
words = document.body[i].split()
if len(words) > 1 and words[0] == "\\begin_inset" and \
( words[1] in ["ERT", "listings"] or words[2] == "URL" ):
j = find_end_of_inset(document.body, i)
if j == -1:
document.warning("Malformed LyX document: Can't find end of " + words[1] + " inset at line " + str(i))
i += 1
continue
while True:
k = find_token(document.body, '\\begin_inset Quotes', i, j)
if k == -1:
i += 1
break
l = find_end_of_inset(document.body, k)
if l == -1:
document.warning("Malformed LyX document: Can't find end of Quote inset at line " + str(k))
i = k
continue
replace = "\""
if document.body[k].endswith("s"):
replace = "'"
document.body[k:l+1] = [replace]
else:
i += 1
continue
# Now handle Hebrew
i = 0
j = 0
while True:
k = find_token(document.body, '\\begin_inset Quotes', i, j)
if k == -1:
return
l = find_end_of_inset(document.body, k)
if l == -1:
document.warning("Malformed LyX document: Can't find end of Quote inset at line " + str(k))
i = k
continue
hebrew = False
parent = get_containing_layout(document.body, k)
ql = find_token_backwards(document.body, "\\lang", k)
if ql == -1 or ql < parent[1]:
hebrew = document.language == "hebrew"
elif document.body[ql] == "\\lang hebrew":
hebrew = True
if hebrew:
replace = "\""
if document.body[k].endswith("s"):
replace = "'"
document.body[k:l+1] = [replace]
i += 1
##
# Conversion hub
#
@ -506,10 +568,12 @@ convert = [
[514, []],
[515, []],
[516, [convert_inputenc]],
[517, []]
]
revert = [
[516, []],
[516, [revert_quotes]],
[515, []],
[514, [revert_urdu, revert_syriac]],
[513, [revert_amharic, revert_asturian, revert_kannada, revert_khmer]],
[512, [revert_bosnian, revert_friulan, revert_macedonian, revert_piedmontese, revert_romansh]],

View File

@ -1548,26 +1548,15 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
while (pos > 0 && par.isDeleted(pos - 1))
--pos;
BufferParams const & bufparams = bv->buffer().params();
bool const hebrew =
par.getFontSettings(bufparams, pos).language()->lang() == "hebrew";
bool const allow_inset_quote = !(par.isPassThru() || hebrew);
string const arg = to_utf8(cmd.argument());
if (allow_inset_quote) {
char_type c = ' ';
if (pos > 0 && (!cur.prevInset() || !cur.prevInset()->isSpace()))
c = par.getChar(pos - 1);
InsetQuotes::QuoteTimes const quote_type = (arg == "single")
? InsetQuotes::SingleQuotes : InsetQuotes::DoubleQuotes;
cur.insert(new InsetQuotes(cur.buffer(), c, quote_type));
cur.buffer()->updateBuffer();
cur.posForward();
} else {
// The cursor might have been invalidated by the replaceSelection.
cur.buffer()->changed(true);
string const quote_string = (arg == "single") ? "'" : "\"";
lyx::dispatch(FuncRequest(LFUN_SELF_INSERT, quote_string));
}
break;
}
@ -2860,6 +2849,7 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
case LFUN_QUOTE_INSERT:
// always allow this, since we will inset a raw quote
// if an inset is not allowed.
allow_in_passthru = true;
break;
case LFUN_SPECIALCHAR_INSERT:
code = SPECIALCHAR_CODE;

View File

@ -158,8 +158,20 @@ void InsetListings::latex(otexstream & os, OutputParams const & runparams) const
if (i == 0 && par->isInset(i) && i + 1 == siz)
captionline = true;
// ignore all struck out text and (caption) insets
if (par->isDeleted(i) || par->isInset(i))
if (par->isDeleted(i)
|| (par->isInset(i) && par->getInset(i)->lyxCode() == CAPTION_CODE))
continue;
if (par->isInset(i)) {
// Currently, this can only be a quote inset
// that is output as plain quote here, but
// we use more generic code anyway.
otexstringstream ots;
OutputParams rp = runparams;
rp.pass_thru = true;
par->getInset(i)->latex(ots, rp);
code += ots.str();
continue;
}
char_type c = par->getChar(i);
// we can only output characters covered by the current
// encoding!

View File

@ -78,7 +78,7 @@ private:
///
TexString getCaption(OutputParams const &) const;
///
bool insetAllowed(InsetCode c) const { return c == CAPTION_CODE; }
bool insetAllowed(InsetCode c) const { return c == CAPTION_CODE || c == QUOTE_CODE; }
///
InsetListingsParams params_;

View File

@ -24,6 +24,8 @@
#include "MetricsInfo.h"
#include "OutputParams.h"
#include "output_xhtml.h"
#include "Paragraph.h"
#include "ParIterator.h"
#include "texstream.h"
#include "frontends/FontMetrics.h"
@ -103,7 +105,7 @@ InsetQuotes::InsetQuotes(Buffer * buf, string const & str) : Inset(buf)
}
InsetQuotes::InsetQuotes(Buffer * buf, char_type c, QuoteTimes t)
: Inset(buf), times_(t)
: Inset(buf), times_(t), pass_thru_(false)
{
if (buf) {
language_ = buf->params().quotes_language;
@ -188,17 +190,18 @@ void InsetQuotes::parseString(string const & s)
}
// FIXME: should we add a language or a font parameter member?
docstring InsetQuotes::displayString() const
{
Language const * loclang =
isBufferValid() ? buffer().params().language : 0;
// In PassThru and Hebrew, we use straight quotes
if (pass_thru_ || context_lang_ == "he_IL")
return (times_ == DoubleQuotes) ? from_ascii("\"") : from_ascii("'");
int const index = quote_index[side_][language_];
docstring retdisp = docstring(1, display_quote_char[times_][index]);
// in french, thin spaces are added inside double quotes
// in French, thin spaces are added inside double quotes
// FIXME: this should be done by a separate quote type.
if (times_ == DoubleQuotes && loclang && prefixIs(loclang->code(), "fr")) {
if (times_ == DoubleQuotes && prefixIs(context_lang_, "fr")) {
// THIN SPACE (U+2009)
char_type const thin_space = 0x2009;
if (side_ == LeftQuote)
@ -253,7 +256,13 @@ void InsetQuotes::latex(otexstream & os, OutputParams const & runparams) const
const int quoteind = quote_index[side_][language_];
string qstr;
if (language_ == FrenchQuotes && times_ == DoubleQuotes
// In some context, we output plain quotes
bool const force_plain =
runparams.pass_thru
|| runparams.local_font->language()->lang() == "hebrew";
if (force_plain)
qstr = (times_ == DoubleQuotes) ? "\"" : "'";
else if (language_ == FrenchQuotes && times_ == DoubleQuotes
&& prefixIs(runparams.local_font->language()->code(), "fr")
&& !runparams.use_polyglossia) {
if (side_ == LeftQuote)
@ -273,6 +282,7 @@ void InsetQuotes::latex(otexstream & os, OutputParams const & runparams) const
qstr = latex_quote_babel[times_][quoteind];
}
if (!force_plain) {
// Always guard against unfortunate ligatures (!` ?` `` '' ,, << >>)
char_type const lastchar = os.lastChar();
if (prefixIs(qstr, "`")) {
@ -281,6 +291,7 @@ void InsetQuotes::latex(otexstream & os, OutputParams const & runparams) const
}
if (qstr[1] == lastchar)
qstr.insert(0, "{}");
}
os << from_ascii(qstr);
}
@ -327,6 +338,14 @@ void InsetQuotes::forOutliner(docstring & os, size_t const, bool const) const
}
void InsetQuotes::updateBuffer(ParIterator const & it, UpdateType /* utype*/)
{
BufferParams const & bp = buffer().masterBuffer()->params();
pass_thru_ = it.paragraph().isPassThru();
context_lang_ = it.paragraph().getFontSettings(bp, it.pos()).language()->code();
}
void InsetQuotes::validate(LaTeXFeatures & features) const
{
char type = quote_char[quote_index[side_][language_]];

View File

@ -90,6 +90,9 @@ public:
///
void forOutliner(docstring &, size_t const maxlen, bool const) const;
/// Update the contextual information of this inset
void updateBuffer(ParIterator const &, UpdateType);
///
void validate(LaTeXFeatures &) const;
///
@ -118,6 +121,10 @@ private:
QuoteTimes times_;
///
std::string fontenc_;
/// Code of the contextual language
std::string context_lang_;
/// Is this in a pass-thru context?
bool pass_thru_;
};
} // namespace lyx

View File

@ -768,8 +768,9 @@ ParagraphList & InsetText::paragraphs()
bool InsetText::insetAllowed(InsetCode code) const
{
switch (code) {
// Arguments are also allowed in PassThru insets
// Arguments and (plain) quotes are also allowed in PassThru insets
case ARG_CODE:
case QUOTE_CODE:
return true;
default:
return !isPassThru();

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
// independent branches. Instead add your own.
#define LYX_FORMAT_LYX 516 // Removed \inputenc value "pt254"
#define LYX_FORMAT_TEX2LYX 516
#define LYX_FORMAT_LYX 517 // spitz: quote inset in verbatim
#define LYX_FORMAT_TEX2LYX 517
#if LYX_FORMAT_TEX2LYX != LYX_FORMAT_LYX
#ifndef _MSC_VER