Andre Poenitz schrieb:
On Fri, Oct 05, 2007 at 12:24:45AM +0200, Bernhard Roider wrote:
hello all,

the attached patch adds
- the possibility to define macros in the bind file, like

\define "my macro" "command-sequence inset-insert ert 1; char-backward; self-insert some important latex code; char-forward"

- the lfun "call" to execute that macro. this call can be used in key bindings (\bind "X-y" "call my macro") menus and toolbar definitions (Item "My complex ert" "call my macro") as well as in the command buffer ("call my macro").

the benefits from that:
+ customization is easier because the definition is done in one place and can be used as descriebed above + it is possible to add complex commands (like the one above) to the toolbar with an image on the button, because the image name used equals the macro name ("my macro.png" in the above example)

oppinions?

Patch is too short.


so here it is, now tested as i managed to compile again (after hours of investigation and no idea what the real problem was).

if there are no objections i'll commit later this week

bernhard
Index: src/frontends/qt4/GuiToolbar.cpp
===================================================================
--- src/frontends/qt4/GuiToolbar.cpp    (revision 20854)
+++ 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/KeyMap.cpp
===================================================================
--- src/KeyMap.cpp      (revision 20854)
+++ src/KeyMap.cpp      (working copy)
@@ -77,12 +77,14 @@
 
 enum BindTags {
        BN_BIND,
-       BN_BINDFILE
+       BN_BINDFILE,
+       BN_DEFINE
 };
 
 keyword_item bindTags[] = {
        { "\\bind", BN_BIND },
-       { "\\bind_file", BN_BINDFILE }
+       { "\\bind_file", BN_BINDFILE },
+       { "\\define", BN_DEFINE }
 };
 
 }
@@ -115,6 +117,43 @@
                        continue;
                case Lexer::LEX_FEOF:
                        continue;
