]> git.eshelyaron.com Git - emacs.git/commitdiff
Synch SRecode to CEDET 1.0.
authorEric M. Ludlam <zappo@gnu.org>
Tue, 21 Sep 2010 22:11:23 +0000 (18:11 -0400)
committerChong Yidong <cyd@stupidchicken.com>
Tue, 21 Sep 2010 22:11:23 +0000 (18:11 -0400)
* lisp/cedet/cedet.el (cedet-version):
* lisp/cedet/srecode.el (srecode-version): Bump version to 1.0.

* lisp/cedet/pulse.el (pulse-momentary-highlight-overlay): If pulse-flag is
'never, disable all pulsing.

* lisp/cedet/srecode/compile.el (srecode-compile-templates): Fix directory
compare of built-in templates.  Give built-ins lower piority.
Support special variable "project".
(srecode-compile-template-table): Set :project slot of new tables.
(srecode-compile-one-template-tag): Use
srecode-create-dictionaries-from-tags.

* lisp/cedet/srecode/cpp.el (srecode-cpp): New defgroup.
(srecode-cpp-namespaces): New option.
(srecode-semantic-handle-:using-namespaces)
(srecode-cpp-apply-templates): New functions.
(srecode-semantic-apply-tag-to-dict): Handle template parameters
by calling `srecode-cpp-apply-templates'.

* lisp/cedet/srecode/dictionary.el (srecode-dictionary-add-template-table):
Do not add variables in tables not for the current project.
(srecode-compound-toString): Handle cases where the default value
is another compound value.
(srecode-dictionary-lookup-name): New optional argument
NON-RECURSIVE, which inhibits visiting dictionary parents.
(srecode-dictionary-add-section-dictionary)
(srecode-dictionary-merge): New optional argument FORCE adds
values even if an identically named entry exists.
(srecode-dictionary-add-entries): New method.
(srecode-create-dictionaries-from-tags): New function.

* lisp/cedet/srecode/fields.el (srecode-fields-exit-confirmation): New option.
(srecode-field-exit-ask): Use it.

* lisp/cedet/srecode/find.el (srecode-template-get-table)
(srecode-template-get-table-for-binding)
(srecode-all-template-hash): Skip if not in current project.
(srecode-template-table-in-project-p): New method.

* lisp/cedet/srecode/getset.el (srecode-insert-getset): Force tag table
update.  Don't query the class if it is empty.

* lisp/cedet/srecode/insert.el (srecode-insert-fcn): Merge template
dictionary before resolving arguments.
(srecode-insert-method-helper): Add error checking to make sure
that we only have dictionaries.
(srecode-insert-method): Check template nesting depth when using
point inserter override.
(srecode-insert-method): Install override with depth limit.

* lisp/cedet/srecode/map.el (srecode-map-update-map): Make map loading more
robust.

* lisp/cedet/srecode/mode.el (srecode-bind-insert): Call
srecode-load-tables-for-mode.
(srecode-minor-mode-templates-menu): Do not list templates that
are not in the current project.
(srecode-menu-bar): Add binding for srecode-macro-help.

* lisp/cedet/srecode/table.el (srecode-template-table): Add :project slot.
(srecode-dump): Dump it.

* lisp/cedet/srecode/texi.el (srecode-texi-insert-tag-as-doc): New function.
(semantic-insert-foreign-tag): Use it.

18 files changed:
etc/ChangeLog
etc/srecode/java.srt
lisp/cedet/ChangeLog
lisp/cedet/cedet.el
lisp/cedet/pulse.el
lisp/cedet/srecode.el
lisp/cedet/srecode/compile.el
lisp/cedet/srecode/cpp.el
lisp/cedet/srecode/dictionary.el
lisp/cedet/srecode/fields.el
lisp/cedet/srecode/find.el
lisp/cedet/srecode/getset.el
lisp/cedet/srecode/insert.el
lisp/cedet/srecode/map.el
lisp/cedet/srecode/mode.el
lisp/cedet/srecode/semantic.el
lisp/cedet/srecode/table.el
lisp/cedet/srecode/texi.el

index d2145fb811bb1b918816e304a3b64bfafb0bb1f0..7bbc06fa4afaa3eeb2095752052121339e725340 100644 (file)
@@ -1,3 +1,7 @@
+2010-09-21  Eric Ludlam  <zappo@gnu.org>
+
+       * srecode/java.srt: Make NAME be a prompt.
+
 2010-08-22  Alex Harsanyi  <harsanyi@mac.com>  (tiny change)
 
        * emacs3.py: Import imp module and use it (Bug#5756).
index c449f0d77c927dfec4d995931c1c563c4c41cd8e..d4cc986a3237ab02e8bfce84836e151c09cbf610 100644 (file)
@@ -83,7 +83,7 @@ public Class {{?NAME}} {{#PARENTS}}{{#FIRST}}extends {{/FIRST}}{{#NOTFIRST}}impl
 template include :blank
 "An include statement."
 ----
-import {{NAME}};
+import {{?NAME}};
 ----
 
 context misc
index cdd5568dffcfd7c3728c054d63a0e99cdb0cd211..34120817a43f152329e23bf725cdd73b9159c386 100644 (file)
@@ -1,3 +1,73 @@
+2010-09-21  Eric Ludlam  <zappo@gnu.org>
+
+       Synch SRecode to CEDET 1.0.
+
+       * pulse.el (pulse-momentary-highlight-overlay): If pulse-flag is
+       'never, disable all pulsing.
+
+       * cedet.el (cedet-version):
+       * srecode.el (srecode-version): Bump version to 1.0.
+
+       * srecode/texi.el (srecode-texi-insert-tag-as-doc): New function.
+       (semantic-insert-foreign-tag): Use it.
+
+       * srecode/mode.el (srecode-bind-insert): Call
+       srecode-load-tables-for-mode.
+       (srecode-minor-mode-templates-menu): Do not list templates that
+       are not in the current project.
+       (srecode-menu-bar): Add binding for srecode-macro-help.
+
+       * srecode/table.el (srecode-template-table): Add :project slot.
+       (srecode-dump): Dump it.
+
+       * srecode/map.el (srecode-map-update-map): Make map loading more
+       robust.
+
+       * srecode/insert.el (srecode-insert-fcn): Merge template
+       dictionary before resolving arguments.
+       (srecode-insert-method-helper): Add error checking to make sure
+       that we only have dictionaries.
+       (srecode-insert-method): Check template nesting depth when using
+       point inserter override.
+       (srecode-insert-method): Install override with depth limit.
+
+       * srecode/getset.el (srecode-insert-getset): Force tag table
+       update.  Don't query the class if it is empty.
+
+       * srecode/find.el (srecode-template-get-table)
+       (srecode-template-get-table-for-binding)
+       (srecode-all-template-hash): Skip if not in current project.
+       (srecode-template-table-in-project-p): New method.
+
+       * srecode/fields.el (srecode-fields-exit-confirmation): New option.
+       (srecode-field-exit-ask): Use it.
+
+       * srecode/dictionary.el (srecode-dictionary-add-template-table):
+       Do not add variables in tables not for the current project.
+       (srecode-compound-toString): Handle cases where the default value
+       is another compound value.
+       (srecode-dictionary-lookup-name): New optional argument
+       NON-RECURSIVE, which inhibits visiting dictionary parents.
+       (srecode-dictionary-add-section-dictionary)
+       (srecode-dictionary-merge): New optional argument FORCE adds
+       values even if an identically named entry exists.
+       (srecode-dictionary-add-entries): New method.
+       (srecode-create-dictionaries-from-tags): New function.
+
+       * srecode/cpp.el (srecode-cpp): New defgroup.
+       (srecode-cpp-namespaces): New option.
+       (srecode-semantic-handle-:using-namespaces)
+       (srecode-cpp-apply-templates): New functions.
+       (srecode-semantic-apply-tag-to-dict): Handle template parameters
+       by calling `srecode-cpp-apply-templates'.
+
+       * srecode/compile.el (srecode-compile-templates): Fix directory
+       compare of built-in templates.  Give built-ins lower piority.
+       Support special variable "project".
+       (srecode-compile-template-table): Set :project slot of new tables.
+       (srecode-compile-one-template-tag): Use
+       srecode-create-dictionaries-from-tags.
+
 2010-09-21  Eric Ludlam  <zappo@gnu.org>
 
        Synch EDE to CEDET 1.0.
index b15745aac76e2bf043cd1f97ef4a82e99bb8eb76..26452f20c171ec020bce149b3cf6649b75b95524 100644 (file)
 
 (declare-function inversion-find-version "inversion")
 
