This is an old one held over from pre-1.6. I've updated it and plan to commit now. Any comments?

JMarc and Abdel, the new version takes account of some comments of yours from way back.

rh

Index: src/Buffer.h
===================================================================
--- src/Buffer.h	(revision 29093)
+++ src/Buffer.h	(working copy)
@@ -12,6 +12,8 @@
 #ifndef BUFFER_H
 #define BUFFER_H
 
+#include "update_flags.h"
+
 #include "insets/InsetCode.h"
 
 #include "support/strfwd.h"
@@ -27,11 +29,13 @@
 class BiblioInfo;
 class BufferParams;
 class BufferSet;
+class DispatchResult;
 class DocIterator;
 class docstring_list;
 class ErrorItem;
 class ErrorList;
 class FuncRequest;
+class FuncStatus;
 class Inset;
 class InsetRef;
 class InsetLabel;
@@ -125,13 +129,17 @@
 	~Buffer();
 
 	/** High-level interface to buffer functionality.
-	    This function parses a command string and executes it
+	    This function parses a command string and executes it.
 	*/
-	bool dispatch(std::string const & command, bool * result = 0);
+	void dispatch(std::string const & command, DispatchResult & result);
 
 	/// Maybe we know the function already by number...
-	bool dispatch(FuncRequest const & func, bool * result = 0);
+	void dispatch(FuncRequest const & func, DispatchResult & result);
 
+	/// Can this function be exectued?
+	/// \return true if we made a decision
+	bool getStatus(FuncRequest const & cmd, FuncStatus & flag);
+
 	/// read a new document from a string
 	bool readString(std::string const &);
 	/// load a new file
Index: src/Buffer.cpp
===================================================================
--- src/Buffer.cpp	(revision 29093)
+++ src/Buffer.cpp	(working copy)
@@ -24,12 +24,14 @@
 #include "Chktex.h"
 #include "Converter.h"
 #include "Counters.h"
+#include "DispatchResult.h"
 #include "DocIterator.h"
 #include "Encoding.h"
 #include "ErrorList.h"
 #include "Exporter.h"
 #include "Format.h"
 #include "FuncRequest.h"
+#include "FuncStatus.h"
 #include "InsetIterator.h"
 #include "InsetList.h"
 #include "Language.h"
@@ -94,6 +96,7 @@
 #include "support/os.h"
 #include "support/Package.h"
 #include "support/Path.h"
+#include "support/Systemcall.h"
 #include "support/textutils.h"
 #include "support/types.h"
 
@@ -126,6 +129,14 @@
 typedef map<string, bool> DepClean;
 typedef map<docstring, pair<InsetLabel const *, Buffer::References> > RefCache;
 
+void showPrintError(string const & name)
+{
+	docstring str = bformat(_("Could not print the document %1$s.\n"
+					    "Check that your printer is set up correctly."),
+			     makeDisplayPath(name, 50));
+	Alert::error(_("Print document failed"), str);
+}
+
 } // namespace anon
 
 class BufferSet : public std::set<Buffer const *> {};
@@ -1502,21 +1513,61 @@
 }
 
 
-bool Buffer::dispatch(string const & command, bool * result)
+bool Buffer::getStatus(FuncRequest const & cmd, FuncStatus & flag)
 {
+	switch (cmd.action) {
+		case LFUN_BUFFER_EXPORT: {
+			docstring const arg = cmd.argument();
+			bool enable = arg == "custom" || isExportable(to_utf8(arg));
+			if (!enable)
+				flag.message(bformat(
+					_("Don't know how to export to format: %1$s"), arg));
+			flag.setEnabled(enable);
+			break;
+		}
+
+		case LFUN_BRANCH_ACTIVATE: 
+		case LFUN_BRANCH_DEACTIVATE: {
+		BranchList const & branchList = params().branchlist();
+		docstring const branchName = cmd.argument();
+		flag.setEnabled(!branchName.empty()
+				&& branchList.find(branchName));
+			break;
+		}
+
+		case LFUN_BUFFER_PRINT:
+			// if no Buffer is present, then of course we won't be called!
+			flag.setEnabled(true);
+			break;
+
+		default:
+			return false;
+	}
+	return true;
+}
+
+
+void Buffer::dispatch(string const & command, DispatchResult & result)
+{
 	return dispatch(lyxaction.lookupFunc(command), result);
 }
 
 
