Jean-Marc Lasgouttes schrieb:
Bernhard Roider <[EMAIL PROTECTED]> writes:
- it is wrong to define that in binding files, since these definitions
are available to menus and toolbars too. I propose to move the
definitions to their own file.
ok, then should we create another directory like "bind" or "ui"?
Either that, or just one file. I do not really know.
Do we want a default file that is always read? Do we want also a
user-defined file?
It could be two files
default.cmd
user.cmd
What do other think?
JMarc
The attached patch implements a CmdDef class and reading of *.cmd files similar to the *.bind files.
There is no user interface yet.
bernhard
Index: src/CmdDef.cpp
===================================================================
--- src/CmdDef.cpp (revision 0)
+++ src/CmdDef.cpp (revision 0)
@@ -0,0 +1,202 @@
+/**
+ * \file CmdDef.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Bernhard Roider
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "CmdDef.h"
+
+#include "LyXAction.h"
+#include "debug.h"
+#include "Lexer.h"
+
+#include "support/filetools.h"
+#include "support/lstrings.h"
+
+using std::endl;
+using std::string;
+
+namespace lyx {
+
+using support::FileName;
+using support::i18nLibFileSearch;
+using support::trim;
+
+
+namespace {
+
+enum CmdDefTags {
+ BN_DEFFILE,
+ BN_DEFINE
+};
+
+keyword_item cmdDefTags[] = {
+ { "\\def_file", BN_DEFFILE },
+ { "\\define", BN_DEFINE }
+};
+
+}
+
+
+bool CmdDef::read(string const & def_file)
+{
+ const int cmdDefCount = sizeof(cmdDefTags) / sizeof(keyword_item);
+
+ Lexer lexrc(cmdDefTags, cmdDefCount);
+ if (lyxerr.debugging(Debug::PARSER))
+ lexrc.printTable(lyxerr);
+
+ FileName const tmp(i18nLibFileSearch("commands", def_file, "def"));
+ lexrc.setFile(tmp);
+ if (!lexrc.isOK()) {
+ lyxerr << "CmdDef::read: cannot open def file:"
+ << tmp << endl;
+ return false;
+ }
+
+// LYXERR(Debug::KBMAP) << "Reading def file:" << tmp << endl;
+
+ bool error = false;
+ while (lexrc.isOK()) {
+ switch (lexrc.lex()) {
+ case Lexer::LEX_UNDEF:
+ lexrc.printError("Unknown tag `$$Token'");
+ error = true;
+ continue;
+ case Lexer::LEX_FEOF:
+ continue;
+ case BN_DEFINE:
+ {
+ string name, def;
+
+ if (lexrc.next()) {
+ name = lexrc.getString();
+ } else {
+ lexrc.printError("BN_DEFINE: Missing command
name");
+ error = true;
+ break;
+ }
+
+ if (lexrc.next(true)) {
+ def = lexrc.getString();
+ } else {
+ lexrc.printError("BN_DEFINE: missing command
definition");
+ error = true;
+ break;
+ }
+
+ newCmdDefResult e = newCmdDef(name, def);
+ switch (e) {
+ case CmdDefNameEmpty:
+ lexrc.printError("BN_DEFINE: Command
name is empty");
+ error = true;
+ break;
+ case CmdDefExists:
+ lexrc.printError("BN_DEFINE: Command `"
+ name + "' already defined");
+ error = true;
+ break;
+ case CmdDefInvalid:
+ lexrc.printError("BN_DEFINE: Command
definition for `" + name + "' is not valid");
+ error = true;
+ }
+
+ break;
+ }
+ case BN_DEFFILE:
+ if (lexrc.next()) {
+ string const tmp(lexrc.getString());
+ error |= !read(tmp);
+ } else {
+ lexrc.printError("BN_DEFFILE: Missing file
name");
+ error = true;
+ break;
+
+ }
+ break;
+ }
+ }
+
+ if (error)
+ lyxerr << "CmdDef::read: error while reading def file:"
+ << tmp << endl;
+ return !error;
+}
+
+
+bool CmdDef::lock(string const & name, FuncRequest & func)
+{
+ if (cmdDefMap.empty())
+ {
+ func = FuncRequest::unknown;
+ return false;
+ }
+
+ string const name2 = trim(name);
+
+ CmdDefMap::const_iterator pos = cmdDefMap.find(name2);
+
+ if (pos == cmdDefMap.end())
+ {
+ func = FuncRequest::unknown;
+ return false;
+ }
+
+ if (pos->second->locked)
+ {
+ func = FuncRequest::noaction;
+ return false;
+ }
+
+ pos->second->locked = true;
+ func = pos->second->func;
+ return true;
+}
+
+
+void CmdDef::release(string const & name)
+{
+ if (cmdDefMap.empty())
+ return;
+
+ string const name2 = trim(name);
+
+ CmdDefMap::const_iterator pos = cmdDefMap.find(name2);
+
+ if (pos == cmdDefMap.end())
+ return;
+
+ pos->second->locked = false;
+}
+
+CmdDef::newCmdDefResult CmdDef::newCmdDef(string const & name,
+
string const & def)
+{
+ string const name2 = trim(name);
+
+ if (name2.empty())
+ return CmdDefNameEmpty;
+
+ if (cmdDefMap.find(name) != cmdDefMap.end())
+ return CmdDefExists;
+
+ FuncRequest func = lyxaction.lookupFunc(def);
+ if (func.action == LFUN_NOACTION ||
+ func.action == LFUN_UNKNOWN_ACTION) {
+ return CmdDefInvalid;
+ }
+
+ boost::shared_ptr<CmdDefInfo> info;
+ info.reset(new CmdDefInfo(func));
+ cmdDefMap[name2] = info;
+
+ return CmdDefOk;
+}
+
+
+} // namespace lyx
Index: src/CmdDef.h
===================================================================
--- src/CmdDef.h (revision 0)
+++ src/CmdDef.h (revision 0)
@@ -0,0 +1,87 @@
+// -*- C++ -*-
+/**
+ * \file CmdDef.h
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Bernhard Roider
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#ifndef CMDDEF_H
+#define CMDDEF_H
+
+#include "FuncRequest.h"
+
+#include "support/docstream.h"
+
+#include <boost/shared_ptr.hpp>
+
+#include <vector>
+#include <deque>
+
+
+namespace lyx {
+
+/// Creates command definitions
+class CmdDef {
+private:
+ /// information for a definition
+ struct CmdDefInfo {
+ CmdDefInfo(FuncRequest const & f): func(f), locked(false) {}
+ /// the expanded FuncRequest
+ FuncRequest func;
+ /// to avoid recursive calls
+ bool locked;
+ };
+
+
+ /// type for map between a macro name and its info
+ typedef std::map<std::string, boost::shared_ptr<CmdDefInfo> > CmdDefMap;
+
+public:
+
+ /// Parse a def file
+ bool read(std::string const & def_file);
+
+ /**
+ * Look up a definition, lock it and return the
+ * associated action if it is not locked.
+ * @param name the name of the command
+ * @param func contains the action on success
+ * @return true if lock was successful
+ */
+ bool lock(std::string const & name, FuncRequest & func);
+
+ /// release a locked definition
+ void release(std::string const & name);
+
+private:
+
+ /// possible reasons for not allowed definitions
+ enum newCmdDefResult {
+ CmdDefOk,
+ CmdDefNameEmpty,
+ CmdDefInvalid,
+ CmdDefExists
+ };
+
+ /**
+ * Add a new command definition.
+ * @param name internal recursion level
+ */
+ newCmdDefResult newCmdDef(std::string const & name,
+ std::string const & def);
+
+ ///
+ CmdDefMap cmdDefMap;
+};
+
+/// Implementation is in LyX.cpp
+extern CmdDef & theTopLevelCmdDef();
+
+
+} // namespace lyx
+
+#endif // CMDDEF_H
Index: src/frontends/qt4/GuiToolbar.cpp
===================================================================
--- src/frontends/qt4/GuiToolbar.cpp (revision 20969)
+++ src/frontends/qt4/GuiToolbar.cpp (working copy)
@@ -444,6 +444,9 @@
case LFUN_MATH_BIGDELIM:
fullname = find_png(to_utf8(f.argument()));
break;
+ case LFUN_CALL:
+ fullname = libFileSearch("images", to_utf8(f.argument()),
"png").absFilename();
+ break;
default:
string const name = lyxaction.getActionName(f.action);
string png_name = name;
Index: src/FuncRequest.cpp
===================================================================
--- src/FuncRequest.cpp (revision 20969)
+++ src/FuncRequest.cpp (working copy)
@@ -24,6 +24,8 @@
namespace lyx {
+FuncRequest const FuncRequest::unknown(LFUN_UNKNOWN_ACTION);
+FuncRequest const FuncRequest::noaction(LFUN_NOACTION);
FuncRequest::FuncRequest(Origin o)
: action(LFUN_NOACTION), origin(o), x(0), y(0),
Index: src/FuncRequest.h
===================================================================
--- src/FuncRequest.h (revision 20969)
+++ src/FuncRequest.h (working copy)
@@ -67,6 +67,10 @@
/// access the whole argument
docstring const & argument() const { return argument_; }
+ ///
+ static FuncRequest const unknown;
+ ///
+ static FuncRequest const noaction;
public: // should be private
/// the action
kb_action action;
Index: src/lfuns.h
===================================================================
--- src/lfuns.h (revision 20969)
+++ src/lfuns.h (working copy)
@@ -404,6 +404,8 @@
LFUN_MASTER_BUFFER_VIEW, // Tommaso, 20070920
LFUN_MASTER_BUFFER_UPDATE, // Tommaso, 20070920
LFUN_INFO_INSERT, // bpeng, 20071007
+ // 295
+ LFUN_CALL, // broider, 20071002
LFUN_LASTACTION // end of the table
};
Index: src/LyX.cpp
===================================================================
--- src/LyX.cpp (revision 20969)
+++ src/LyX.cpp (working copy)
@@ -29,6 +29,7 @@
#include "Format.h"
#include "gettext.h"
#include "KeyMap.h"
+#include "CmdDef.h"
#include "Language.h"
#include "Session.h"
#include "Color.h"
@@ -169,6 +170,8 @@
///
boost::scoped_ptr<KeyMap> toplevel_keymap_;
///
+ boost::scoped_ptr<CmdDef> toplevel_cmddef_;
+ ///
boost::scoped_ptr<Server> lyx_server_;
///
boost::scoped_ptr<ServerSocket> lyx_socket_;
@@ -320,6 +323,13 @@
}
+CmdDef & LyX::topLevelCmdDef()
+{
+ BOOST_ASSERT(pimpl_->toplevel_cmddef_.get());
+ return *pimpl_->toplevel_cmddef_.get();
+}
+
+
Converters & LyX::converters()
{
return pimpl_->converters_;
@@ -966,6 +976,10 @@
// Set the language defined by the user.
//setGuiLanguage(lyxrc.gui_language);
+ // Set up command definitions
+ pimpl_->toplevel_cmddef_.reset(new CmdDef);
+ pimpl_->toplevel_cmddef_->read(lyxrc.def_file);
+
// Set up bindings
pimpl_->toplevel_keymap_.reset(new KeyMap);
defaultKeyBindings(pimpl_->toplevel_keymap_.get());
Index: src/LyX.h
===================================================================
--- src/LyX.h (revision 20969)
+++ src/LyX.h (working copy)
@@ -38,6 +38,7 @@
class Movers;
class Session;
class KeyMap;
+class CmdDef;
extern bool use_gui;
@@ -87,6 +88,9 @@
KeyMap const & topLevelKeymap() const;
///
+ CmdDef & topLevelCmdDef();
+
+ ///
Converters & converters();
Converters & systemConverters();
Index: src/LyXAction.cpp
===================================================================
--- src/LyXAction.cpp (revision 20969)
+++ src/LyXAction.cpp (working copy)
@@ -144,6 +144,7 @@
{ LFUN_COMMAND_EXECUTE, "command-execute", NoBuffer },
{ LFUN_COMMAND_PREFIX, "command-prefix", NoBuffer },
{ LFUN_COMMAND_SEQUENCE, "command-sequence", NoBuffer },
+ { LFUN_CALL, "call", NoBuffer | ReadOnly},
{ LFUN_COPY, "copy", ReadOnly },
{ LFUN_CUT, "cut", Noop },
{ LFUN_DATE_INSERT, "date-insert", Noop },
Index: src/LyXFunc.cpp
===================================================================
--- src/LyXFunc.cpp (revision 20969)
+++ src/LyXFunc.cpp (working copy)
@@ -28,6 +28,7 @@
#include "BufferList.h"
#include "BufferParams.h"
#include "BufferView.h"
+#include "CmdDef.h"
#include "Color.h"
#include "Cursor.h"
#include "CutAndPaste.h"
@@ -669,8 +670,25 @@
FuncRequest func(lyxaction.lookupFunc(firstcmd));
func.origin = cmd.origin;
flag = getStatus(func);
+ break;
}
+ case LFUN_CALL: {
+ FuncRequest func;
+ std::string name(to_utf8(cmd.argument()));
+ if (LyX::ref().topLevelCmdDef().lock(name, func)) {
+ func.origin = cmd.origin;
+ flag = getStatus(func);
+ LyX::ref().topLevelCmdDef().release(name);
+ } else {
+ // catch recursion or unknown command definiton
+ // all operations until the recursion or unknown
command
+ // definiton occures are performed, so set the state to
enabled
+ enable = true;
+ }
+ break;
+ }
+
case LFUN_BUFFER_NEW:
case LFUN_BUFFER_NEW_TEMPLATE:
case LFUN_WORD_FIND_FORWARD:
@@ -1605,6 +1623,28 @@
break;
}
+ case LFUN_CALL: {
+ FuncRequest func;
+ if (LyX::ref().topLevelCmdDef().lock(argument, func)) {
+ func.origin = cmd.origin;
+ dispatch(func);
+ LyX::ref().topLevelCmdDef().release(argument);
+ } else {
+ if (func.action == LFUN_UNKNOWN_ACTION) {
+ // unknown command definition
+ lyxerr << "Warning: unknown command
definition `"
+ << argument << "'"
+ << endl;
+ } else {
+ // recursion detected
+ lyxerr << "Warning: Recursion in the
command definition `"
+ << argument << "' detected"
+ << endl;
+ }
+ }
+ break;
+ }
+
case LFUN_PREFERENCES_SAVE: {
lyxrc.write(makeAbsPath("preferences",
package().user_support().absFilename()),
Index: src/LyXRC.cpp
===================================================================
--- src/LyXRC.cpp (revision 20969)
+++ src/LyXRC.cpp (working copy)
@@ -84,6 +84,7 @@
{ "\\custom_export_command", LyXRC::RC_CUSTOM_EXPORT_COMMAND },
{ "\\custom_export_format", LyXRC::RC_CUSTOM_EXPORT_FORMAT },
{ "\\date_insert_format", LyXRC::RC_DATE_INSERT_FORMAT },
+ { "\\def_file", LyXRC::RC_DEFFILE },
{ "\\default_language", LyXRC::RC_DEFAULT_LANGUAGE },
{ "\\default_papersize", LyXRC::RC_DEFAULT_PAPERSIZE },
{ "\\dialogs_iconify_with_main", LyXRC::RC_DIALOGS_ICONIFY_WITH_MAIN },
@@ -189,6 +190,7 @@
void LyXRC::setDefaults() {
bind_file = "cua";
+ def_file = "default";
ui_file = "default";
// Get printer from the environment. If fail, use default "",
// assuming that everything is set up correctly.
@@ -370,6 +372,12 @@
}
break;
+ case RC_DEFFILE:
+ if (lexrc.next()) {
+ def_file = os::internal_path(lexrc.getString());
+ }
+ break;
+
case RC_UIFILE:
if (lexrc.next()) {
ui_file = os::internal_path(lexrc.getString());
@@ -1226,7 +1234,7 @@
<< "### LyX, The Document Processor\n"
<< "###\n"
<< "### Copyright 1995 Matthias Ettrich\n"
- << "### Copyright 1995-2001 The LyX Team.\n"
+ << "### Copyright 1995-2007 The LyX Team.\n"
<< "###\n"
<< "###
========================================================\n"
<< "\n"
@@ -1252,6 +1260,15 @@
if (tag != RC_LAST)
break;
+ case RC_DEFFILE:
+ if (ignore_system_lyxrc ||
+ def_file != system_lyxrc.def_file) {
+ string const path = os::external_path(def_file);
+ os << "\\def_file \"" << path << "\"\n";
+ }
+ if (tag != RC_LAST)
+ break;
+
//
// Misc Section
//
Index: src/LyXRC.h
===================================================================
--- src/LyXRC.h (revision 20969)
+++ src/LyXRC.h (working copy)
@@ -58,6 +58,7 @@
RC_CUSTOM_EXPORT_COMMAND,
RC_CUSTOM_EXPORT_FORMAT,
RC_DATE_INSERT_FORMAT,
+ RC_DEFFILE,
RC_DEFAULT_LANGUAGE,
RC_DEFAULT_PAPERSIZE,
RC_DIALOGS_ICONIFY_WITH_MAIN,
@@ -171,6 +172,8 @@
///
std::string bind_file;
///
+ std::string def_file;
+ ///
std::string ui_file;
///
std::string printer;
Index: src/Makefile.am
===================================================================
--- src/Makefile.am (revision 20969)
+++ src/Makefile.am (working copy)
@@ -100,6 +100,8 @@
Changes.h \
Chktex.cpp \
Chktex.h \
+ CmdDef.cpp \
+ CmdDef.h \
Color.cpp \
Color.h \
config.h.in \
Index: lib/commands/default.def
===================================================================
--- lib/commands/default.def (revision 0)
+++ lib/commands/default.def (revision 0)
@@ -0,0 +1,20 @@
+# -*- text -*-
+
+# file default.def
+# This file is part of LyX, the document processor.
+# Licence details can be found in the file COPYING.
+
+# author Bernhard Roider
+
+# Full author contact details are available in file CREDITS.
+
+# This is the default command definition file.
+
+# DO NOT CHANGE THIS DEFAULT COMMAND DEFINITION FILE! It will be replaced
+# with every new install of LyX and your changes will be lost.
+# Instead, customize a copy of this file placed in
+# ~/.lyx/commands/default.bind
+#
+# Happy tuning!
+
+\define "InlineErtInsert" "command-sequence inset-insert ert 1; char-backward"