-(defconst cedet-version "1.0pre7"
+(defconst cedet-version "1.0"
   "Current version of CEDET.")
 
 (defconst cedet-packages
   `(
     ;;PACKAGE   MIN-VERSION
     (cedet         ,cedet-version)
-    (eieio         "1.2")
-    (semantic      "2.0pre7")
-    (srecode       "1.0pre7")
-    (ede           "1.0pre7")
-    (speedbar      "1.0.3"))
-  "Table of CEDET packages to install.")
+    (eieio         "1.3")
+    (semantic      "2.0")
+    (srecode       "1.0")
+    (ede           "1.0")
+    (speedbar      "1.0"))
+  "Table of CEDET packages installed.")
 
 (defvar cedet-menu-map ;(make-sparse-keymap "CEDET menu")
   (let ((map (make-sparse-keymap "CEDET menu")))
index ce11c18e60906c1422251370692838cb5ed07594..593f196982b65b620f45cf094148e979dce77257 100644 (file)
@@ -3,6 +3,7 @@
 ;;; Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <eric@siege-engine.com>
+;; Version: 1.0
 
 ;; This file is part of GNU Emacs.
 
     (error nil)))
 
 (defcustom pulse-flag (pulse-available-p)
-  "*Non-nil means to pulse the overlay face for momentary highlighting.
-Pulsing involves a bright highlight that slowly shifts to the background
-color.  Non-nil just means to highlight with an unchanging color for a short
-time.
+  "Whether to use pulsing for momentary highlighting.
+Pulsing involves a bright highlight that slowly shifts to the
+background color.
+
+If the value is nil, highlight with an unchanging color until a
+key is pressed.
+If the value is `never', do no coloring at all.
+Any other value means to the default pulsing behavior.
 
 If `pulse-flag' is non-nil, but `pulse-available-p' is nil, then
 this flag is ignored."
@@ -178,22 +183,23 @@ Be sure to call `pulse-reset-face' after calling pulse."
 Optional argument FACE specifies the fact to do the highlighting."
   (overlay-put o 'original-face (overlay-get o 'face))
   (add-to-list 'pulse-momentary-overlay o)
-  (if (or (not pulse-flag) (not (pulse-available-p)))
-      ;; Provide a face... clear on next command
-      (progn
-       (overlay-put o 'face (or face 'pulse-highlight-start-face))
-       (add-hook 'pre-command-hook
-                 'pulse-momentary-unhighlight)
-       )
-    ;; pulse it.
-    (unwind-protect
+  (if (eq pulse-flag 'never)
+      nil
+    (if (or (not pulse-flag) (not (pulse-available-p)))
+       ;; Provide a face... clear on next command
        (progn
-         (overlay-put o 'face 'pulse-highlight-face)
-         ;; The pulse function puts FACE onto 'pulse-highlight-face.
-         ;; Thus above we put our face on the overlay, but pulse
-         ;; with a reference face needed for the color.
-         (pulse face))
-      (pulse-momentary-unhighlight))))
+         (overlay-put o 'face (or face 'pulse-highlight-start-face))
+         (add-hook 'pre-command-hook
+                   'pulse-momentary-unhighlight))
+      ;; pulse it.
+      (unwind-protect
+         (progn
+           (overlay-put o 'face 'pulse-highlight-face)
+           ;; The pulse function puts FACE onto 'pulse-highlight-face.
+           ;; Thus above we put our face on the overlay, but pulse
+           ;; with a reference face needed for the color.
+           (pulse face))
+       (pulse-momentary-unhighlight)))))
 
 (defun pulse-momentary-unhighlight ()
   "Unhighlight a line recently highlighted."
index a903ffd0af15e89ea17bfcea65018538356d99fa..ac9a000ccd579439f714a362246d5a1f1282783a 100644 (file)
@@ -40,7 +40,7 @@
 (require 'mode-local)
 (load "srecode/loaddefs" nil 'nomessage)
 
-(defvar srecode-version "1.0pre7"
+(defvar srecode-version "1.0"
   "Current version of the Semantic Recoder.")
 
 ;;; Code:
index 3caab23e31f6700ce179fa33d545aa5d9df716fc..de9b6f56de32450dd4a3bd9174b20c7079d1841c 100644 (file)
 (require 'semantic)
 (require 'eieio)
 (require 'eieio-base)
-(require 'srecode)
 (require 'srecode/table)
+(require 'srecode/dictionary)
 
 (declare-function srecode-template-inserter-newline-child-p "srecode/insert"
                  t t)
-(declare-function srecode-create-section-dictionary "srecode/dictionary")
-(declare-function srecode-dictionary-compound-variable "srecode/dictionary")
 
 ;;; Code:
 
 ;;; Template Class
 ;;
-;; Templatets describe a patter of text that can be inserted into a
+;; Templates describe a pattern of text that can be inserted into a
 ;; buffer.
 ;;
 (defclass srecode-template (eieio-named)
@@ -213,6 +211,7 @@ Arguments ESCAPE-START and ESCAPE-END are the current escape sequences in use."
        (mode nil)
        (application nil)
        (priority nil)
+       (project nil)
        (vars nil)
        )
 
@@ -256,6 +255,8 @@ Arguments ESCAPE-START and ESCAPE-END are the current escape sequences in use."
                     (setq application (read firstvalue)))
                    ((string= name "priority")
                     (setq priority (read firstvalue)))
+                   ((string= name "project")
+                    (setq project firstvalue))
                    (t
                     ;; Assign this into some table of variables.
                     (setq vars (cons (cons name firstvalue) vars))
@@ -297,12 +298,19 @@ Arguments ESCAPE-START and ESCAPE-END are the current escape sequences in use."
     ;; Calculate priority
     ;;
     (if (not priority)
-       (let ((d (file-name-directory (buffer-file-name)))
-             (sd (file-name-directory (locate-library "srecode")))
-             (defaultdelta (if (eq mode 'default) 20 0)))
-         (if (string= d sd)
-             (setq priority (+ 80 defaultdelta))
-           (setq priority (+ 30 defaultdelta)))
+       (let ((d (expand-file-name (file-name-directory (buffer-file-name))))
+             (sd (expand-file-name (file-name-directory (locate-library "srecode"))))
+             (defaultdelta (if (eq mode 'default) 0 10)))
+         ;; @TODO :   WHEN INTEGRATING INTO EMACS
+         ;;   The location of Emacs default templates needs to be specified
+         ;;   here to also have a lower priority.
+         (if (string-match (concat "^" sd) d)
+             (setq priority (+ 30 defaultdelta))
+           ;; If the user created template is for a project, then
+           ;; don't add as much as if it is unique to just some user.
+           (if (stringp project)
+               (setq priority (+ 50 defaultdelta))
+             (setq priority (+ 80 defaultdelta))))
          (message "Templates %s has estimated priority of %d"
                   (file-name-nondirectory (buffer-file-name))
                   priority))
@@ -311,56 +319,56 @@ Arguments ESCAPE-START and ESCAPE-END are the current escape sequences in use."
               priority))
 
     ;; Save it up!
-    (srecode-compile-template-table table mode priority application vars)
+    (srecode-compile-template-table table mode priority application project vars)
     )
 )
 
-(defun srecode-compile-one-template-tag (tag STATE)
-  "Compile a template tag TAG into an srecode template class.
-STATE is the current compile state as an object `srecode-compile-state'."
-  (require 'srecode/dictionary)
-  (let* ((context (oref STATE context))
-        (codeout  (srecode-compile-split-code
-                   tag (semantic-tag-get-attribute tag :code)
-                   STATE))
-        (code (cdr codeout))
-        (args (semantic-tag-function-arguments tag))
-        (binding (semantic-tag-get-attribute tag :binding))
-        (rawdicts (semantic-tag-get-attribute tag :dictionaries))
-        (sdicts (srecode-create-section-dictionary rawdicts STATE))
-        (addargs nil)
-        )
-;    (message "Compiled %s to %d codes with %d args and %d prompts."
-;           (semantic-tag-name tag)
-;           (length code)
-;           (length args)
-;           (length prompts))
-    (while args
-      (setq addargs (cons (intern (car args)) addargs))
-      (when (eq (car addargs) :blank)
-       ;; If we have a wrap, then put wrap inserters on both
-       ;; ends of the code.
-       (setq code (append
-                   (list (srecode-compile-inserter "BLANK"
-                                                   "\r"
-                                                   STATE
-                                                   :secondname nil
-                                                   :where 'begin))
-                   code
-                   (list (srecode-compile-inserter "BLANK"
-                                                   "\r"
-                                                   STATE
-                                                   :secondname nil
-                                                   :where 'end))
-                         )))
-      (setq args (cdr args)))
+(defun srecode-compile-one-template-tag (tag state)
+  "Compile a template tag TAG into a srecode template object.
+STATE is the current compile state as an object of class
+`srecode-compile-state'."
+  (let* ((context   (oref state context))
+        (code      (cdr (srecode-compile-split-code
+                         tag (semantic-tag-get-attribute tag :code)
+                         state)))
+        (args      (semantic-tag-function-arguments tag))
+        (binding   (semantic-tag-get-attribute tag :binding))
+        (dict-tags (semantic-tag-get-attribute tag :dictionaries))
+        (root-dict (when dict-tags
+                     (srecode-create-dictionaries-from-tags
+                      dict-tags state)))
+        (addargs))
+    ;; Examine arguments.
+    (dolist (arg args)
+      (let ((symbol (intern arg)))
+       (push symbol addargs)
+
+       ;; If we have a wrap, then put wrap inserters on both ends of
+       ;; the code.
+       (when (eq symbol :blank)
+         (setq code (append
+                     (list (srecode-compile-inserter
+                            "BLANK"
+                            "\r"
+                            state
+                            :secondname nil
+                            :where 'begin))
+                     code
+                     (list (srecode-compile-inserter
+                            "BLANK"
+                            "\r"
+                            state
+                            :secondname nil
+                            :where 'end)))))))
+
+    ;; Construct and return the template object.
     (srecode-template (semantic-tag-name tag)
-                     :context context
-                     :args (nreverse addargs)
-                     :dictionary sdicts
-                     :binding binding
-                     :code code)
-    ))
+                     :context    context
+                     :args       (nreverse addargs)
+                     :dictionary root-dict
+                     :binding    binding
+                     :code       code))
+  )
 
 (defun srecode-compile-do-hard-newline-p (comp)
   "Examine COMP to decide if the upcoming newline should be hard.
@@ -514,12 +522,13 @@ to the inserter constructor."
       (if (not new) (error "SRECODE: Unknown macro code %S" key))
       new)))
 
-(defun srecode-compile-template-table (templates mode priority application vars)
+(defun srecode-compile-template-table (templates mode priority application project vars)
   "Compile a list of TEMPLATES into an semantic recode table.
 The table being compiled is for MODE, or the string \"default\".
 PRIORITY is a numerical value that indicates this tables location
 in an ordered search.
 APPLICATION is the name of the application these templates belong to.
+PROJECT is a directory name which these templates scope to.
 A list of defined variables VARS provides a variable table."
   (let ((namehash (make-hash-table :test 'equal
                                   :size (length templates)))
@@ -549,6 +558,9 @@ A list of defined variables VARS provides a variable table."
 
        (setq lp (cdr lp))))
 
+    (when (stringp project)
+      (setq project (expand-file-name project)))
+
     (let* ((table (srecode-mode-table-new mode (buffer-file-name)
                   :templates (nreverse templates)
                   :namehash namehash
@@ -556,7 +568,8 @@ A list of defined variables VARS provides a variable table."
                   :variables vars
                   :major-mode mode
                   :priority priority
-                  :application application))
+                  :application application
+                  :project project))
           (tmpl (oref table templates)))
       ;; Loop over all the templates, and xref.
       (while tmpl
index ceaa6fba3aa19c5f5276dfbf71d8c8873a2e76b3..7fe2bdaa410c021cf69d0caa84b45453d69cd8ff 100644 (file)
 
 ;;; Code:
 
+(require 'srecode)
+(require 'srecode/dictionary)
+(require 'srecode/semantic)
+(require 'semantic/tag)
+
+;;; Customization
+;;
+
+(defgroup srecode-cpp nil
+  "C++-specific Semantic Recoder settings."
+  :group 'srecode)
+
+(defcustom srecode-cpp-namespaces
+  '("std" "boost")
+  "List expansion candidates for the :using-namespaces argument.
+A dictionary entry of the named PREFIX_NAMESPACE with the value
+NAMESPACE:: is created for each namespace unless the current
+buffer contains a using NAMESPACE; statement "
+  :group 'srecode-cpp
+  :type  '(repeat string))
+
 ;;; :cpp ARGUMENT HANDLING
 ;;
 ;; When a :cpp argument is required, fill the dictionary with
 ;;
 ;; Error if not in a C++ mode.
 
-(require 'srecode)
-(require 'srecode/dictionary)
-(require 'srecode/semantic)
-
 ;;;###autoload
 (defun srecode-semantic-handle-:cpp (dict)
   "Add macros into the dictionary DICT based on the current c++ file.
@@ -59,6 +76,23 @@ HEADER - Shown section if in a header file."
     )
   )
 
+(defun srecode-semantic-handle-:using-namespaces (dict)
+  "Add macros into the dictionary DICT based on used namespaces.
+Adds the following:
+PREFIX_NAMESPACE - for each NAMESPACE in `srecode-cpp-namespaces'."
+  (let ((tags (semantic-find-tags-by-class
+              'using (semantic-fetch-tags))))
+    (dolist (name srecode-cpp-namespaces)
+      (let ((variable (format "PREFIX_%s" (upcase name)))
+           (prefix   (format "%s::"      name)))
+       (srecode-dictionary-set-value dict variable prefix)
+       (dolist (tag tags)
+         (when (and (eq (semantic-tag-get-attribute tag :kind)
+                        'namespace)
+                    (string= (semantic-tag-name tag) name))
+           (srecode-dictionary-set-value dict variable ""))))))
+  )
+
 (define-mode-local-override srecode-semantic-apply-tag-to-dict
   c++-mode (tag-wrapper dict)
   "Apply C++ specific features from TAG-WRAPPER into DICT.
@@ -97,6 +131,7 @@ special behavior for tag of classes include, using and function."
         (srecode-semantic-tag (semantic-tag-name value-tag)
                               :prime value-tag)
         value-dict))
+
       ;; Discriminate using statements referring to namespaces and
       ;; types.
       (when (eq (semantic-tag-get-attribute tag :kind) 'namespace)
@@ -111,7 +146,8 @@ special behavior for tag of classes include, using and function."
       ;; when they make sense. My best bet would be
       ;; (semantic-tag-function-parent tag), but it is not there, when
       ;; the function is defined in the scope of a class.
-      (let ((member    't)
+      (let ((member t)
+           (templates (semantic-tag-get-attribute tag :template))
            (modifiers (semantic-tag-modifiers tag)))
 
        ;; Add modifiers into the dictionary
@@ -120,6 +156,9 @@ special behavior for tag of classes include, using and function."
                                dict "MODIFIERS")))
            (srecode-dictionary-set-value modifier-dict "NAME" modifier)))
 
+       ;; Add templates into child dictionaries.
+       (srecode-cpp-apply-templates dict templates)
+
        ;; When the function is a member function, it can have
        ;; additional modifiers.
        (when member
@@ -133,11 +172,40 @@ special behavior for tag of classes include, using and function."
          ;; entry.
          (when (semantic-tag-get-attribute tag :pure-virtual-flag)
            (srecode-dictionary-show-section dict "PURE"))
-         )
-       ))
+         )))
+
+     ;;
+     ;; CLASS
+     ;;
+     ((eq class 'type)
+      ;; For classes, add template parameters.
+      (when (or (semantic-tag-of-type-p tag "class")
+               (semantic-tag-of-type-p tag "struct"))
+
+       ;; Add templates into child dictionaries.
+       (let ((templates (semantic-tag-get-attribute tag :template)))
+         (srecode-cpp-apply-templates dict templates))))
      ))
   )
 
+\f
+;;; Helper functions
+;;
+
+(defun srecode-cpp-apply-templates (dict templates)
+  "Add section dictionaries for TEMPLATES to DICT."
+  (when templates
+    (let ((templates-dict (srecode-dictionary-add-section-dictionary
+                          dict "TEMPLATES")))
+      (dolist (template templates)
+       (let ((template-dict (srecode-dictionary-add-section-dictionary
+                             templates-dict "ARGS")))
+         (srecode-semantic-apply-tag-to-dict
+          (srecode-semantic-tag (semantic-tag-name template)
+                                :prime template)
+          template-dict)))))
+  )
+
 (provide 'srecode/cpp)
 
 ;; Local variables:
index 8d168a7f3392203f5157be87799f094b0b32ddd7..cd97c8805953f958f22fbc99ec3ffa217fa7a10c 100644 (file)
@@ -37,6 +37,7 @@
 (declare-function srecode-compile-parse-inserter "srecode/compile")
 (declare-function srecode-dump-code-list "srecode/compile")
 (declare-function srecode-load-tables-for-mode "srecode/find")
+(declare-function srecode-template-table-in-project-p "srecode/find")
 (declare-function srecode-insert-code-stream "srecode/insert")
 (declare-function data-debug-new-buffer "data-debug")
 (declare-function data-debug-insert-object-slots "eieio-datadebug")
@@ -157,40 +158,49 @@ buffer's table.
 If BUFFER-OR-PARENT is t, then this dictionary should not be
 associated with a buffer or parent."
   (save-excursion
+    ;; Handle the parent
     (let ((parent nil)
          (buffer nil)
          (origin nil)
          (initfrombuff nil))
-      (cond ((bufferp buffer-or-parent)
-            (set-buffer buffer-or-parent)
-            (setq buffer buffer-or-parent
-                  origin (buffer-name buffer-or-parent)
-                  initfrombuff t))
-           ((srecode-dictionary-child-p buffer-or-parent)
-            (setq parent buffer-or-parent
-                  buffer (oref buffer-or-parent buffer)
-                  origin (concat (object-name buffer-or-parent) " in "
-                                 (if buffer (buffer-name buffer)
-                                   "no buffer")))
-            (when buffer
-              (set-buffer buffer)))
-           ((eq buffer-or-parent t)
-            (setq buffer nil
-                  origin "Unspecified Origin"))
-           (t
-            (setq buffer (current-buffer)
-                  origin (concat "Unspecified.  Assume "
-                                 (buffer-name buffer))
-                  initfrombuff t)
-            )
-           )
+      (cond
+       ;; Parent is a buffer
+       ((bufferp buffer-or-parent)
+       (set-buffer buffer-or-parent)
+       (setq buffer buffer-or-parent
+             origin (buffer-name buffer-or-parent)
+             initfrombuff t))
+
+       ;; Parent is another dictionary
+       ((srecode-dictionary-child-p buffer-or-parent)
+       (setq parent buffer-or-parent
+             buffer (oref buffer-or-parent buffer)
+             origin (concat (object-name buffer-or-parent) " in "
+                            (if buffer (buffer-name buffer)
+                              "no buffer")))
+       (when buffer
+         (set-buffer buffer)))
+
+       ;; No parent
+       ((eq buffer-or-parent t)
+       (setq buffer nil
+             origin "Unspecified Origin"))
+
+       ;; Default to unspecified parent
+       (t
+       (setq buffer (current-buffer)
+             origin (concat "Unspecified.  Assume "
+                            (buffer-name buffer))
+             initfrombuff t)))
+
+      ;; Create the new dictionary object.
       (let ((dict (srecode-dictionary
                   major-mode
-                  :buffer buffer
-                  :parent parent
-                  :namehash  (make-hash-table :test 'equal
-                                              :size 20)
-                  :origin origin)))
+                  :buffer   buffer
+                  :parent   parent
+                  :namehash (make-hash-table :test 'equal
+                                             :size 20)
+                  :origin   origin)))
        ;; Only set up the default variables if we are being built
        ;; directroy for a particular buffer.
        (when initfrombuff
@@ -211,34 +221,37 @@ associated with a buffer or parent."
 TPL is an object representing a compiled template file."
   (when tpl
     (let ((tabs (oref tpl :tables)))
+      (require 'srecode/find) ; For srecode-template-table-in-project-p
       (while tabs
-       (let ((vars (oref (car tabs) variables)))
-         (while vars
-           (srecode-dictionary-set-value
-            dict (car (car vars)) (cdr (car vars)))
-           (setq vars (cdr vars))))
-       (setq tabs (cdr tabs))))))
+       (when (srecode-template-table-in-project-p (car tabs))
+         (let ((vars (oref (car tabs) variables)))
+           (while vars
+             (srecode-dictionary-set-value
+              dict (car (car vars)) (cdr (car vars)))
+             (setq vars (cdr vars)))))
+       (setq tabs (cdr tabs))))))
 
 
 (defmethod srecode-dictionary-set-value ((dict srecode-dictionary)
                                         name value)
   "In dictionary DICT, set NAME to have VALUE."
   ;; Validate inputs
-  (if (not (stringp name))
-      (signal 'wrong-type-argument (list name 'stringp)))
+  (unless (stringp name)
+    (signal 'wrong-type-argument (list name 'stringp)))
+
   ;; Add the value.
   (with-slots (namehash) dict
     (puthash name value namehash))
   )
 
 (defmethod srecode-dictionary-add-section-dictionary ((dict srecode-dictionary)
-                                                     name &optional show-only)
+                                                     name &optional show-only force)
   "In dictionary DICT, add a section dictionary for section macro NAME.
 Return the new dictionary.
 
-You can add several dictionaries to the same section macro.
-For each dictionary added to a macro, the block of codes in the
-template will be repeated.
+You can add several dictionaries to the same section entry.
+For each dictionary added to a variable, the block of codes in
+the template will be repeated.
 
 If optional argument SHOW-ONLY is non-nil, then don't add a new dictionary
 if there is already one in place.  Also, don't add FIRST/LAST entries.
@@ -255,10 +268,11 @@ which will enable SECTIONS to be enabled.
 Adding a new dictionary will alter these values in previously
 inserted dictionaries."
   ;; Validate inputs
-  (if (not (stringp name))
-      (signal 'wrong-type-argument (list name 'stringp)))
+  (unless (stringp name)
+    (signal 'wrong-type-argument (list name 'stringp)))
+
   (let ((new (srecode-create-dictionary dict))
-       (ov (srecode-dictionary-lookup-name dict name)))
+       (ov  (srecode-dictionary-lookup-name dict name t)))
 
     (when (not show-only)
       ;; Setup the FIRST/NOTFIRST and LAST/NOTLAST entries.
@@ -275,7 +289,9 @@ inserted dictionaries."
        (srecode-dictionary-show-section new "LAST"))
       )
 