-bool Buffer::dispatch(FuncRequest const & func, bool * result)
+// NOTE We can end up here even if we have no GUI, because we are called
+// by LyX::exec to handled command-line requests. So we may need to check 
+// whether we have a GUI or not. The boolean use_gui holds this information.
+void Buffer::dispatch(FuncRequest const & func, DispatchResult & dr)
 {
+	// We'll set this back to false if need be.
 	bool dispatched = true;
 
 	switch (func.action) {
 		case LFUN_BUFFER_EXPORT: {
-			bool const tmp = doExport(to_utf8(func.argument()), false);
-			if (result)
-				*result = tmp;
+			bool success = doExport(to_utf8(func.argument()), false);
+			dr.setError(success);
+			if (!success)
+				dr.setMessage(bformat(_("Error exporting to format: %1$s."), 
+				                      func.argument()));
 			break;
 		}
 
@@ -1530,18 +1581,138 @@
 				break;
 			}
 			Branch * branch = branchList.find(branchName);
-			if (!branch)
+			if (!branch) {
 				LYXERR0("Branch " << branchName << " does not exist.");
-			else
+				dr.setError(true);
+				docstring const msg = 
+					bformat(_("Branch \%1$s\" does not exist."), branchName);
+				dr.setMessage(msg);
+			} else {
 				branch->setSelected(func.action == LFUN_BRANCH_ACTIVATE);
-			if (result)
-				*result = true;
+				dr.setError(false);
+				dr.update(Update::Force);
+			}
+			break;
 		}
 
