mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-22 10:00:33 +00:00
Add -copyfiles command line option to tex2lyx
If this option is given, included files will be copied to the output directory. Also -roundtrip is now allowed with given output file. -copyfiles is useful if you want to ensure that no file (not even an included one) is overwritten by a subsequent export from LyX. Both changes are needed for unit tests that do not write to the source directory.
This commit is contained in:
parent
02c73cd721
commit
24181cf28e
@ -21,7 +21,7 @@ options.
|
||||
.PP
|
||||
\fBtex2lyx\fR [ \fB\-userdir\fR \fIuserdir\fR ] [ \fB\-systemdir\fR \fIsystemdir\fR ]
|
||||
[ \fB\-n\fR ] [ \fB\-c\fR \fItextclass\fR ] [\ \fB\-s\fR\ \fIsfile1\fR[,\fIsfile2\fR...]] [
|
||||
\fB\-roundtrip\fR ] \fIinputfile\fR [ \fIoutputfile\fR ]
|
||||
\fB\-roundtrip\fR ] [ \fB\-copyfiles\fR ] \fIinputfile\fR [ \fIoutputfile\fR ]
|
||||
.\" .PP
|
||||
.\" \fBtex2lyx\fR [ \fB\-userdir\fR \fIuserdir\fR ] [ \fB\-systemdir\fR \fIsystemdir\fR ]
|
||||
.\" [\ \fB\-r\fR\ \fIrenv1\fR[,\fIrenv2\fR...]] [\ \fB\-s\fR\ \fIsfile1\fR[,\fIsfile2\fR...]]
|
||||
@ -70,12 +70,21 @@ Specify a user directory. Normally, you shouldn't need this. Your LyX user direc
|
||||
chosen. Cf. the section \f(CWFILES\fR for details.
|
||||
.TP
|
||||
.BI \-roundtrip
|
||||
Call LyX to re-export the created output file to LaTeX. The output file name
|
||||
is always determined automatically to avoid over-writing the input file by
|
||||
accident: If the input file is named \fIfoo.tex\fR the output file will be
|
||||
Call LyX to re-export the created output file to LaTeX. If the output file name
|
||||
is not given it is determined automatically to avoid over-writing the input file
|
||||
by accident: If the input file is named \fIfoo.tex\fR the output file will be
|
||||
named \fIfoo.lyx.lyx\fR, and the re-exported file will be named
|
||||
\fIfoo.lyx.tex\fR.
|
||||
.TP
|
||||
.BI \-copyfiles
|
||||
Copy all included files below the input directory and that \fBtex2lyx\fR is
|
||||
aware of to the output directory if the output file is located in a different
|
||||
directory than the input file. This is useful if you want to ensure that no
|
||||
included file is overwritten (either in roundtrip mode or by a later export
|
||||
from LyX). Please note that the resulting document may be uncompilable. This
|
||||
happens if it needs files that \fBtex2lyx\fR does not know about and therefore
|
||||
does not copy to the output directory.
|
||||
.TP
|
||||
.BI \-help
|
||||
Help. Print out usage information and quit.
|
||||
.TP
|
||||
|
@ -446,6 +446,7 @@ void read_syntaxfile(FileName const & file_name)
|
||||
string documentclass;
|
||||
string default_encoding;
|
||||
string syntaxfile;
|
||||
bool copy_files = false;
|
||||
bool overwrite_files = false;
|
||||
int error_code = 0;
|
||||
|
||||
@ -458,6 +459,7 @@ int parse_help(string const &, string const &)
|
||||
cerr << "Usage: tex2lyx [options] infile.tex [outfile.lyx]\n"
|
||||
"Options:\n"
|
||||
"\t-c textclass Declare the textclass.\n"
|
||||
"\t-copyfiles Copy all included files to the directory of outfile.lyx.\n"
|
||||
"\t-e encoding Set the default encoding (latex name).\n"
|
||||
"\t-f Force overwrite of .lyx files.\n"
|
||||
"\t-help Print this message and quit.\n"
|
||||
@ -571,6 +573,13 @@ int parse_roundtrip(string const &, string const &)
|
||||
}
|
||||
|
||||
|
||||
int parse_copyfiles(string const &, string const &)
|
||||
{
|
||||
copy_files = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void easyParse(int & argc, char * argv[])
|
||||
{
|
||||
map<string, cmd_helper> cmdmap;
|
||||
@ -589,6 +598,7 @@ void easyParse(int & argc, char * argv[])
|
||||
cmdmap["-sysdir"] = parse_sysdir;
|
||||
cmdmap["-userdir"] = parse_userdir;
|
||||
cmdmap["-roundtrip"] = parse_roundtrip;
|
||||
cmdmap["-copyfiles"] = parse_copyfiles;
|
||||
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
map<string, cmd_helper>::const_iterator it
|
||||
@ -619,21 +629,42 @@ void easyParse(int & argc, char * argv[])
|
||||
|
||||
|
||||
// path of the first parsed file
|
||||
string masterFilePath;
|
||||
string masterFilePathLyX;
|
||||
string masterFilePathTeX;
|
||||
// path of the currently parsed file
|
||||
string parentFilePath;
|
||||
string parentFilePathTeX;
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
string getMasterFilePath()
|
||||
string getMasterFilePath(bool input)
|
||||
{
|
||||
return masterFilePath;
|
||||
return input ? masterFilePathTeX : masterFilePathLyX;
|
||||
}
|
||||
|
||||
string getParentFilePath()
|
||||
string getParentFilePath(bool input)
|
||||
{
|
||||
return parentFilePath;
|
||||
if (input)
|
||||
return parentFilePathTeX;
|
||||
string const rel = to_utf8(makeRelPath(from_utf8(masterFilePathTeX),
|
||||
from_utf8(parentFilePathTeX)));
|
||||
if (rel.substr(0, 3) == "../") {
|
||||
// The parent is not below the master - keep the path
|
||||
return parentFilePathTeX;
|
||||
}
|
||||
return makeAbsPath(rel, masterFilePathLyX).absFileName();
|
||||
}
|
||||
|
||||
|
||||
bool copyFiles()
|
||||
{
|
||||
return copy_files;
|
||||
}
|
||||
|
||||
|
||||
bool overwriteFiles()
|
||||
{
|
||||
return overwrite_files;
|
||||
}
|
||||
|
||||
|
||||
@ -645,7 +676,7 @@ namespace {
|
||||
* be used more than once for included documents.
|
||||
* Caution: Overwrites the existing preamble settings if the new document
|
||||
* contains a preamble.
|
||||
* You must ensure that \p parentFilePath is properly set before calling
|
||||
* You must ensure that \p parentFilePathTeX is properly set before calling
|
||||
* this function!
|
||||
*/
|
||||
bool tex2lyx(idocstream & is, ostream & os, string encoding)
|
||||
@ -720,10 +751,10 @@ bool tex2lyx(FileName const & infilename, ostream & os, string const & encoding)
|
||||
<< "\" for reading." << endl;
|
||||
return false;
|
||||
}
|
||||
string const oldParentFilePath = parentFilePath;
|
||||
parentFilePath = onlyPath(infilename.absFileName());
|
||||
string const oldParentFilePath = parentFilePathTeX;
|
||||
parentFilePathTeX = onlyPath(infilename.absFileName());
|
||||
bool retval = tex2lyx(is, os, encoding);
|
||||
parentFilePath = oldParentFilePath;
|
||||
parentFilePathTeX = oldParentFilePath;
|
||||
return retval;
|
||||
}
|
||||
|
||||
@ -826,20 +857,28 @@ int main(int argc, char * argv[])
|
||||
infilename = makeAbsPath(infilename).absFileName();
|
||||
|
||||
string outfilename;
|
||||
if (roundtrip) {
|
||||
if (argc > 2) {
|
||||
// Do not allow a user supplied output filename
|
||||
// (otherwise it could easily happen that LyX would
|
||||
// overwrite the original .tex file)
|
||||
cerr << "Error: output filename must not be given in roundtrip mode."
|
||||
<< endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
outfilename = changeExtension(infilename, ".lyx.lyx");
|
||||
} else if (argc > 2) {
|
||||
if (argc > 2) {
|
||||
outfilename = internal_path(os::utf8_argv(2));
|
||||
if (outfilename != "-")
|
||||
outfilename = makeAbsPath(outfilename).absFileName();
|
||||
if (roundtrip) {
|
||||
if (outfilename == "-") {
|
||||
cerr << "Error: Writing to standard output is "
|
||||
"not supported in roundtrip mode."
|
||||
<< endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
string texfilename = changeExtension(outfilename, ".tex");
|
||||
if (equivalent(FileName(infilename), FileName(texfilename))) {
|
||||
cerr << "Error: The input file `" << infilename
|
||||
<< "´ would be overwritten by the TeX file exported from `"
|
||||
<< outfilename << "´ in roundtrip mode." << endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
} else if (roundtrip) {
|
||||
// avoid overwriting the input file
|
||||
outfilename = changeExtension(infilename, ".lyx.lyx");
|
||||
} else
|
||||
outfilename = changeExtension(infilename, ".lyx");
|
||||
|
||||
@ -876,17 +915,22 @@ int main(int argc, char * argv[])
|
||||
theModuleList.read();
|
||||
|
||||
// The real work now.
|
||||
masterFilePath = onlyPath(infilename);
|
||||
parentFilePath = masterFilePath;
|
||||
masterFilePathTeX = onlyPath(infilename);
|
||||
parentFilePathTeX = masterFilePathTeX;
|
||||
if (outfilename == "-") {
|
||||
// assume same directory as input file
|
||||
masterFilePathLyX = masterFilePathTeX;
|
||||
if (tex2lyx(FileName(infilename), cout, default_encoding))
|
||||
return EXIT_SUCCESS;
|
||||
} else if (roundtrip) {
|
||||
if (tex2tex(infilename, FileName(outfilename), default_encoding))
|
||||
return EXIT_SUCCESS;
|
||||
} else {
|
||||
if (tex2lyx(infilename, FileName(outfilename), default_encoding))
|
||||
return EXIT_SUCCESS;
|
||||
masterFilePathLyX = onlyPath(outfilename);
|
||||
if (roundtrip) {
|
||||
if (tex2tex(infilename, FileName(outfilename), default_encoding))
|
||||
return EXIT_SUCCESS;
|
||||
} else {
|
||||
if (tex2lyx(infilename, FileName(outfilename), default_encoding))
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
}
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
@ -173,10 +173,14 @@ extern bool is_nonCJKJapanese;
|
||||
/// LyX format that is created by tex2lyx
|
||||
extern int const LYX_FORMAT;
|
||||
|
||||
/// path of the master .tex file
|
||||
extern std::string getMasterFilePath();
|
||||
/// path of the currently processed .tex file
|
||||
extern std::string getParentFilePath();
|
||||
/// Absolute path of the master .lyx or .tex file
|
||||
extern std::string getMasterFilePath(bool input);
|
||||
/// Absolute path of the currently processed .lyx or .tex file
|
||||
extern std::string getParentFilePath(bool input);
|
||||
/// Is it allowed to overwrite existing files?
|
||||
extern bool overwriteFiles();
|
||||
/// Do we need to copy included files to the output directory?
|
||||
extern bool copyFiles();
|
||||
|
||||
|
||||
/*!
|
||||
|
@ -1834,15 +1834,88 @@ string const normalize_filename(string const & name)
|
||||
|
||||
/// Convert \p name from TeX convention (relative to master file) to LyX
|
||||
/// convention (relative to .lyx file) if it is relative
|
||||
void fix_relative_filename(string & name)
|
||||
void fix_child_filename(string & name)
|
||||
{
|
||||
if (FileName::isAbsolute(name))
|
||||
return;
|
||||
string const absMasterTeX = getMasterFilePath(true);
|
||||
bool const isabs = FileName::isAbsolute(name);
|
||||
// convert from "relative to .tex master" to absolute original path
|
||||
if (!isabs)
|
||||
name = makeAbsPath(name, absMasterTeX).absFileName();
|
||||
bool copyfile = copyFiles();
|
||||
// convert from absolute original path to "relative to master file"
|
||||
string const rel = to_utf8(makeRelPath(from_utf8(name),
|
||||
from_utf8(absMasterTeX)));
|
||||
// Do not copy if the file is not in or below the directory of the
|
||||
// master, since in this case the new path might be impossible to
|
||||
// create. Example:
|
||||
// absMasterTeX = "/foo/bar/"
|
||||
// absMasterLyX = "/bar/"
|
||||
// name = "/baz.eps" => new absolute name would be "/../baz.eps"
|
||||
if (copyfile && rel.substr(0, 3) == "../")
|
||||
copyfile = false;
|
||||
string const absParentLyX = getParentFilePath(false);
|
||||
if (copyfile) {
|
||||
// re-interpret "relative to .tex file" as "relative to .lyx file"
|
||||
// (is different if the master .lyx file resides in a
|
||||
// different path than the master .tex file)
|
||||
string const absMasterLyX = getMasterFilePath(false);
|
||||
name = makeAbsPath(rel, absMasterLyX).absFileName();
|
||||
if (!isabs) {
|
||||
// convert from absolute original path to
|
||||
// "relative to .lyx file"
|
||||
name = to_utf8(makeRelPath(from_utf8(name),
|
||||
from_utf8(absParentLyX)));
|
||||
}
|
||||
}
|
||||
else if (!isabs) {
|
||||
// convert from absolute original path to "relative to .lyx file"
|
||||
name = to_utf8(makeRelPath(from_utf8(name),
|
||||
from_utf8(absParentLyX)));
|
||||
}
|
||||
}
|
||||
|
||||
string const absMaster = makeAbsPath(getMasterFilePath()).absFileName();
|
||||
string const absParent = makeAbsPath(getParentFilePath()).absFileName();
|
||||
string const abs = makeAbsPath(name, absMaster).absFileName();
|
||||
name = to_utf8(makeRelPath(from_utf8(abs), from_utf8(absParent)));
|
||||
|
||||
void copy_file(FileName const & src, string dstname)
|
||||
{
|
||||
if (!copyFiles())
|
||||
return;
|
||||
string const absParent = getParentFilePath(false);
|
||||
FileName dst;
|
||||
if (FileName::isAbsolute(dstname))
|
||||
dst = FileName(dstname);
|
||||
else
|
||||
dst = makeAbsPath(dstname, absParent);
|
||||
string const absMaster = getMasterFilePath(false);
|
||||
string const rel = to_utf8(makeRelPath(from_utf8(dst.absFileName()),
|
||||
from_utf8(absMaster)));
|
||||
// Do not copy if the file is not in or below the directory of the
|
||||
// master (see above)
|
||||
if (rel.substr(0, 3) == "../")
|
||||
return;
|
||||
FileName const srcpath = src.onlyPath();
|
||||
FileName const dstpath = dst.onlyPath();
|
||||
if (equivalent(srcpath, dstpath))
|
||||
return;
|
||||
if (!dstpath.isDirectory()) {
|
||||
if (!dstpath.createPath()) {
|
||||
cerr << "Warning: Could not create directory for file `"
|
||||
<< dst.absFileName() << "´." << endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (dst.isReadableFile()) {
|
||||
if (overwriteFiles())
|
||||
cerr << "Warning: Overwriting existing file `"
|
||||
<< dst.absFileName() << "´." << endl;
|
||||
else {
|
||||
cerr << "Warning: Not overwriting existing file `"
|
||||
<< dst.absFileName() << "´." << endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!src.copyTo(dst))
|
||||
cerr << "Warning: Could not copy file `" << src.absFileName()
|
||||
<< "´ to `" << dst.absFileName() << "´." << endl;
|
||||
}
|
||||
|
||||
|
||||
@ -2533,7 +2606,7 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
|
||||
skip_braces(p);
|
||||
p.get_token();
|
||||
string name = normalize_filename(p.verbatim_item());
|
||||
string const path = makeAbsPath(getMasterFilePath()).absFileName();
|
||||
string const path = getMasterFilePath(true);
|
||||
// We want to preserve relative / absolute filenames,
|
||||
// therefore path is only used for testing
|
||||
// The file extension is in every case ".tex".
|
||||
@ -2548,9 +2621,11 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
|
||||
if (!Gnumeric_name.empty())
|
||||
name = Gnumeric_name;
|
||||
}
|
||||
if (makeAbsPath(name, path).exists())
|
||||
fix_relative_filename(name);
|
||||
else
|
||||
FileName const absname = makeAbsPath(name, path);
|
||||
if (absname.exists()) {
|
||||
fix_child_filename(name);
|
||||
copy_file(absname, name);
|
||||
} else
|
||||
cerr << "Warning: Could not find file '"
|
||||
<< name << "'." << endl;
|
||||
context.check_layout(os);
|
||||
@ -2560,7 +2635,7 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
|
||||
end_inset(os);
|
||||
context.check_layout(os);
|
||||
macro = false;
|
||||
// register the packages that are automatically reloaded
|
||||
// register the packages that are automatically loaded
|
||||
// by the Gnumeric template
|
||||
registerExternalTemplatePackages("GnumericSpreadsheet");
|
||||
}
|
||||
@ -2760,7 +2835,7 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
|
||||
opts["clip"] = string();
|
||||
string name = normalize_filename(p.verbatim_item());
|
||||
|
||||
string const path = makeAbsPath(getMasterFilePath()).absFileName();
|
||||
string const path = getMasterFilePath(true);
|
||||
// We want to preserve relative / absolute filenames,
|
||||
// therefore path is only used for testing
|
||||
if (!makeAbsPath(name, path).exists()) {
|
||||
@ -2795,9 +2870,11 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
|
||||
}
|
||||
}
|
||||
|
||||
if (makeAbsPath(name, path).exists())
|
||||
fix_relative_filename(name);
|
||||
else
|
||||
FileName const absname = makeAbsPath(name, path);
|
||||
if (absname.exists()) {
|
||||
fix_child_filename(name);
|
||||
copy_file(absname, name);
|
||||
} else
|
||||
cerr << "Warning: Could not find graphics file '"
|
||||
<< name << "'." << endl;
|
||||
|
||||
@ -3725,7 +3802,7 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
|
||||
name += p.get_token().asInput();
|
||||
context.check_layout(os);
|
||||
string filename(normalize_filename(p.getArg('{', '}')));
|
||||
string const path = makeAbsPath(getMasterFilePath()).absFileName();
|
||||
string const path = getMasterFilePath(true);
|
||||
// We want to preserve relative / absolute filenames,
|
||||
// therefore path is only used for testing
|
||||
if ((t.cs() == "include" || t.cs() == "input") &&
|
||||
@ -3743,13 +3820,13 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
|
||||
if (makeAbsPath(filename, path).exists()) {
|
||||
string const abstexname =
|
||||
makeAbsPath(filename, path).absFileName();
|
||||
string const abslyxname =
|
||||
changeExtension(abstexname, ".lyx");
|
||||
string const absfigname =
|
||||
changeExtension(abstexname, ".fig");
|
||||
fix_relative_filename(filename);
|
||||
fix_child_filename(filename);
|
||||
string const lyxname =
|
||||
changeExtension(filename, ".lyx");
|
||||
string const abslyxname = makeAbsPath(
|
||||
lyxname, getParentFilePath(false)).absFileName();
|
||||
bool xfig = false;
|
||||
external = FileName(absfigname).exists();
|
||||
if (t.cs() == "input") {
|
||||
@ -3795,16 +3872,24 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
|
||||
}
|
||||
if (external) {
|
||||
outname = changeExtension(filename, ".fig");
|
||||
FileName abssrc(changeExtension(abstexname, ".fig"));
|
||||
copy_file(abssrc, outname);
|
||||
} else if (xfig) {
|
||||
// Don't try to convert, the result
|
||||
// would be full of ERT.
|
||||
outname = filename;
|
||||
FileName abssrc(abstexname);
|
||||
copy_file(abssrc, outname);
|
||||
} else if (t.cs() != "verbatiminput" &&
|
||||
tex2lyx(abstexname, FileName(abslyxname),
|
||||
p.getEncoding())) {
|
||||
outname = lyxname;
|
||||
// no need to call copy_file
|
||||
// tex2lyx creates the file
|
||||
} else {
|
||||
outname = filename;
|
||||
FileName abssrc(abstexname);
|
||||
copy_file(abssrc, outname);
|
||||
}
|
||||
} else {
|
||||
cerr << "Warning: Could not find included file '"
|
||||
@ -4185,7 +4270,7 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
|
||||
vector<string> keys;
|
||||
split_map(arg, opts, keys);
|
||||
string name = normalize_filename(p.verbatim_item());
|
||||
string const path = makeAbsPath(getMasterFilePath()).absFileName();
|
||||
string const path = getMasterFilePath(true);
|
||||
// We want to preserve relative / absolute filenames,
|
||||
// therefore path is only used for testing
|
||||
if (!makeAbsPath(name, path).exists()) {
|
||||
@ -4199,9 +4284,12 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
|
||||
pdflatex = true;
|
||||
}
|
||||
}
|
||||
if (makeAbsPath(name, path).exists())
|
||||
fix_relative_filename(name);
|
||||
else
|
||||
FileName const absname = makeAbsPath(name, path);
|
||||
if (absname.exists())
|
||||
{
|
||||
fix_child_filename(name);
|
||||
copy_file(absname, name);
|
||||
} else
|
||||
cerr << "Warning: Could not find file '"
|
||||
<< name << "'." << endl;
|
||||
// write output
|
||||
@ -4250,7 +4338,7 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
|
||||
else if (t.cs() == "loadgame") {
|
||||
p.skip_spaces();
|
||||
string name = normalize_filename(p.verbatim_item());
|
||||
string const path = makeAbsPath(getMasterFilePath()).absFileName();
|
||||
string const path = getMasterFilePath(true);
|
||||
// We want to preserve relative / absolute filenames,
|
||||
// therefore path is only used for testing
|
||||
if (!makeAbsPath(name, path).exists()) {
|
||||
@ -4262,9 +4350,12 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
|
||||
if (!lyxskak_name.empty())
|
||||
name = lyxskak_name;
|
||||
}
|
||||
if (makeAbsPath(name, path).exists())
|
||||
fix_relative_filename(name);
|
||||
else
|
||||
FileName const absname = makeAbsPath(name, path);
|
||||
if (absname.exists())
|
||||
{
|
||||
fix_child_filename(name);
|
||||
copy_file(absname, name);
|
||||
} else
|
||||
cerr << "Warning: Could not find file '"
|
||||
<< name << "'." << endl;
|
||||
context.check_layout(os);
|
||||
|
Loading…
Reference in New Issue
Block a user