-    (when (or (not show-only) (null ov))
+    (when (or force
+             (not show-only)
+             (null ov))
       (srecode-dictionary-set-value dict name (append ov (list new))))
     ;; Return the new sub-dictionary.
     new))
@@ -283,8 +299,9 @@ inserted dictionaries."
 (defmethod srecode-dictionary-show-section ((dict srecode-dictionary) name)
   "In dictionary DICT, indicate that the section NAME should be exposed."
   ;; Validate inputs
-  (if (not (stringp name))
-      (signal 'wrong-type-argument (list name 'stringp)))
+  (unless (stringp name)
+    (signal 'wrong-type-argument (list name 'stringp)))
+
   ;; Showing a section is just like making a section dictionary, but
   ;; with no dictionary values to add.
   (srecode-dictionary-add-section-dictionary dict name t)
@@ -294,51 +311,120 @@ inserted dictionaries."
   "In dictionary DICT, indicate that the section NAME should be hidden."
   ;; We need to find the has value, and then delete it.
   ;; Validate inputs
-  (if (not (stringp name))
-      (signal 'wrong-type-argument (list name 'stringp)))
+  (unless (stringp name)
+    (signal 'wrong-type-argument (list name 'stringp)))
+
   ;; Add the value.
   (with-slots (namehash) dict
     (remhash name namehash))
   nil)
 