+		case LFUN_BUFFER_PRINT: {
+			dr.setError(true); // we'll assume there's a problem until we succeed
+			string target = func.getArg(0);
+			string target_name = func.getArg(1);
+			string command = func.getArg(2);
+
+			if (target.empty()
+			    || target_name.empty()
+			    || command.empty()) {
+				LYXERR0("Unable to parse " << func.argument());
+				docstring const msg = 
+					bformat(_("Unable to parse \"%1$s\""), func.argument());
+				dr.setMessage(msg);
+				break;
+			}
+			if (target != "printer" && target != "file") {
+				LYXERR0("Unrecognized target \"" << target << '"');
+				docstring const msg = 
+					bformat(_("Unrecognized target \"%1$s\""), from_utf8(target));
+				dr.setMessage(msg);
+				break;
+			}
+
+			if (!doExport("dvi", true)) {
+				showPrintError(absFileName());
+				dr.setMessage(_("Error exporting to DVI."));
+				break;
+			}
+
+			// Push directory path.
+			string const path = temppath();
+			// Prevent the compiler from optimizing away p
+			FileName pp(path);
+			PathChanger p(pp);
+
+			// there are three cases here:
+			// 1. we print to a file
+			// 2. we print directly to a printer
+			// 3. we print using a spool command (print to file first)
+			Systemcall one;
+			int res = 0;
+			string const dviname = changeExtension(latexName(true), "dvi");
+
+			if (target == "printer") {
+				if (!lyxrc.print_spool_command.empty()) {
+					// case 3: print using a spool
+					string const psname = changeExtension(dviname,".ps");
+					command += ' ' + lyxrc.print_to_file
+						+ quoteName(psname)
+						+ ' '
+						+ quoteName(dviname);
+
+					string command2 = lyxrc.print_spool_command + ' ';
+					if (target_name != "default") {
+						command2 += lyxrc.print_spool_printerprefix
+							+ target_name
+							+ ' ';
+					}
+					command2 += quoteName(psname);
+					// First run dvips.
+					// If successful, then spool command
+					res = one.startscript(Systemcall::Wait, command);
+
+					if (res == 0) {
+						// If there's no GUI, we have to wait on this command. Otherwise,
+						// LyX deletes the temporary directory, and with it the spooled
+						// file, before it can be printed!!
+						Systemcall::Starttype stype = use_gui ?
+							Systemcall::DontWait : Systemcall::Wait;
+						res = one.startscript(stype, command2);
+					}
+				} else {
+					// case 2: print directly to a printer
+					if (target_name != "default")
+						command += ' ' + lyxrc.print_to_printer + target_name + ' ';
+					// as above....
+					Systemcall::Starttype stype = use_gui ?
+						Systemcall::DontWait : Systemcall::Wait;
+					res = one.startscript(stype, command + quoteName(dviname));
+				}
+
+			} else {
+				// case 1: print to a file
+				FileName const filename(makeAbsPath(target_name, filePath()));
+				FileName const dvifile(makeAbsPath(dviname, path));
+				if (filename.exists()) {
+					docstring text = bformat(
+						_("The file %1$s already exists.\n\n"
+						  "Do you want to overwrite that file?"),
+						makeDisplayPath(filename.absFilename()));
+					if (Alert::prompt(_("Overwrite file?"),
+					    text, 0, 1, _("&Overwrite"), _("&Cancel")) != 0)
+						break;
+				}
+				command += ' ' + lyxrc.print_to_file
+					+ quoteName(filename.toFilesystemEncoding())
+					+ ' '
+					+ quoteName(dvifile.toFilesystemEncoding());
+				// as above....
+				Systemcall::Starttype stype = use_gui ?
+					Systemcall::DontWait : Systemcall::Wait;
+				res = one.startscript(stype, command);
+			}
+
+			if (res == 0) 
+				dr.setError(false);
+			else {
+				dr.setMessage(_("Error running external commands."));
+				showPrintError(absFileName());
+			}
+			break;
+		}
+
 		default:
 			dispatched = false;
+			break;
 	}
-	return dispatched;
+	dr.dispatched(dispatched);
 }
 
 
Index: src/BufferView.h
===================================================================
--- src/BufferView.h	(revision 29093)
+++ src/BufferView.h	(working copy)
@@ -195,8 +195,8 @@
 	/// translate and insert a character, using the correct keymap.
 	void translateAndInsert(char_type c, Text * t, Cursor & cur);
 
-	/// return true for events that will handle.
-	FuncStatus getStatus(FuncRequest const & cmd);
+	/// \return true if we've made a decision
+	bool getStatus(FuncRequest const & cmd, FuncStatus & flag);
 	/// execute the given function.
 	/// \return true if the function has been processed.
 	bool dispatch(FuncRequest const & argument);
Index: src/BufferView.cpp
===================================================================
--- src/BufferView.cpp	(revision 29093)
+++ src/BufferView.cpp	(working copy)
@@ -895,10 +895,8 @@
 }
 
 
