mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-12-22 13:18:28 +00:00
fix bug 1750
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@9444 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
parent
46756fd9e4
commit
d7b224d692
@ -1,3 +1,17 @@
|
||||
2005-01-04 Georg Baum <Georg.Baum@post.rwth-aachen.de>
|
||||
|
||||
* preamble.C (parse_preamble): handle second optional arg of
|
||||
\newcommand etc. and add the command to the known commands (fixes
|
||||
bug 1750)
|
||||
* texparser.[Ch] (getFullArg): new, like getArg but distinguish
|
||||
between empty arguments and no argument found
|
||||
* texparser.[Ch] (getFullOpt): new, like getOpt but distinguish
|
||||
between empty arguments and no argument found
|
||||
* tex2lyx.[Ch]: (add_known_command): new
|
||||
* text.C (parse_text): handle \newcommand etc. (see above)
|
||||
* text.C (parse_text): add comment about \underline
|
||||
* text.C (getCiteArguments): use getFullOpt
|
||||
|
||||
2004-12-15 Georg Baum <Georg.Baum@post.rwth-aachen.de>
|
||||
|
||||
* table.C (ColInfo, LTRowType, RowInfo, CellInfo, verbose_align):
|
||||
|
@ -329,7 +329,8 @@ LyXTextClass const parse_preamble(Parser & p, ostream & os, string const & force
|
||||
star = true;
|
||||
}
|
||||
string const name = p.verbatim_item();
|
||||
string const opts = p.getOpt();
|
||||
string const opt1 = p.getOpt();
|
||||
string const opt2 = p.getFullOpt();
|
||||
string const body = p.verbatim_item();
|
||||
// only non-lyxspecific stuff
|
||||
if ( name != "\\noun"
|
||||
@ -345,8 +346,12 @@ LyXTextClass const parse_preamble(Parser & p, ostream & os, string const & force
|
||||
ss << '\\' << t.cs();
|
||||
if (star)
|
||||
ss << '*';
|
||||
ss << '{' << name << '}' << opts << '{' << body << "}";
|
||||
ss << '{' << name << '}' << opt1 << opt2
|
||||
<< '{' << body << "}";
|
||||
h_preamble << ss.str();
|
||||
|
||||
// Add the command to the known commands
|
||||
add_known_command(name, opt1, !opt2.empty());
|
||||
/*
|
||||
ostream & out = in_preamble ? h_preamble : os;
|
||||
out << "\\" << t.cs() << "{" << name << "}"
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "lyxtextclass.h"
|
||||
#include "support/path_defines.h"
|
||||
#include "support/filetools.h"
|
||||
#include "support/lstrings.h"
|
||||
#include "support/lyxlib.h"
|
||||
#include "support/os.h"
|
||||
|
||||
@ -46,6 +47,10 @@ using std::string;
|
||||
using std::vector;
|
||||
using std::map;
|
||||
|
||||
using lyx::support::isStrUnsignedInt;
|
||||
using lyx::support::ltrim;
|
||||
using lyx::support::rtrim;
|
||||
using lyx::support::strToUnsignedInt;
|
||||
using lyx::support::system_lyxdir;
|
||||
using lyx::support::user_lyxdir;
|
||||
using lyx::support::IsFileReadable;
|
||||
@ -119,6 +124,34 @@ string active_environment()
|
||||
map<string, vector<ArgumentType> > known_commands;
|
||||
|
||||
|
||||
void add_known_command(string const & command, string const & o1,
|
||||
bool o2)
|
||||
{
|
||||
// We have to handle the following cases:
|
||||
// definition o1 o2 invocation result
|
||||
// \newcommand{\foo}{bar} "" false \foo bar
|
||||
// \newcommand{\foo}[1]{bar #1} "[1]" false \foo{x} bar x
|
||||
// \newcommand{\foo}[1][]{bar #1} "[1]" true \foo bar
|
||||
// \newcommand{\foo}[1][]{bar #1} "[1]" true \foo[x] bar x
|
||||
// \newcommand{\foo}[1][x]{bar #1} "[1]" true \foo[x] bar x
|
||||
unsigned int nargs = 0;
|
||||
vector<ArgumentType> arguments;
|
||||
string const opt1 = rtrim(ltrim(o1, "["), "]");
|
||||
if (isStrUnsignedInt(opt1)) {
|
||||
// The command has arguments
|
||||
nargs = strToUnsignedInt(opt1);
|
||||
if (nargs > 0 && o2) {
|
||||
// The first argument is optional
|
||||
arguments.push_back(optional);
|
||||
--nargs;
|
||||
}
|
||||
}
|
||||
for (unsigned int i = 0; i < nargs; ++i)
|
||||
arguments.push_back(required);
|
||||
known_commands[command] = arguments;
|
||||
}
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
|
@ -62,6 +62,15 @@ std::string join(std::vector<std::string> const & input,
|
||||
bool is_math_env(std::string const & name);
|
||||
char const * const * is_known(std::string const &, char const * const *);
|
||||
|
||||
/*!
|
||||
* Adds the command \p command to the list of known commands.
|
||||
* \param o1 first optional parameter to the latex command \newcommand
|
||||
* (with brackets), or the empty string if there were no optional arguments.
|
||||
* \param o2 wether \newcommand had a second optional parameter
|
||||
*/
|
||||
void add_known_command(std::string const & command, std::string const & o1,
|
||||
bool o2);
|
||||
|
||||
// Access to environment stack
|
||||
extern std::vector<std::string> active_environments;
|
||||
std::string active_environment();
|
||||
|
@ -271,21 +271,22 @@ char Parser::getChar()
|
||||
}
|
||||
|
||||
|
||||
string Parser::getArg(char left, char right)
|
||||
Parser::Arg Parser::getFullArg(char left, char right)
|
||||
{
|
||||
skip_spaces(true);
|
||||
|
||||
// This is needed if a partial file ends with a command without arguments,
|
||||
// e. g. \medskip
|
||||
if (! good())
|
||||
return string();
|
||||
return std::make_pair(false, string());
|
||||
|
||||
string result;
|
||||
char c = getChar();
|
||||
|
||||
if (c != left)
|
||||
if (c != left) {
|
||||
putback();
|
||||
else
|
||||
return std::make_pair(false, string());
|
||||
} else
|
||||
while ((c = getChar()) != right && good()) {
|
||||
// Ignore comments
|
||||
if (curr_token().cat() == catComment) {
|
||||
@ -296,14 +297,29 @@ string Parser::getArg(char left, char right)
|
||||
result += curr_token().asInput();
|
||||
}
|
||||
|
||||
return result;
|
||||
return std::make_pair(true, result);
|
||||
}
|
||||
|
||||
|
||||
string Parser::getArg(char left, char right)
|
||||
{
|
||||
return getFullArg(left, right).second;
|
||||
}
|
||||
|
||||
|
||||
string Parser::getFullOpt()
|
||||
{
|
||||
Arg arg = getFullArg('[', ']');
|
||||
if (arg.first)
|
||||
return '[' + arg.second + ']';
|
||||
return arg.second;
|
||||
}
|
||||
|
||||
|
||||
string Parser::getOpt()
|
||||
{
|
||||
string const res = getArg('[', ']');
|
||||
return res.size() ? '[' + res + ']' : string();
|
||||
return res.empty() ? string() : '[' + res + ']';
|
||||
}
|
||||
|
||||
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
|
||||
enum mode_type {UNDECIDED_MODE, TEXT_MODE, MATH_MODE, MATHTEXT_MODE, TABLE_MODE};
|
||||
@ -127,8 +128,27 @@ public:
|
||||
void dump() const;
|
||||
|
||||
///
|
||||
typedef std::pair<bool, std::string> Arg;
|
||||
/*!
|
||||
* Get an argument enclosed by \p left and \p right.
|
||||
* \returns wether an argument was found in \p Arg.first and the
|
||||
* argument in \p Arg.second. \see getArg().
|
||||
*/
|
||||
Arg getFullArg(char left, char right);
|
||||
/*!
|
||||
* Get an argument enclosed by \p left and \p right.
|
||||
* \returns the argument (without \p left and \p right) or the empty
|
||||
* string if the next non-space token is not \p left. Use
|
||||
* getFullArg() if you need to know wether there was an empty
|
||||
* argument or no argument at all.
|
||||
*/
|
||||
std::string getArg(char left, char right);
|
||||
/// getArg('[', ']') including the brackets
|
||||
/*!
|
||||
* \returns getFullArg('[', ']') including the brackets or the
|
||||
* empty string if no argument was found.
|
||||
*/
|
||||
std::string getFullOpt();
|
||||
/// \returns getArg('[', ']') including the brackets
|
||||
std::string getOpt();
|
||||
/// Returns the character of the current token and increments the token position.
|
||||
char getChar();
|
||||
|
@ -848,29 +848,19 @@ void parse_text_attributes(Parser & p, ostream & os, unsigned flags, bool outer,
|
||||
|
||||
|
||||
/// get the arguments of a natbib or jurabib citation command
|
||||
std::pair<string, string> getCiteArguments(Parser & p, ostream & os,
|
||||
Context & context, bool natbibOrder)
|
||||
std::pair<string, string> getCiteArguments(Parser & p, bool natbibOrder)
|
||||
{
|
||||
// We need to distinguish "" and "[]", so we can't use p.getOpt().
|
||||
|
||||
// text before the citation
|
||||
string before;
|
||||
// text after the citation
|
||||
string after;
|
||||
string after = p.getFullOpt();
|
||||
|
||||
eat_whitespace(p, os, context, false);
|
||||
if (p.next_token().asInput() == "[") {
|
||||
after = '[' + p.getArg('[', ']') + ']';
|
||||
eat_whitespace(p, os, context, false);
|
||||
if (natbibOrder) {
|
||||
if (p.next_token().asInput() == "[") {
|
||||
before = after;
|
||||
after = '[' + p.getArg('[', ']') + ']';
|
||||
}
|
||||
} else {
|
||||
if (p.next_token().asInput() == "[")
|
||||
before = '[' + p.getArg('[', ']') + ']';
|
||||
}
|
||||
if (!after.empty()) {
|
||||
before = p.getFullOpt();
|
||||
if (natbibOrder && !before.empty())
|
||||
std::swap(before, after);
|
||||
}
|
||||
return std::make_pair(before, after);
|
||||
}
|
||||
@ -1445,6 +1435,9 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
|
||||
}
|
||||
|
||||
else if (t.cs() == "underbar") {
|
||||
// Do NOT handle \underline.
|
||||
// \underbar cuts through y, g, q, p etc.,
|
||||
// \underline does not.
|
||||
context.check_layout(os);
|
||||
os << "\n\\bar under\n";
|
||||
parse_text_snippet(p, os, FLAG_ITEM, outer, context);
|
||||
@ -1484,8 +1477,7 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
|
||||
// text after the citation
|
||||
string after;
|
||||
|
||||
boost::tie(before, after) =
|
||||
getCiteArguments(p, os, context, true);
|
||||
boost::tie(before, after) = getCiteArguments(p, true);
|
||||
if (command == "\\cite") {
|
||||
// \cite without optional argument means
|
||||
// \citet, \cite with at least one optional
|
||||
@ -1528,8 +1520,7 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
|
||||
string after;
|
||||
|
||||
boost::tie(before, after) =
|
||||
getCiteArguments(p, os, context,
|
||||
argumentOrder != 'j');
|
||||
getCiteArguments(p, argumentOrder != 'j');
|
||||
string const citation = p.verbatim_item();
|
||||
if (!before.empty() && argumentOrder == '\0') {
|
||||
cerr << "Warning: Assuming argument order "
|
||||
@ -1851,6 +1842,27 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
|
||||
skip_braces(p);
|
||||
}
|
||||
|
||||
else if (t.cs() == "newcommand" ||
|
||||
t.cs() == "providecommand" ||
|
||||
t.cs() == "renewcommand") {
|
||||
// these could be handled by parse_command(), but
|
||||
// we need to call add_known_command() here.
|
||||
string name = t.asInput();
|
||||
if (p.next_token().asInput() == "*") {
|
||||
// Starred form. Eat '*'
|
||||
p.get_token();
|
||||
name += '*';
|
||||
}
|
||||
string const command = p.verbatim_item();
|
||||
string const opt1 = p.getOpt();
|
||||
string const opt2 = p.getFullOpt();
|
||||
add_known_command(command, opt1, !opt2.empty());
|
||||
string const ert = name + '{' + command + '}' +
|
||||
opt1 + opt2 +
|
||||
'{' + p.verbatim_item() + '}';
|
||||
handle_ert(os, ert, context);
|
||||
}
|
||||
|
||||
else if (t.cs() == "vspace") {
|
||||
bool starred = false;
|
||||
if (p.next_token().asInput() == "*") {
|
||||
|
Loading…
Reference in New Issue
Block a user