-(defmethod srecode-dictionary-merge ((dict srecode-dictionary) otherdict)
-  "Merge into DICT the dictionary entries from OTHERDICT."
+(defmethod srecode-dictionary-add-entries ((dict srecode-dictionary)
+                                          entries &optional state)
+  "Add ENTRIES to DICT.
+
+ENTRIES is a list of even length of dictionary entries to
+add. ENTRIES looks like this:
+
+  (NAME_1 VALUE_1 NAME_2 VALUE_2 ...)
+
+The following rules apply:
+ * NAME_N is a string
+and for values
+ * If VALUE_N is t, the section NAME_N is shown.
+ * If VALUE_N is a string, an ordinary value is inserted.
+ * If VALUE_N is a dictionary, it is inserted as entry NAME_N.
+ * Otherwise, a compound variable is created for VALUE_N.
+
+The optional argument STATE has to non-nil when compound values
+are inserted. An error is signaled if ENTRIES contains compound
+values but STATE is nil."
+  (while entries
+    (let ((name  (nth 0 entries))
+         (value (nth 1 entries)))
+      (cond
+       ;; Value is t; show a section.
+       ((eq value t)
+       (srecode-dictionary-show-section dict name))
+
+       ;; Value is a simple string; create an ordinary dictionary
+       ;; entry
+       ((stringp value)
+       (srecode-dictionary-set-value dict name value))
+
+       ;; Value is a dictionary; insert as child dictionary.
+       ((srecode-dictionary-child-p value)
+       (srecode-dictionary-merge
+        (srecode-dictionary-add-section-dictionary dict name)
+        value t))
+
+       ;; Value is some other object; create a compound value.
+       (t
+       (unless state
+         (error "Cannot insert compound values without state."))
+
+       (srecode-dictionary-set-value
+        dict name
+        (srecode-dictionary-compound-variable
+         name :value value :state state)))))
+    (setq entries (nthcdr 2 entries)))
+  dict)
+
+(defmethod srecode-dictionary-merge ((dict srecode-dictionary) otherdict
+                                    &optional force)
+  "Merge into DICT the dictionary entries from OTHERDICT.
+Unless the optional argument FORCE is non-nil, values in DICT are
+not modified, even if there are values of the same names in
+OTHERDICT."
   (when otherdict
     (maphash
      (lambda (key entry)
-       ;; Only merge in the new values if there was no old value.
+       ;; The new values is only merged in if there was no old value
+       ;; or FORCE is non-nil.
+       ;;
        ;; This protects applications from being whacked, and basically
        ;; makes these new section dictionary entries act like
        ;; "defaults" instead of overrides.
-       (when (not (srecode-dictionary-lookup-name dict key))
-        (cond ((and (listp entry) (srecode-dictionary-p (car entry)))
-               ;; A list of section dictionaries.
-               ;; We need to merge them in.
-               (while entry
-                 (let ((new-sub-dict
-                        (srecode-dictionary-add-section-dictionary
-                         dict key)))
-                   (srecode-dictionary-merge new-sub-dict (car entry)))
-                 (setq entry (cdr entry)))
-                 )
-
-              (t
-               (srecode-dictionary-set-value dict key entry)))
-              ))
+       (when (or force
+                (not (srecode-dictionary-lookup-name dict key t)))
+        (cond
+         ;; A list of section dictionaries. We need to merge them in.
+         ((and (listp entry)
+               (srecode-dictionary-p (car entry)))
+          (dolist (sub-dict entry)
+            (srecode-dictionary-merge
+             (srecode-dictionary-add-section-dictionary
+              dict key t t)
+             sub-dict force)))
+
+         ;; Other values can be set directly.
+         (t
+          (srecode-dictionary-set-value dict key entry)))))
      (oref otherdict namehash))))
 
 (defmethod srecode-dictionary-lookup-name ((dict srecode-dictionary)
-                                          name)
-  "Return information about the current DICT's value for NAME."
+                                          name &optional non-recursive)
+  "Return information about DICT's value for NAME.
+DICT is a dictionary, and NAME is a string that is treated as the
+name of an entry in the dictionary. If such an entry exists, its
+value is returned. Otherwise, nil is returned. Normally, the
+lookup is recursive in the sense that the parent of DICT is
+searched for NAME if it is not found in DICT.  This recursive
+lookup can be disabled by the optional argument NON-RECURSIVE.
+
+This function derives values for some special NAMEs, such as
+'FIRST' and 'LAST'."
   (if (not (slot-boundp dict 'namehash))
       nil
-    ;; Get the value of this name from the dictionary
-    (or (with-slots (namehash) dict
-         (gethash name namehash))
-       (and (not (member name '("FIRST" "LAST" "NOTFIRST" "NOTLAST")))
-            (oref dict parent)
-            (srecode-dictionary-lookup-name (oref dict parent) name))
-       )))
+    ;; Get the value of this name from the dictionary or its parent
+    ;; unless the lookup should be non-recursive.
+    (with-slots (namehash parent) dict
+      (or (gethash name namehash)
+         (and (not non-recursive)
+              (not (member name '("FIRST" "LAST" "NOTFIRST" "NOTLAST")))
+              parent
+              (srecode-dictionary-lookup-name parent name)))))
+  )
 
 (defmethod srecode-root-dictionary ((dict srecode-dictionary))
   "For dictionary DICT, return the root dictionary.
@@ -431,10 +517,22 @@ inserted with a new editable field.")
           (start (point))
           (name (oref sti :object-name)))
 
-      (if (or (not dv) (string= dv ""))
-         (insert name)
-       (insert dv))
-
+      (cond
+       ;; No default value.
+       ((not dv) (insert name))
+       ;; A compound value as the default?  Recurse.
+       ((srecode-dictionary-compound-value-child-p dv)
+       (srecode-compound-toString dv function dictionary))
+       ;; A string that is empty?  Use the name.
+       ((and (stringp dv) (string= dv ""))
+       (insert name))
+       ;; Insert strings
+       ((stringp dv) (insert dv))
+       ;; Some other issue
+       (t
+       (error "Unknown default value for value %S" name)))
+
+      ;; Create a field from the inserter.
       (srecode-field name :name name
                     :start start
                     :end (point)
@@ -482,6 +580,53 @@ STATE is the current compiler state."
        (setq sectiondicts (cdr sectiondicts)))
       new)))
 