-FuncStatus BufferView::getStatus(FuncRequest const & cmd)
+bool BufferView::getStatus(FuncRequest const & cmd, FuncStatus & flag)
 {
-	FuncStatus flag;
-
 	Cursor & cur = d->cursor_;
 
 	switch (cmd.action) {
@@ -916,6 +914,7 @@
 		// FIXME: Actually, these LFUNS should be moved to Text
 		flag.setEnabled(cur.inTexted());
 		break;
+
 	case LFUN_FONT_STATE:
 	case LFUN_LABEL_INSERT:
 	case LFUN_INFO_INSERT:
@@ -1048,29 +1047,18 @@
 	}
 
 	case LFUN_DIALOG_SHOW_NEW_INSET:
+		if (cur.inset().lyxCode() == CAPTION_CODE)
+			return cur.inset().getStatus(cur, cmd, flag);
 		flag.setEnabled(cur.inset().lyxCode() != ERT_CODE &&
 			cur.inset().lyxCode() != LISTINGS_CODE);
-		if (cur.inset().lyxCode() == CAPTION_CODE) {
-			FuncStatus flag;
-			if (cur.inset().getStatus(cur, cmd, flag))
-				return flag;
-		}
 		break;
 
-	case LFUN_BRANCH_ACTIVATE: 
-	case LFUN_BRANCH_DEACTIVATE: {
-		BranchList const & branchList = buffer_.params().branchlist();
-		docstring const branchName = cmd.argument();
-		flag.setEnabled(!branchName.empty()
-				&& branchList.find(branchName));
-		break;
-	}
-
 	default:
 		flag.setEnabled(false);
+		return false;
 	}
 
-	return flag;
+	return true;
 }
 
 
@@ -1499,14 +1487,6 @@
 		break;
 	}
 
-	case LFUN_BRANCH_ACTIVATE:
-	case LFUN_BRANCH_DEACTIVATE:
-		if (cmd.argument().empty())
-			return false;
-		buffer_.dispatch(cmd);
-		processUpdateFlags(Update::Force);
-		break;
-
 	// This could be rewriten using some command like forall <insetname> <command>
 	// once the insets refactoring is done.
 	case LFUN_NOTES_MUTATE: {
Index: src/DispatchResult.h
===================================================================
--- src/DispatchResult.h	(revision 29093)
+++ src/DispatchResult.h	(working copy)
@@ -15,6 +15,8 @@
 
 #include "update_flags.h"
 
+#include "support/docstring.h"
+
 namespace lyx {
 
 /// Maybe this can go entirely
@@ -24,19 +26,31 @@
 	DispatchResult() : dispatched_(false), update_(Update::None) {}
 	///
 	DispatchResult(bool disp, Update::flags f) : dispatched_(disp), update_(f) {}
-	//
+	///
 	bool dispatched() const { return dispatched_; }
 	///
 	void dispatched(bool disp) { dispatched_ = disp; }
 	///
+	bool error() const { return error_; }
+	///
+	void setError(bool e) { error_ = e; }
+	///
+	docstring message() { return message_; }
+	///
+	void setMessage(docstring m) { message_ = m; }
+	///
 	Update::flags update() const { return update_; }
 	///
 	void update(Update::flags f) { update_ = f; }
 private:
 	/// was the event fully dispatched?
 	bool dispatched_;
+	/// was there an error?
+	bool error_;
 	/// do we need to redraw the screen afterwards?
 	Update::flags update_;
+	///
+	docstring message_;
 };
 
 
Index: src/LyXFunc.cpp
===================================================================
--- src/LyXFunc.cpp	(revision 29093)
+++ src/LyXFunc.cpp	(working copy)
@@ -457,11 +457,6 @@
 			flag.setOnOff(true);
 		break;
 
-	case LFUN_BUFFER_EXPORT:
-		enable = cmd.argument() == "custom"
-			|| buf->isExportable(to_utf8(cmd.argument()));
-		break;
-
 	case LFUN_BUFFER_CHKTEX:
 		enable = buf->isLatex() && !lyxrc.chktex_command.empty();
 		break;
@@ -619,7 +614,6 @@
 	case LFUN_KEYMAP_TOGGLE:
 	case LFUN_REPEAT:
 	case LFUN_BUFFER_EXPORT_CUSTOM:
-	case LFUN_BUFFER_PRINT:
 	case LFUN_PREFERENCES_SAVE:
 	case LFUN_MESSAGE:
 	case LFUN_INSET_EDIT:
@@ -653,8 +647,7 @@
 		if (lyx_view_->getStatus(cmd, flag))
 			break;
 
-		// If we have a BufferView, try cursor position and
-		// then the BufferView.
+		// If we do not have a BufferView, then other functions are disabled
 		if (!view()) {
 			enable = false;
 			break;
@@ -666,8 +659,13 @@
 		    && inset && inset->getStatus(view()->cursor(), cmd, flag))
 			break;
 
-		if (!getLocalStatus(view()->cursor(), cmd, flag))
-			flag = view()->getStatus(cmd);
+		bool decided = getLocalStatus(view()->cursor(), cmd, flag);
+		if (!decided)
+			// try the BufferView
+			decided = view()->getStatus(cmd, flag);
+		if (!decided)
+			// bry the Buffer
+			view()->buffer().getStatus(cmd, flag);
 	}
 
 	if (!enable)
