]> git.lyx.org Git - features.git/commitdiff
Fix pasting as LaTeX in documents with no modules
authorJean-Marc Lasgouttes <lasgouttes@lyx.org>
Thu, 27 Oct 2022 15:26:53 +0000 (17:26 +0200)
committerJean-Marc Lasgouttes <lasgouttes@lyx.org>
Sun, 6 Nov 2022 12:20:02 +0000 (13:20 +0100)
When there is no module, the old code would invoke tex2lyx with option
 -m
instead of
 -m ""
and an error would ensue.

This is because the QProcess command line parser used in Systemcall is
broken and does not recognize empty parameters as such. The solution
is to rewrite our parsecmd() parser to generate a list of parameters.
This is post-2.4.0 work.

The workaround used here is:

- set the list of modules to "," when it should be empty. In effect,
  this is a list of two empty modules.

- change tex2lyx to accept empty module names and ignore them; this is
  good in terms of robustness anyway.

Additionally, when there is no receiving buffer, set the defaults as
the BufferParams defaults instead of empty (this is cleaner, but
should not make a difference in practice).

In the long term, we should switch to use the QStringList-based API of
QProcess in Systemcall (see QTBUG-80640).

src/BufferParams.cpp
src/BufferParams.h
src/Converter.cpp
src/support/Systemcall.cpp
src/tex2lyx/tex2lyx.cpp

index f7516fc0269019a98133fb3166a1f1fe29cc9257..6bb90d0be0b1a8d323d8946254757fab67b8bac6 100644 (file)
@@ -3840,5 +3840,11 @@ string const BufferParams::bibFileEncoding(string const & file) const
 }
 
 
+BufferParams const & defaultBufferParams()
+{
+       static BufferParams default_params;
+       return default_params;
+}
+
 
 } // namespace lyx
index 890d8843a7e2ae68a56c0aef76766ecadd14892a..77b4856b4d3bca7b6a435c85c467f1a510354d67 100644 (file)
@@ -691,6 +691,10 @@ private:
        support::copied_ptr<Impl, MemoryTraits> pimpl_;
 };
 
+
+///
+BufferParams const & defaultBufferParams();
+
 } // namespace lyx
 
 #endif
index 172b2a20914ea7c97d4df8089b41966c0f4e625c..b63f77146a6f57e4dee563ef07d0e3066a553071 100644 (file)
@@ -646,21 +646,24 @@ Converters::RetVal Converters::convert(Buffer const * buffer,
                                to_utf8(makeRelPath(from_utf8(outfile.absFileName()), from_utf8(path)));
 
                        string command = conv.command();
+                       BufferParams const & bparams = buffer ? buffer->params() : defaultBufferParams();
                        command = subst(command, token_from, quoteName(infile2));
                        command = subst(command, token_base, quoteName(from_base));
                        command = subst(command, token_to, quoteName(outfile2));
                        command = subst(command, token_path, quoteName(onlyPath(infile.absFileName())));
                        command = subst(command, token_orig_path, quoteName(onlyPath(orig_from.absFileName())));
                        command = subst(command, token_orig_from, quoteName(onlyFileName(orig_from.absFileName())));
-                       command = subst(command, token_textclass,
-                                       buffer ? quoteName(buffer->params().documentClass().name())
-                                              : string());
-                       command = subst(command, token_modules,
-                                       buffer ? quoteName(buffer->params().getModules().asString())
-                                              : string());
-                       command = subst(command, token_encoding,
-                                       buffer ? quoteName(buffer->params().encoding().iconvName())
-                                              : string());
+                       command = subst(command, token_textclass, quoteName(bparams.documentClass().name()));
+                       string modules = bparams.getModules().asString();
+                       // FIXME: remove when SystemCall uses QProcess with the list API.
+                       // Currently the QProcess parser is not able to encode an
+                       // empty argument as ""; work around this by passing a
+                       // single comma, that will be interpreted as a list of two
+                       // empty module names.
+                       if (modules.empty())
+                               modules = ",";
+                       command = subst(command, token_modules, quoteName(modules));
+                       command = subst(command, token_encoding, quoteName(bparams.encoding().iconvName()));
                        command = subst(command, token_python, os::python());
 
                        if (!conv.parselog().empty())
index d339e11b804e1c53c059a6130e0214898b258705..20fe1034b96d43f735941097197c446943332a81 100644 (file)
@@ -392,6 +392,11 @@ void SystemcallPrivate::startProcess(QString const & cmd, string const & path,
         * The cleanest solution would be to have parsecmd() produce a
         * QStringList for arguments, instead of transforming the string
         * into something that the QProcess splitter accepts.
+        *
+        * Another reason for doing that is that the Qt parser ignores
+        * empty "" arguments, which are needed in some instances (see
+        * e.g. the work around for modules in Converter:convert. See
+        * QTBUG-80640 for a discussion.
        */
        QStringList arguments = QProcess::splitCommand(toqstr(latexEnvCmdPrefix(path, lpath)) + cmd_);
        QString command = (arguments.empty()) ? QString() : arguments.first();
index 1b11a45ba43515be484b18605ed84d177ee5b366..0d588d283868102e0be479ac12f43b4f71104680 100644 (file)
@@ -699,8 +699,6 @@ int parse_class(string const & arg, string const &)
 
 int parse_module(string const & arg, string const &)
 {
-       if (arg.empty())
-               error_message("Missing modules string after -m switch");
        split(arg, preloaded_modules, ',');
        return 1;
 }
@@ -924,11 +922,12 @@ bool tex2lyx(idocstream & is, ostream & os, string const & encoding,
 
        // Load preloaded modules.
        // This needs to be done after the preamble is parsed, since the text
-       // class may not be known before. It neds to be done before parsing
+       // class may not be known before. It needs to be done before parsing
        // body, since otherwise the commands/environments provided by the
        // modules would be parsed as ERT.
+       // Empty module names are silently skipped.
        for (auto const & module : preloaded_modules) {
-               if (!addModule(module)) {
+               if (!module.empty() && !addModule(module)) {
                        cerr << "Error: Could not load module \""
                             << module << "\"." << endl;
                        return false;