+(defun srecode-create-dictionaries-from-tags (tags state)
+  "Create a dictionary with entries according to TAGS.
+
+TAGS should be in the format produced by the template file
+grammar. That is
+
+TAGS = (ENTRY_1 ENTRY_2 ...)
+
+where
+
+ENTRY_N = (NAME ENTRY_N_1 ENTRY_N_2 ...) | TAG
+
+where TAG is a semantic tag of class 'variable. The (NAME ... )
+form creates a child dictionary which is stored under the name
+NAME. The TAG form creates a value entry or section dictionary
+entry whose name is the name of the tag.
+
+STATE is the current compiler state."
+  (let ((dict    (srecode-create-dictionary t))
+       (entries (apply #'append
+                       (mapcar
+                        (lambda (entry)
+                          (cond
+                           ;; Entry is a tag
+                           ((semantic-tag-p entry)
+                            (let ((name  (semantic-tag-name entry))
+                                  (value (semantic-tag-variable-default entry)))
+                              (list name
+                                    (if (and (listp value)
+                                             (= (length value) 1)
+                                             (stringp (car value)))
+                                        (car value)
+                                      value))))
+
+                           ;; Entry is a nested dictionary
+                           (t
+                            (let ((name    (car entry))
+                                  (entries (cdr entry)))
+                              (list name
+                                    (srecode-create-dictionaries-from-tags
+                                     entries state))))))
+                        tags))))
+    (srecode-dictionary-add-entries
+     dict entries state)
+    dict)
+  )
+
 ;;; DUMP DICTIONARY
 ;;
 ;; Make a dictionary, and dump it's contents.
index 347538aa8710ca5202ee08e4807e2d3e4429f56e..0cfc2953792327daaa5e76c4d1e21e2f523594d7 100644 (file)
@@ -35,6 +35,8 @@
 ;; Each field has 2 overlays.  The second overlay allows control in
 ;; the character just after the field, but does not highlight it.
 
+;; @TODO - Cancel an old field array if a new one is about to be created!
+
 ;; Keep this library independent of SRecode proper.
 (require 'eieio)
 
   "While inserting a set of fields, collect in this variable.
 Once an insertion set is done, these fields will be activated.")
 
+\f
+;;; Customization
+;;
+
 (defface srecode-field-face
   '((((class color) (background dark))
      (:underline "green"))
@@ -51,6 +57,11 @@ Once an insertion set is done, these fields will be activated.")
   "*Face used to specify editable fields from a template."
   :group 'semantic-faces)
 
+(defcustom srecode-fields-exit-confirmation nil
+  "Ask for confirmation before leaving field editing mode."
+  :group 'srecode
+  :type  'boolean)
+
 ;;; BASECLASS
 ;;
 ;; Fields and the template region share some basic overlay features.
@@ -237,7 +248,7 @@ If SET-TO is a string, then replace the text of OLAID wit SET-TO."
        (remove-hook 'post-command-hook 'srecode-field-post-command t)
       (if (srecode-point-in-region-p ar)
          nil ;; Keep going
-       ;; We moved out of the temlate.  Cancel the edits.
+       ;; We moved out of the template.  Cancel the edits.
        (srecode-delete ar)))
     ))
 
@@ -429,7 +440,8 @@ PRE-LEN is used in the after mode for the length of the changed text."
 (defun srecode-field-exit-ask ()
   "Ask if the user wants to exit field-editing mini-mode."
   (interactive)
-  (when (y-or-n-p "Exit field-editing mode? ")
+  (when (or (not srecode-fields-exit-confirmation)
+           (y-or-n-p "Exit field-editing mode? "))
     (srecode-delete (srecode-active-template-region))))
 
 
index 1a3057fda0ee46b054bf3aa32fde7cdc97ea75c8..9c5a897fc4f644c26f4c7e4ec90c47b3891327ae 100644 (file)
@@ -92,6 +92,23 @@ all template files for that application will be loaded."
        ))
     ))
 