@@ -730,15 +728,6 @@
 
 namespace {
 
-void showPrintError(string const & name)
-{
-	docstring str = bformat(_("Could not print the document %1$s.\n"
-					    "Check that your printer is set up correctly."),
-			     makeDisplayPath(name, 50));
-	Alert::error(_("Print document failed"), str);
-}
-
-
 bool loadLayoutFile(string const & name, string const & buf_path)
 {
 	if (!LayoutFileList::get().haveClass(name)) {
@@ -943,111 +932,6 @@
 			break;
 		}
 
-		case LFUN_BUFFER_PRINT: {
-			LASSERT(lyx_view_ && buffer, /**/);
-			// FIXME: cmd.getArg() might fail if one of the arguments
-			// contains double quotes
-			string target = cmd.getArg(0);
-			string target_name = cmd.getArg(1);
-			string command = cmd.getArg(2);
-
-			if (target.empty()
-			    || target_name.empty()
-			    || command.empty()) {
-				lyxerr << "Unable to parse \""
-				       << argument << '"' << endl;
-				break;
-			}
-			if (target != "printer" && target != "file") {
-				lyxerr << "Unrecognized target \""
-				       << target << '"' << endl;
-				break;
-			}
-
-			if (!buffer->doExport("dvi", true)) {
-				showPrintError(buffer->absFileName());
-				break;
-			}
-
-			// Push directory path.
-			string const path = buffer->temppath();
-			// Prevent the compiler from optimizing away p
-			FileName pp(path);
-			PathChanger p(pp);
-
-			// there are three cases here:
-			// 1. we print to a file
-			// 2. we print directly to a printer
-			// 3. we print using a spool command (print to file first)
-			Systemcall one;
-			int res = 0;
-			string const dviname =
-				changeExtension(buffer->latexName(true), "dvi");
-
-			if (target == "printer") {
-				if (!lyxrc.print_spool_command.empty()) {
-					// case 3: print using a spool
-					string const psname =
-						changeExtension(dviname,".ps");
-					command += ' ' + lyxrc.print_to_file
-						+ quoteName(psname)
-						+ ' '
-						+ quoteName(dviname);
-
-					string command2 =
-						lyxrc.print_spool_command + ' ';
-					if (target_name != "default") {
-						command2 += lyxrc.print_spool_printerprefix
-							+ target_name
-							+ ' ';
-					}
-					command2 += quoteName(psname);
-					// First run dvips.
-					// If successful, then spool command
-					res = one.startscript(
-						Systemcall::Wait,
-						command);
-
-					if (res == 0)
-						res = one.startscript(
-							Systemcall::DontWait,
-							command2);
-				} else {
-					// case 2: print directly to a printer
-					if (target_name != "default")
-						command += ' ' + lyxrc.print_to_printer + target_name + ' ';
-					res = one.startscript(
-						Systemcall::DontWait,
-						command + quoteName(dviname));
-				}
-
-			} else {
-				// case 1: print to a file
-				FileName const filename(makeAbsPath(target_name,
-							buffer->filePath()));
-				FileName const dvifile(makeAbsPath(dviname, path));
-				if (filename.exists()) {
-					docstring text = bformat(
-						_("The file %1$s already exists.\n\n"
-						  "Do you want to overwrite that file?"),
-						makeDisplayPath(filename.absFilename()));
-					if (Alert::prompt(_("Overwrite file?"),
-					    text, 0, 1, _("&Overwrite"), _("&Cancel")) != 0)
-						break;
-				}
-				command += ' ' + lyxrc.print_to_file
-					+ quoteName(filename.toFilesystemEncoding())
-					+ ' '
-					+ quoteName(dvifile.toFilesystemEncoding());
-				res = one.startscript(Systemcall::DontWait,
-						      command);
-			}
-
-			if (res != 0)
-				showPrintError(buffer->absFileName());
-			break;
-		}
-
 		// FIXME: There is need for a command-line import.
 		/*
 		case LFUN_BUFFER_IMPORT:
@@ -1712,6 +1596,14 @@
 				break;
 			}
 
+			// OK, so try the Buffer itself
+			DispatchResult dr;
+			view()->buffer().dispatch(cmd, dr);
+			if (dr.dispatched()) {
+				updateFlags = dr.update();
+				break;
+			}
+
 			// Is this a function that acts on inset at point?
 			Inset * inset = view()->cursor().nextInset();
 			if (lyxaction.funcHasFlag(action, LyXAction::AtPoint)
Index: src/LyX.cpp
===================================================================
--- src/LyX.cpp	(revision 29093)
+++ src/LyX.cpp	(working copy)
@@ -311,13 +311,13 @@
 			Buffer * buf = *I;
 			if (buf != buf->masterBuffer())
 				continue;
-			bool success = false;
 			vector<string>::const_iterator bcit  = pimpl_->batch_commands.begin();
 			vector<string>::const_iterator bcend = pimpl_->batch_commands.end();
+			DispatchResult dr;
 			for (; bcit != bcend; bcit++) {
 				LYXERR(Debug::ACTION, "Buffer::dispatch: cmd: " << *bcit);
-				buf->dispatch(*bcit, &success);
-				final_success |= success;
+				buf->dispatch(*bcit, dr);
+				final_success |= !dr.error();
 			}
 		}
 		prepareExit();
@@ -985,6 +985,7 @@
 		  "\t-i [--import] fmt file.xxx\n"
 		  "                  where fmt is the import format of choice\n"
 		  "                  and file.xxx is the file to be imported.\n"
+		  "\t--batch         execute commands and exit\n"
 		  "\t-version        summarize version and build info\n"
 			       "Check the LyX man page for more details.")) << endl;
 	exit(0);
@@ -1079,6 +1080,13 @@
 }
 
 
+int parse_batch(string const &, string const &, string &) 
+{
+	use_gui = false;
+	return 0;
+}
+
+
 } // namespace anon
 
 
@@ -1100,6 +1108,7 @@
 	cmdmap["-i"] = parse_import;
 	cmdmap["--import"] = parse_import;
 	cmdmap["-geometry"] = parse_geometry;
+	cmdmap["--batch"] = parse_batch;
 
 	for (int i = 1; i < argc; ++i) {
 		map<string, cmd_helper>::const_iterator it
Index: RELEASE-NOTES
===================================================================
--- RELEASE-NOTES	(revision 25000)
+++ RELEASE-NOTES	(working copy)
@@ -177,6 +177,14 @@
 
 For the detailed description of LyX functions look into doxygen documentation.
 
+There have been some changes to the LyX command line. There is a new option 
+"--batch" that causes LyX to run the given commands without opening a GUI 
+window. Thus, something like:
+    lyx --batch -x "buffer-print printer default dvips" myfile.lyx
+will cause LyX to print myfile.lyx to the default printer, using dvips and 
+the default print settings (which, of course, have to have been configured 
+already). At present, not many commands can be used this way, but there will
+be more eventually.
 
 Known issues in version 1.6.0
 ------------------------------------

Reply via email to