+               case BN_DEFINE:
+               {
+                       string name, def;
+
+                       if (lexrc.next()) {
+                               name = lexrc.getString();
+                       } else {
+                               lexrc.printError("BN_DEFINE: Missing macro 
name");
+                               error = true;
+                               break;
+                       }
+
+                       if (lexrc.next(true)) {
+                               def = lexrc.getString();
+                       } else {
+                               lexrc.printError("BN_DEFINE: missing macro 
definition");
+                               error = true;
+                               break;
+                       }
+
+                       LyXAction::new_macro_error e = lyxaction.newMacro(name, 
def);
+                       switch (e) {
+                               case LyXAction::MacroNameEmpty:
+                                       lexrc.printError("BN_DEFINE: Macro name 
is empty");
+                                       error = true;
+                                       break;
+                               case LyXAction::MacroExists:
+                                       lexrc.printError("BN_DEFINE: Macro 
already defined");
+                                       error = true;
+                                       break;
+                               case LyXAction::MacroDefInvalid:
+                                       lexrc.printError("BN_DEFINE: Macro 
definition is not valid");
+                                       error = true;
+                       }
+
+                       break;
+               }
                case BN_BIND:
                {
                        string seq, cmd;
Index: src/lfuns.h
===================================================================
--- src/lfuns.h (revision 20854)
+++ src/lfuns.h (working copy)
@@ -402,8 +402,10 @@
        LFUN_LAYOUT_MODULES_CLEAR,       // rgh, 20070825
        LFUN_LAYOUT_MODULE_ADD,          // rgh, 20070825
        LFUN_LAYOUT_RELOAD,              // rgh, 20070903
-       LFUN_MASTER_BUFFER_VIEW,         // Tommaso, 20070920
-       LFUN_MASTER_BUFFER_UPDATE,       // Tommaso, 20070920
+       LFUN_MASTER_BUFFER_VIEW,             // Tommaso, 20070920
+       // 295
+       LFUN_MASTER_BUFFER_UPDATE,           // Tommaso, 20070920
+       LFUN_CALL,                       // broider, 20071002
 
        LFUN_LASTACTION                  // end of the table
 };
Index: src/LyXAction.cpp
===================================================================
--- src/LyXAction.cpp   (revision 20854)
+++ src/LyXAction.cpp   (working copy)
@@ -53,6 +53,38 @@
 LyXAction lyxaction;
 
 
+/// information for a macro
+struct LyXAction::macro_info {
+       /// the expanded FuncRequest
+       FuncRequest func;
+       /// to avoid recursive calls
+       bool locked;
+};
+
+LyXAction::new_macro_error LyXAction::newMacro(string const & name, string 
const & def)
+{
+       string const name2 = trim(name);
+
+       if (!name2.length()) return MacroNameEmpty;
+
+       if (lyx_macro_map.find(name) != lyx_macro_map.end()) {
+               return MacroExists;
+       }
+
+       FuncRequest     func = lookupFunc(def);
+       if (func.action == LFUN_NOACTION ||
+               func.action == LFUN_UNKNOWN_ACTION) {
+                       return MacroDefInvalid;
+       }
+
+       macro_info * info = new macro_info;
+       info->func = func;
+       info->locked = false;
+       lyx_macro_map[name] = info;
+       return MacroOk;
+}
+
+
 void LyXAction::newFunc(kb_action action, string const & name,
                        unsigned int attrib)
 {
@@ -144,6 +176,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 },
@@ -394,6 +427,16 @@
 }
 
 
+LyXAction::~LyXAction()
+{
+       macro_map::iterator pos = lyx_macro_map.begin();
+       while (pos != lyx_macro_map.end()) {
+               delete pos->second;
+               ++pos;
+       }
+}
+
+
 // Returns an action tag from a string.
 FuncRequest LyXAction::lookupFunc(string const & func) const
 {
@@ -412,6 +455,53 @@
 }
 
 
+// lock a macro and get the associated action
+bool LyXAction::lockMacro(string const & name, FuncRequest &func)
+{
+       string const name2 = trim(name);
+
+       if (name2.empty()) {
+               func = FuncRequest(LFUN_NOACTION);
+               return true;
+       }
+
+       macro_map::const_iterator mit = lyx_macro_map.find(name2);
+
+       if (mit == lyx_macro_map.end()) {
+               func = FuncRequest(LFUN_UNKNOWN_ACTION);
+               return true;
+       }
+
+       if (mit->second->locked) {
+               func = FuncRequest(LFUN_NOACTION);
+               return false;
+       }
+
+       mit->second->locked = true;
+       func = mit->second->func;
+       return true;
+}
+
+
+// release a macro lock
+void LyXAction::releaseMacro(string const & name)
+{
+       string const name2 = trim(name);
+
+       if (name2.empty()) {
+               return;
+       }
+
+       macro_map::const_iterator mit = lyx_macro_map.find(name2);
+
+       if (mit == lyx_macro_map.end()) {
+               return;
+       }
+
+       mit->second->locked = false;
+}
+
+
 string const LyXAction::getActionName(kb_action action) const
 {
        info_map::const_iterator const it = lyx_info_map.find(action);
Index: src/LyXAction.h
===================================================================
--- src/LyXAction.h     (revision 20854)
+++ src/LyXAction.h     (working copy)
@@ -42,6 +42,11 @@
                unsigned int attrib;
        };
 
+       /// information for a macro
+       struct macro_info;
+
+               /// type for map between a macro name and its info
+       typedef std::map<std::string, macro_info*> macro_map;
 public:
        /// type for map between a function name and its action
        typedef std::map<std::string, kb_action> func_map;
@@ -58,7 +63,16 @@
                SingleParUpdate = 16 //< Usually only requires this par updated
        };
 
+       /// possible reasons for not allowed macros
+       enum new_macro_error {
+               MacroOk,
+               MacroNameEmpty,
+               MacroDefInvalid,
+               MacroExists
+       };
+
        LyXAction();
+       ~LyXAction();
 
        /**
         * Returns an pseudoaction from a string
@@ -67,6 +81,11 @@
         */
        FuncRequest lookupFunc(std::string const & func_name) const;
 
+       /// lock and retieve the macro
+       bool lockMacro(std::string const & macro_name, FuncRequest &func);
+       /// release the macro
+       void releaseMacro(std::string const & macro_name);
+
        /// Return the name (and argument) associated with the given (pseudo) 
action
        std::string const getActionName(kb_action action) const;
 
@@ -82,6 +101,9 @@
        /// return an iterator to the end of all real actions
        const_func_iterator func_end() const;
 
+       /// add a new macro
+       new_macro_error newMacro(std::string const & name, std::string const & 
def);
+
 private:
        /// populate the action container with our actions
        void init();
@@ -101,6 +123,9 @@
         * command attributes (ro)
         */
        info_map lyx_info_map;
+
+       /// This is a list of all the macros with the coresponding expansion.
+       macro_map lyx_macro_map;
 };
 
 /// singleton instance
Index: src/LyXFunc.cpp
===================================================================
--- src/LyXFunc.cpp     (revision 20854)
+++ src/LyXFunc.cpp     (working copy)
@@ -701,8 +701,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 (lyxaction.lockMacro(name, func)) {
+                       func.origin = cmd.origin;
+                       flag = getStatus(func);
+                       lyxaction.releaseMacro(name);
+               } else {
+                       // catch recursion
+                       // all operations until the recursion 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:
@@ -1632,6 +1649,21 @@
                        break;
                }
 
+               case LFUN_CALL: {
+                       FuncRequest func;
+                       if (lyxaction.lockMacro(argument, func)) {
+                               func.origin = cmd.origin;
+                               dispatch(func);
+                               lyxaction.releaseMacro(argument);
+                       } else {
+                               // recursion detected
+                               lyxerr << "Warning: Recursion in the macro '"
+                                      << argument << " detected"
+                                      << endl;
+                       }
+                       break;
+               }
+
                case LFUN_PREFERENCES_SAVE: {
                        lyxrc.write(makeAbsPath("preferences",
                                                
package().user_support().absFilename()),

Reply via email to