+;;; PROJECT
+;;
+;; Find if a template table has a project set, and if so, is the
+;; current buffer in that project.
+(defmethod srecode-template-table-in-project-p ((tab srecode-template-table))
+  "Return non-nil if the table TAB can be used in the current project.
+If TAB has a :project set, check that the directories match.
+If TAB is nil, then always return t."
+  (let ((proj (oref tab :project)))
+    ;; Return t if the project wasn't set.
+    (if (not proj) t
+      ;; If the project directory was set, lets check it.
+      (let ((dd (expand-file-name default-directory))
+           (projexp (regexp-quote (directory-file-name proj))))
+       (if (string-match (concat "^" projexp) dd)
+           t nil)))))
+
 ;;; SEARCH
 ;;
 ;; Find a given template based on name, and features of the current
@@ -103,13 +120,14 @@ all template files for that application will be loaded."
 Optional argument CONTEXT specifies that the template should part
 of a particular context.
 The APPLICATION argument is unused."
-  (if context
-      ;; If a context is specified, then look it up there.
-      (let ((ctxth (gethash context (oref tab contexthash))))
-       (when ctxth
-         (gethash template-name ctxth)))
-    ;; No context, perhaps a merged name?
-    (gethash template-name (oref tab namehash))))
+  (when (srecode-template-table-in-project-p tab)
+    (if context
+       ;; If a context is specified, then look it up there.
+       (let ((ctxth (gethash context (oref tab contexthash))))
+         (when ctxth
+           (gethash template-name ctxth)))
+      ;; No context, perhaps a merged name?
+      (gethash template-name (oref tab namehash)))))
 
 (defmethod srecode-template-get-table ((tab srecode-mode-table)
                                       template-name &optional
@@ -144,32 +162,33 @@ tables that do not belong to an application will be searched."
   "Find in the template name in table TAB, the template with BINDING.
 Optional argument CONTEXT specifies that the template should part
 of a particular context."
-  (let* ((keyout nil)
-        (hashfcn (lambda (key value)
-                   (when (and (slot-boundp value 'binding)
-                              (oref value binding)
-                              (= (aref (oref value binding) 0) binding))
-                     (setq keyout key))))
-        (contextstr (cond ((listp context)
-                           (car-safe context))
-                          ((stringp context)
-                           context)
-                          (t nil)))
-        )
-    (if context
-       (let ((ctxth (gethash contextstr (oref tab contexthash))))
-         (when ctxth
-           ;; If a context is specified, then look it up there.
-           (maphash hashfcn ctxth)
-           ;; Context hashes EXCLUDE the context prefix which
-           ;; we need to include, so concat it here
-           (when keyout
-             (setq keyout (concat contextstr ":" keyout)))
-           )))
-    (when (not keyout)
-      ;; No context, or binding in context.  Try full hash.
-      (maphash hashfcn (oref tab namehash)))
-    keyout))
+  (when (srecode-template-table-in-project-p tab)
+    (let* ((keyout nil)
+          (hashfcn (lambda (key value)
+                     (when (and (slot-boundp value 'binding)
+                                (oref value binding)
+                                (= (aref (oref value binding) 0) binding))
+                       (setq keyout key))))
+          (contextstr (cond ((listp context)
+                             (car-safe context))
+                            ((stringp context)
+                             context)
+                            (t nil)))
+          )
+      (if context
+         (let ((ctxth (gethash contextstr (oref tab contexthash))))
+           (when ctxth
+             ;; If a context is specified, then look it up there.
+             (maphash hashfcn ctxth)
+             ;; Context hashes EXCLUDE the context prefix which
+             ;; we need to include, so concat it here
+             (when keyout
+               (setq keyout (concat contextstr ":" keyout)))
+             )))
+      (when (not keyout)
+       ;; No context, or binding in context.  Try full hash.
+       (maphash hashfcn (oref tab namehash)))
+      keyout)))
 
 (defmethod srecode-template-get-table-for-binding
   ((tab srecode-mode-table) binding &optional context application)
@@ -220,7 +239,8 @@ Optional argument HASH is the hash table to fill in."
           )
       (while tabs
        ;; Exclude templates for a perticular application.
-       (when (not (oref (car tabs) :application))
+       (when (and (not (oref (car tabs) :application))
+                  (srecode-template-table-in-project-p (car tabs)))
          (maphash (lambda (key temp)
                     (puthash key temp mhash)
                     )
index 87266bf247585e7759e2cd6dc67f8fe46ce1ddfd..a90f3a6d67af77c9f559ef8ba19ce114876cf8df 100644 (file)
@@ -55,8 +55,9 @@ will be derived."
       (error "No templates for inserting get/set"))
 
   ;; Step 1: Try to derive the tag for the class we will use
+  (semantic-fetch-tags)
   (let* ((class (or class-in (srecode-auto-choose-class (point))))
-        (tagstart (semantic-tag-start class))
+        (tagstart (when class (semantic-tag-start class)))
         (inclass (eq (semantic-current-tag-of-class 'type) class))
         (field nil)
         )
index 4ee6d4670098afa6c9b8cab709c8cfdf24422bc4..843b577e1eb8bba8032a71ad935e9fb62c3769aa 100644 (file)
@@ -26,6 +26,9 @@
 ;; Manage the insertion process for a template.
 ;;
 
+(eval-when-compile
+  (require 'cl)) ;; for `lexical-let'
+
 (require 'srecode/compile)
 (require 'srecode/find)
 (require 'srecode/dictionary)
@@ -49,7 +52,7 @@ Possible values are:
 NOTE: The field feature does not yet work with XEmacs."
   :group 'srecode
   :type '(choice (const :tag "Ask" ask)
-                (cons :tag "Field" field)))
+                (const :tag "Field" field)))
 
 (defvar srecode-insert-with-fields-in-progress nil
   "Non-nil means that we are actively inserting a template with fields.")
@@ -86,7 +89,6 @@ DICT-ENTRIES are additional dictionary values to add."
                                    (car dict-entries)
                                    (car (cdr dict-entries)))
       (setq dict-entries (cdr (cdr dict-entries))))
-    ;;(srecode-resolve-arguments temp newdict)
     (srecode-insert-fcn temp newdict)
     ;; Don't put code here.  We need to return the end-mark
     ;; for this insertion step.
@@ -100,6 +102,10 @@ has set everything up already."
   ;; Perform the insertion.
   (let ((standard-output (or stream (current-buffer)))
        (end-mark nil))
+    ;; Merge any template entries into the input dictionary.
+    (when (slot-boundp template 'dictionary)
+      (srecode-dictionary-merge dictionary (oref template dictionary)))
+
     (unless skipresolver
       ;; Make sure the semantic tags are up to date.
       (semantic-fetch-tags)
@@ -110,7 +116,7 @@ has set everything up already."
        ;; If there is a buffer, turn off various hooks.  This will cause
        ;; the mod hooks to be buffered up during the insert, but
        ;; prevent tools like font-lock from fontifying mid-template.
-       ;; Especialy important during insertion of complex comments that
+       ;; Especially important during insertion of complex comments that
        ;; cause the new font-lock to comment-color stuff after the inserted
        ;; comment.
        ;;
@@ -239,6 +245,9 @@ ST can be a class, or an object."
 (defmethod srecode-insert-method ((st srecode-template) dictionary)
   "Insert the srecoder template ST."
   ;; Merge any template entries into the input dictionary.
+  ;; This may happen twice since some templates arguments need
+  ;; these dictionary values earlier, but these values always
+  ;; need merging for template inserting in other templates.
   (when (slot-boundp st 'dictionary)
     (srecode-dictionary-merge dictionary (oref st dictionary)))
   ;; Do an insertion.
@@ -264,7 +273,7 @@ Use DICTIONARY to resolve any macros."
 ;; Specific srecode inserters.
 ;; The base class is from srecode-compile.
 ;;
-;; Each inserter handles various macro codes from the temlate.
+;; Each inserter handles various macro codes from the template.
 ;; The `code' slot specifies a character used to identify which
 ;; inserter is to be created.
 ;;
@@ -471,7 +480,7 @@ If SECONDNAME is nil, return VALUE."
        ;;    (setq val (format "%S" val))))
        ))
     ;; Output the dumb thing unless the type of thing specifically
-    ;; did the inserting forus.
+    ;; did the inserting for us.
     (when do-princ
       (princ val))))
 
@@ -498,7 +507,8 @@ If there is no entry, prompt the user for the value to use.
 The prompt text used is derived from the previous PROMPT command in the
 template file.")
 
-(defmethod srecode-inserter-apply-state ((ins srecode-template-inserter-ask) STATE)
+(defmethod srecode-inserter-apply-state
+  ((ins srecode-template-inserter-ask) STATE)
   "For the template inserter INS, apply information from STATE.
 Loop over the prompts to see if we have a match."
   (let ((prompts (oref STATE prompts))
@@ -669,7 +679,13 @@ Arguments ESCAPE-START and ESCAPE-END are the current escape sequences in use."
   )
 
 (defvar srecode-template-inserter-point-override nil
-  "When non-nil, the point inserter will do this function instead.")
+  "Point-positioning method for the SRecode template inserter.
+When nil, perform normal point-positioning behavior.
+When the value is a cons cell (DEPTH . FUNCTION), call FUNCTION
+instead, unless the template nesting depth, measured
+by (length (oref srecode-template active)), is greater than
+DEPTH.")
+
 
 (defclass srecode-template-inserter-point (srecode-template-inserter)
   ((key :initform ?^
@@ -702,15 +718,20 @@ Arguments ESCAPE-START and ESCAPE-END are the current escape sequences in use."
                                  dictionary)
   "Insert the STI inserter.
 Save point in the class allocated 'point' slot.
-If `srecode-template-inserter-point-override' then this generalized
-marker will do something else.  See `srecode-template-inserter-include-wrap'
-as an example."
-  (if srecode-template-inserter-point-override
+If `srecode-template-inserter-point-override' non-nil then this
+generalized marker will do something else.  See
+`srecode-template-inserter-include-wrap' as an example."
+  ;; If `srecode-template-inserter-point-override' is non-nil, its car
+  ;; is the maximum template nesting depth for which the override is
+  ;; valid. Compare this to the actual template nesting depth and
+  ;; maybe use the override function which is stored in the cdr.
+  (if (and srecode-template-inserter-point-override
+          (<= (length (oref srecode-template active))
+              (car srecode-template-inserter-point-override)))
       ;; Disable the old override while we do this.
-      (let ((over srecode-template-inserter-point-override)
+      (let ((over (cdr srecode-template-inserter-point-override))
            (srecode-template-inserter-point-override nil))
-       (funcall over dictionary)
-       )
+       (funcall over dictionary))
     (oset sti point (point-marker))
     ))
 
@@ -751,9 +772,15 @@ Loops over the embedded CODE which was saved here during compilation.
 The template to insert is stored in SLOT."
   (let ((dicts (srecode-dictionary-lookup-name
                dictionary (oref sti :object-name))))
+    (when (not (listp dicts))
+      (error "Cannot insert section %S from non-section variable."
+            (oref sti :object-name)))
     ;; If there is no section dictionary, then don't output anything
     ;; from this section.
     (while dicts
+      (when (not (srecode-dictionary-p (car dicts)))
+       (error "Cannot insert section %S from non-section variable."
+              (oref sti :object-name)))
       (srecode-insert-subtemplate sti (car dicts) slot)
       (setq dicts (cdr dicts)))))
 
@@ -853,39 +880,44 @@ this template instance."
     ;; If there was no template name, throw an error
     (if (not templatenamepart)
        (error "Include macro %s needs a template name" (oref sti :object-name)))
-    ;; Find the template by name, and save it.
-    (if (or (not (slot-boundp sti 'includedtemplate))
-           (not (oref sti includedtemplate)))
-       (let ((tmpl (srecode-template-get-table (srecode-table)
-                                               templatenamepart))
-             (active (oref srecode-template active))
-             ctxt)
+
+    ;; NOTE: We used to cache the template and not look it up a second time,
+    ;; but changes in the template tables can change which template is
+    ;; eventually discovered, so now we always lookup that template.
+
+    ;; Calculate and store the discovered template
+    (let ((tmpl (srecode-template-get-table (srecode-table)
+                                           templatenamepart))
+         (active (oref srecode-template active))
+         ctxt)
+      (when (not tmpl)
+       ;; If it isn't just available, scan back through
+       ;; the active template stack, searching for a matching
+       ;; context.
+       (while (and (not tmpl) active)
+         (setq ctxt (oref (car active) context))
+         (setq tmpl (srecode-template-get-table (srecode-table)
+                                                templatenamepart
+                                                ctxt))
          (when (not tmpl)
-           ;; If it isn't just available, scan back through
-           ;; the active template stack, searching for a matching
-           ;; context.
-           (while (and (not tmpl) active)
-             (setq ctxt (oref (car active) context))
-             (setq tmpl (srecode-template-get-table (srecode-table)
-                                                    templatenamepart
-                                                    ctxt))
-             (when (not tmpl)
-               (when (slot-boundp (car active) 'table)
-                 (let ((app (oref (oref (car active) table) application)))
-                   (when app
-                     (setq tmpl (srecode-template-get-table
-                                 (srecode-table)
-                                 templatenamepart
-                                 ctxt app)))
-                   )))
-             (setq active (cdr active)))
-           (when (not tmpl)
-             ;; If it wasn't in this context, look to see if it
-             ;; defines its own context
-             (setq tmpl (srecode-template-get-table (srecode-table)
-                                                    templatenamepart)))
-           )
-         (oset sti :includedtemplate tmpl)))
+           (when (slot-boundp (car active) 'table)
+             (let ((app (oref (oref (car active) table) application)))
+               (when app
+                 (setq tmpl (srecode-template-get-table
+                             (srecode-table)
+                             templatenamepart
+                             ctxt app)))
+               )))
+         (setq active (cdr active)))
+       (when (not tmpl)
+         ;; If it wasn't in this context, look to see if it
+         ;; defines it's own context
+         (setq tmpl (srecode-template-get-table (srecode-table)
+                                                templatenamepart)))
+       )
+
+      ;; Store the found template into this object for later use.
+      (oset sti :includedtemplate tmpl))
 
     (if (not (oref sti includedtemplate))
        ;; @todo - Call into a debugger to help find the template in question.
@@ -955,23 +987,31 @@ insert the section it wraps into the location in the included
 template where a ^ inserter occurs."
   ;; Step 1: Look up the included inserter
   (srecode-insert-include-lookup sti dictionary)
-  ;; Step 2: Temporarilly override the point inserter.
-  (let* ((vaguely-unique-name sti)
-        (srecode-template-inserter-point-override
-         (lambda (dict2)
-           (if (srecode-dictionary-lookup-name
-                dict2 (oref vaguely-unique-name :object-name))
-               ;; Insert our sectional part with looping.
-               (srecode-insert-method-helper
-                vaguely-unique-name dict2 'template)
-             ;; Insert our sectional part just once.
-             (srecode-insert-subtemplate vaguely-unique-name
-                                         dict2 'template))
-          )))
+  ;; Step 2: Temporarily override the point inserter.
+  ;; We bind `srecode-template-inserter-point-override' to a cons cell
+  ;; (DEPTH . FUNCTION) that has the maximum template nesting depth,
+  ;; for which the override is valid, in DEPTH and a lambda function
+  ;; which implements the wrap insertion behavior in FUNCTION. The
+  ;; maximum valid nesting depth is just the current depth + 1.
+  (let ((srecode-template-inserter-point-override
+        (lexical-let ((inserter1 sti))
+          (cons
+           ;; DEPTH
+           (+ (length (oref srecode-template active)) 1)
+           ;; FUNCTION
+           (lambda (dict)
+             (let ((srecode-template-inserter-point-override nil))
+               (if (srecode-dictionary-lookup-name
+                    dict (oref inserter1 :object-name))
+                   ;; Insert our sectional part with looping.
+                   (srecode-insert-method-helper
+                    inserter1 dict 'template)
+                 ;; Insert our sectional part just once.
+                 (srecode-insert-subtemplate
+                  inserter1 dict 'template))))))))
     ;; Do a regular insertion for an include, but with our override in
     ;; place.
-    (call-next-method)
-    ))
+    (call-next-method)))
 
 (provide 'srecode/insert)
 
index af96037944b5824162e90eb879237859488a8b80..3a833ca8bb3bad2bbd9a480aff5f60908afd1b80 100644 (file)
@@ -295,8 +295,14 @@ if that file is NEW, otherwise assume the mode has not changed."
 
     ;; 2) Do we not have a current map?  If so load.
     (when (not srecode-current-map)
-      (setq srecode-current-map
-           (eieio-persistent-read srecode-map-save-file))
+      (condition-case nil
+         (setq srecode-current-map
+               (eieio-persistent-read srecode-map-save-file))
+       (error
+        ;; There was an error loading the old map.  Create a new one.
+        (setq srecode-current-map
+              (srecode-map "SRecode Map"
+                           :file srecode-map-save-file))))
       )
 
     )
index f588eed2bb14c42698f77f744e87141cc7d46df1..3f286c961176e90e6e093a18b3372d0e89b070db 100644 (file)
      ["Dump Dictionary"
       srecode-dictionary-dump
       :active t
-      :help "Calculate a dump a dictionary for point."
+      :help "Calculate and dump a dictionary for point."
+      ])
+    (semantic-menu-item
+     ["Show Macro Help"
+      srecode-macro-help
+      :active t
+      :help "Display the different types of macros available."
       ])
     )
    )
@@ -223,43 +229,44 @@ MENU-DEF is the menu to bind this into."
       (setq context (car-safe (srecode-calculate-context)))
 
       (while subtab
-       (setq ltab (oref (car subtab) templates))
-       (while ltab
-         (setq temp (car ltab))
-
-         ;; Do something with this template.
-
-         (let* ((ctxt (oref temp context))
-                (ctxtcons (assoc ctxt alltabs))
-                (bind (if (slot-boundp temp 'binding)
-                          (oref temp binding)))
-                (name (object-name-string temp)))
-
-           (when (not ctxtcons)
-             (if (string= context ctxt)
-                 ;; If this context is not in the current list of contexts
-                 ;; is equal to the current context, then manage the
-                 ;; active list instead
-                 (setq active
-                       (setq ctxtcons (or active (cons ctxt nil))))
-               ;; This is not an active context, add it to alltabs.
-               (setq ctxtcons (cons ctxt nil))
-               (setq alltabs (cons ctxtcons alltabs))))
-
-           (let ((new (vector
-                       (if bind
-                           (concat name "   (" bind ")")
-                         name)
-                       `(lambda () (interactive)
-                          (srecode-insert (concat ,ctxt ":" ,name)))
-                       t)))
-
-             (setcdr ctxtcons (cons
-                               new
-                               (cdr ctxtcons)))))
-
-         (setq ltab (cdr ltab)))
-       (setq subtab (cdr subtab)))
+       (when (srecode-template-table-in-project-p (car subtab))
+         (setq ltab (oref (car subtab) templates))
+         (while ltab
+           (setq temp (car ltab))
+
+           ;; Do something with this template.
+
+           (let* ((ctxt (oref temp context))
+                  (ctxtcons (assoc ctxt alltabs))
+                  (bind (if (slot-boundp temp 'binding)
+                            (oref temp binding)))
+                  (name (object-name-string temp)))
+
+             (when (not ctxtcons)
+               (if (string= context ctxt)
+                   ;; If this context is not in the current list of contexts
+                   ;; is equal to the current context, then manage the
+                   ;; active list instead
+                   (setq active
+                         (setq ctxtcons (or active (cons ctxt nil))))
+                 ;; This is not an active context, add it to alltabs.
+                 (setq ctxtcons (cons ctxt nil))
+                 (setq alltabs (cons ctxtcons alltabs))))
+
+             (let ((new (vector
+                         (if bind
+                             (concat name "   (" bind ")")
+                           name)
+                         `(lambda () (interactive)
+                            (srecode-insert (concat ,ctxt ":" ,name)))
+                         t)))
+
+               (setcdr ctxtcons (cons
+                                 new
+                                 (cdr ctxtcons)))))
+
+           (setq ltab (cdr ltab))))
+       (setq subtab (cdr subtab)))
 
       ;; Now create the menu
       (easy-menu-filter-return
@@ -300,6 +307,7 @@ MENU-DEF is the menu to bind this into."
 This command will insert whichever srecode template has a binding
 to the current key."
   (interactive)
+  (srecode-load-tables-for-mode major-mode)
   (let* ((k last-command-event)
         (ctxt (srecode-calculate-context))
         ;; Find the template with the binding K
index ae96b86a9bcf26d0dd193b86a1d111d07831c7f7..fd8419add6707e06510c0ab82214591033fddbe1 100644 (file)
@@ -91,7 +91,7 @@ The hook is called with two arguments, the TAG and DICT
 to be augmented.")
 
 (define-overload srecode-semantic-apply-tag-to-dict (tagobj dict)
-  "Insert fewatures of TAGOBJ into the dictionary DICT.
+  "Insert features of TAGOBJ into the dictionary DICT.
 TAGOBJ is an object of class `srecode-semantic-tag'.  This class
 is a compound inserter value.
 DICT is a dictionary object.
@@ -195,7 +195,7 @@ variable default values, and other things."
 ;;; :tag ARGUMENT HANDLING
 ;;
 ;; When a :tag argument is required, identify the current :tag,
-;; and apply it's parts into the dictionary.
+;; and apply its parts into the dictionary.
 (defun srecode-semantic-handle-:tag (dict)
   "Add macros into the dictionary DICT based on the current :tag."
   ;; We have a tag, start adding "stuff" into the dictionary.
@@ -305,8 +305,8 @@ or `code'.
 
 For various conditions, this function looks for a template with
 the name CLASS-tag, where CLASS is the tag class.  If it cannot
-find that, it will look for that template in the
-`declaration'context (if the current context was not `declaration').
+find that, it will look for that template in the `declaration'
+context (if the current context was not `declaration').
 
 If PROTOTYPE is specified, it will first look for templates with
 the name CLASS-tag-prototype, or CLASS-prototype as above.
@@ -382,7 +382,7 @@ as `function' will leave point where code might be inserted."
       (error "Cannot find template %s in %s for inserting tag %S"
             errtype top (semantic-format-tag-summarize tag)))
 
-    ;; Resolve Arguments
+    ;; Resolve arguments
     (let ((srecode-semantic-selected-tag tag))
       (srecode-resolve-arguments temp dict))
 
index 3d22922d55160b9faf491d3696f92b2f50e61ba7..2c95d4f64129980913c9dc918b45048a1b33c978 100644 (file)
@@ -31,6 +31,7 @@
 (require 'srecode)
 
 (declare-function srecode-load-tables-for-mode "srecode/find")
+(declare-function srecode-template-table-in-project-p "srecode/find")
 
 ;;; Code:
 
@@ -74,6 +75,12 @@ Emacs Lisp code to fill in the dictionary.")
 When there are multiple template files with similar names, templates with
 the highest priority are scanned last, allowing them to override values in
 previous template files.")
+   (project :initarg :project
+           :type (or null string)
+           :documentation
+           "Scope some project files to a specific project.
+The value is a directory which forms the root of a particular project,
+or a subset of a particular project.")
    ;;
    ;; Parsed Data from the template file
    ;;
@@ -224,6 +231,12 @@ Use PREDICATE is the same as for the `sort' function."
   (when (oref tab :application)
     (princ "\nApplication: ")
     (princ (oref tab :application)))
+  (when (oref tab :project)
+    (require 'srecode/find) ; For srecode-template-table-in-project-p
+    (princ "\nProject Directory: ")
+    (princ (oref tab :project))
+    (when (not (srecode-template-table-in-project-p tab))
+      (princ "\n   ** Not Usable in this file. **")))
   (princ "\n\nVariables:\n")
   (let ((vars (oref tab variables)))
     (while vars
index 2c8d1a7204c51a686343c51099d16e7882901af0..30ba91cadf964682f185c919a2cdb0d1ac04e27e 100644 (file)
@@ -175,10 +175,17 @@ Adds the following:
 
 (define-mode-local-override semantic-insert-foreign-tag
   texinfo-mode (foreign-tag)
-  "Insert TAG from a foreign buffer in TAGFILE.
+  "Insert FOREIGN-TAG from a foreign buffer in TAGFILE.
 Assume TAGFILE is a source buffer, and create a documentation
 thingy from it using the `document' tool."
-  (let ((srecode-semantic-selected-tag foreign-tag))
+  (srecode-texi-insert-tag-as-doc foreign-tag))
+
+(defun srecode-texi-insert-tag-as-doc (tag)
+  "Insert TAG into the current buffer with SRecode."
+  (when (not (eq major-mode 'texinfo-mode))
+    (error "Can only insert tags into texinfo in texinfo mode"))
+  (let ((srecode-semantic-selected-tag tag))
+    (srecode-load-tables-for-mode major-mode)
     ;; @todo - choose of the many types of tags to insert,
     ;; or put all that logic into srecode.
     (srecode-insert "declaration:function")))