+2012-10-01 David Engster <deng@randomsample.de>
+
+ * grammars/bovine-grammar.el (bovine--grammar-newstyle-unquote):
+ Remove.
+ (bovine-grammar-expand-form): Test for emacs-major-version.
+
+ * grammars/c.by: Add EXPLICIT to keyword tokens.
+
+ * grammars/f90.by: Add %provide token.
+
+ * grammar/grammar.wy (semantic-grammar-lexer): Remove, since it
+ was copied to grammar.el. New %provide token to generate prefix
+ which conforms with Emacs conventions. Remove lexer definition,
+ which is now in grammar.el.
+
2012-09-27 Glenn Morris <rgm@gnu.org>
* admin.el (set-version): Set msdos.c's Vwindow_system_version.
;; Cache of macro definitions currently in use.
(defvar bovine--grammar-macros nil)
-;; Detect if we have an Emacs with newstyle unquotes allowed outside
-;; of backquote.
-;; This should probably be changed to a test to (= emacs-major-version 24)
-;; when it is released, but at the moment it might be possible that people
-;; are using an older snapshot.
-(defvar bovine--grammar-newstyle-unquote
- (equal '(\, test) (read ",test")))
-
(defun bovine-grammar-expand-form (form quotemode &optional inplace)
"Expand FORM into a new one suitable to the bovine parser.
FORM is a list in which we are substituting.
form (cdr form))
;; Hack for dealing with new reading of unquotes outside of
;; backquote (introduced in rev. 102591 in emacs-bzr).
- (when (and bovine--grammar-newstyle-unquote
+ (when (and (>= emacs-major-version 24)
(listp first)
(or (equal (car first) '\,)
(equal (car first) '\,@)))
(defun bovine-make-parsers ()
"Generate Emacs' built-in Bovine-based parser files."
+ (interactive)
(semantic-mode 1)
;; Loop through each .by file in current directory, and run
;; `semantic-grammar-batch-build-one-package' to build the grammar.
(with-current-buffer (find-file-noselect f)
(semantic-grammar-create-package))
(error (message "%s" (error-message-string err)) nil)))
- lang)
+ lang filename)
(when (and packagename
- (string-match "^semantic-\\(.*\\)-by\\.el\\'" packagename))
+ (string-match "^.*/\\(.*\\)-by\\.el\\'" packagename))
(setq lang (match-string 1 packagename))
+ (setq filename (concat lang "-by.el"))
(with-temp-buffer
- (insert-file-contents packagename)
- (setq buffer-file-name (expand-file-name packagename))
+ (insert-file-contents filename)
+ (setq buffer-file-name (expand-file-name filename))
;; Fix copyright header:
(goto-char (point-min))
(re-search-forward "^;; Author:")
lang ".by.
;;; Code:
-
-\(require 'semantic/lex)
-\(eval-when-compile (require 'semantic/bovine))\n")
+")
(goto-char (point-min))
(delete-region (point-min) (line-end-position))
- (insert ";;; semantic/bovine/" lang
- "-by.el --- Generated parser support file")
+ (insert ";;; " packagename
+ " --- Generated parser support file")
(delete-trailing-whitespace)
- ;; Fix footer:
- (goto-char (point-max))
- (re-search-backward ".\n;;; Analyzers")
- (delete-region (point) (point-max))
- (insert "(provide 'semantic/bovine/" lang "-by)\n\n")
- (insert ";;; semantic/bovine/" lang "-by.el ends here\n")
+ (re-search-forward ";;; \\(.*\\) ends here")
+ (replace-match packagename nil nil nil 1)
(save-buffer))))))
;;; bovine-grammar.el ends here
;;; c.by -- LL grammar for C/C++ language specification
-
;; Copyright (C) 1999-2012 Free Software Foundation, Inc.
;;
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; > * Can't parse signature element: "RmcBucStatus* rftBucStatus"
%package semantic-c-by
+%provide semantic/bovine/c-by
+
+%{
+(declare-function semantic-c-reconstitute-token "semantic/bovine/c")
+(declare-function semantic-c-reconstitute-template "semantic/bovine/c")
+(declare-function semantic-expand-c-tag "semantic/bovine/c")
+}
%languagemode c-mode c++-mode
%start declaration
%put VIRTUAL summary "Method Modifier: virtual <type> <name>(...) ..."
%token MUTABLE "mutable"
%put MUTABLE summary "Member Declaration Modifier: mutable <type> <name> ..."
+%token EXPLICIT "explicit"
+%put EXPLICIT summary "Forbids implicit type conversion: explicit <constructor>"
%token STRUCT "struct"
%put STRUCT summary "Structure Type Declaration: struct [name] { ... };"
;; PUBLIC or PRIVATE bits. Ignore them for now.
| template
| using
+ ;; Includes inside namespaces
+ | spp-include
+ (TAG $1 'include :inside-ns t)
| ;;EMPTY
;
function-pointer
: LPAREN STAR symbol RPAREN
( (concat "*" $3) )
+ | LPAREN symbol RPAREN
+ ( $2 )
;
fun-or-proto-end
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
+%package semantic-grammar-wy
+%provide semantic/grammar-wy
+
%{
(defvar semantic-grammar-lex-c-char-re)
(defvar semantic-grammar-wy--rindx nil)
}
-%package semantic-grammar-wy
-
%languagemode wy-mode
;; Main
%keyword LEFT "%left"
%keyword NONASSOC "%nonassoc"
%keyword PACKAGE "%package"
+%keyword PROVIDE "%provide"
%keyword PREC "%prec"
%keyword PUT "%put"
%keyword QUOTEMODE "%quotemode"
| no_default_prec_decl
| languagemode_decl
| package_decl
+ | provide_decl
| precedence_decl
| put_decl
| quotemode_decl
`(PACKAGE-TAG ',$2 nil)
;
+provide_decl:
+ PROVIDE SYMBOL
+ `(TAG ',$2 'provide)
+ ;
+
precedence_decl:
associativity token_type_opt items
`(TAG ',$1 'assoc :type ',$2 :value ',$3)
;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
%package wisent-java-tags-wy
+%provide semantic/wisent/javat-wy
%languagemode java-mode
;;; Type Declaration token
;; ("NAME" type "TYPE" ( PART-LIST ) ( PARENTS ) EXTRA-SPEC "DOCSTRING")
interface_declaration
- : modifiers_opt INTERFACE IDENTIFIER extends_interfaces_opt interface_body
+ : modifiers_opt INTERFACE qualified_name extends_interfaces_opt interface_body
(TYPE-TAG $3 $2 $5 (if $4 (cons nil $4)) :typemodifiers $1)
;
;;; Variable token
;; ("NAME" variable "TYPE" DEFAULT-VALUE EXTRA-SPEC "DOCSTRING")
formal_parameter
- : formal_parameter_modifier_opt type variable_declarator_id
+ : formal_parameter_modifier_opt type opt_variable_declarator_id
(VARIABLE-TAG $3 $2 nil :typemodifiers $1)
;
(cons $1 $region)
;
+opt_variable_declarator_id
+ : ;; EMPTY
+ (identity "")
+ | variable_declarator_id
+ (identity $1)
+ ;
+
variable_declarator_id
: IDENTIFIER dims_opt
(concat $1 $2)
;; DAMAGE.
%package wisent-javascript-jv-wy
+%provide semantic/wisent/js-wy
;; JAVE I prefere ecmascript-mode
%languagemode ecmascript-mode javascript-mode
;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
%package semantic-make-by
+%provide semantic/bovine/make-by
%languagemode makefile-mode
%start Makefile
;; --------
%package wisent-python-wy
+%provide semantic/wisent/python-wy
+
+%{
+(declare-function wisent-python-reconstitute-function-tag "semantic/wisent/python")
+(declare-function wisent-python-reconstitute-class-tag "semantic/wisent/python")
+}
%languagemode python-mode
%token <punctuation> COMMA ","
%token <punctuation> ASSIGN "="
%token <punctuation> BACKQUOTE "`"
+%token <punctuation> AT "@"
;; -----------------
%put WHILE summary
"Start a 'while' loop"
+%keyword WITH "with"
+%put WITH summary
+"Start statement with an associated context object"
+
%keyword YIELD "yield"
%put YIELD summary
"Create a generator function"
;; dotted_as_name (',' dotted_as_name)*
dotted_as_name_list
- : dotted_as_name
- | dotted_as_name_list COMMA dotted_as_name
+ : dotted_as_name_list COMMA dotted_as_name
+ (cons $3 $1)
+ | dotted_as_name
+ (list $1)
;
;; ('*' | import_as_name (',' import_as_name)*)
| while_stmt
| for_stmt
| try_stmt
+ | with_stmt
| funcdef
| class_declaration
;
()
;
+;;;============================================================================
+;;@@ with_stmt
+;;;============================================================================
+
+;; with_stmt: 'with' test [ with_var ] ':' suite
+with_stmt
+ : WITH test COLON suite
+ (CODE-TAG $1 nil)
+ | WITH test with_var COLON suite
+ (CODE-TAG $1 nil) ;; TODO capture variable
+ ;
+
+with_var
+ : AS expr
+ () ;; TODO capture
+ ;
+
;;;============================================================================
;;;@@ funcdef
;;;============================================================================
-;; funcdef: 'def' NAME parameters ':' suite
+decorator
+ : AT dotted_name varargslist_opt NEWLINE
+ (FUNCTION-TAG $2 "decorator" $3)
+ ;
+
+decorators
+ : decorator
+ (list $1)
+ | decorator decorators
+ (cons $1 $2)
+ ;
+
+;; funcdef: [decorators] 'def' NAME parameters ':' suite
funcdef
: DEF NAME function_parameter_list COLON suite
- (FUNCTION-TAG $2 nil $3)
+ (wisent-python-reconstitute-function-tag
+ (FUNCTION-TAG $2 nil $3) $5)
+ | decorators DEF NAME function_parameter_list COLON suite
+ (wisent-python-reconstitute-function-tag
+ (FUNCTION-TAG $3 nil $4 :decorators $1) $6)
;
function_parameter_list
;; classdef: 'class' NAME ['(' testlist ')'] ':' suite
class_declaration
: CLASS NAME paren_class_list_opt COLON suite
- (TYPE-TAG $2 $1 ;; Name "class"
- $5 ;; Members
- (cons $3 nil) ;; (SUPERCLASSES . INTERFACES)
- )
+ (wisent-python-reconstitute-class-tag
+ (TYPE-TAG $2 $1 ;; Name "class"
+ $5 ;; Members
+ (cons $3 nil) ;; (SUPERCLASSES . INTERFACES)
+ ))
;
;; ['(' testlist ')']
;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
%package semantic-scm-by
+%provide semantic/bovine/scm-by
%languagemode scheme-mode
%start scheme
;; Semantic Recoder templates are based on Google Templates
;; and are at the bottom of the Semantic Recoder API.
+%package srecode-template-wy
+%provide srecode/srt-wy
+
%languagemode srecode-mode
%start template_file
%put TEMPLATE summary "template <name>\\n <template definition>"
%keyword SECTIONDICTIONARY "sectiondictionary"
%put SECTIONDICTIONARY summary "sectiondictionary <name>\\n <dictionary entries>"
+
+%keyword SECTION "section"
+%put SECTION summary
+ "section <name>\\n <dictionary entries>\\n end"
+
+%keyword END "end"
+%put END summary
+ "section ... end"
+
%keyword PROMPT "prompt"
%keyword DEFAULT "default"
%keyword DEFAULTMACRO "defaultmacro"
%token <separator> TEMPLATE_BLOCK "^----"
;;; Bland default types
-%type <property> ":\\(\\w\\|\\s_\\)*"
+%type <property> syntax ":\\(\\w\\|\\s_\\)*"
%token <property> property
%type <symbol>
template
: TEMPLATE templatename opt-dynamic-arguments newline
opt-string
- opt-section-dictionaries
+ section-dictionary-list
TEMPLATE_BLOCK newline
opt-bind
(FUNCTION-TAG $2 nil $3 :documentation $5 :code $7
| ()
;
-opt-section-dictionaries
- : () ;; EMPTY
- | section-dictionary-list
- ;
-
section-dictionary-list
- : one-section-dictionary
- (list $1)
- | section-dictionary-list one-section-dictionary
+ : ;; empty
+ ()
+ | section-dictionary-list flat-section-dictionary
+ (append $1 (list $2))
+ | section-dictionary-list section-dictionary
(append $1 (list $2))
;
-one-section-dictionary
+flat-section-dictionary
: SECTIONDICTIONARY string newline
- variable-list
+ flat-dictionary-entry-list
+ (cons (read $2) $4)
+ ;
+
+flat-dictionary-entry-list
+ : ;; empty
+ ()
+ | flat-dictionary-entry-list flat-dictionary-entry
+ (append $1 $2)
+ ;
+
+flat-dictionary-entry
+ : variable
+ (EXPANDTAG $1)
+ ;
+
+section-dictionary
+ : SECTION string newline
+ dictionary-entry-list
+ END newline
(cons (read $2) $4)
;
-variable-list
+dictionary-entry-list
+ : ;; emtpy
+ ()
+ | dictionary-entry-list dictionary-entry
+ (append $1 $2)
+ ;
+
+dictionary-entry
: variable
(EXPANDTAG $1)
- | variable-list variable
- (append $1 (EXPANDTAG $2))
+ | section-dictionary
+ (list $1)
;
opt-bind
semantic-lex-default-action
)
-;;; wisent-dot.wy ends here
+;;; srecode-template.wy ends here
"Return the list of terminal symbols.
Keep order of declaration in the WY file without duplicates."
(let (terms)
- (mapcar
+ (mapc
#'(lambda (tag)
- (mapcar #'(lambda (name)
- (add-to-list 'terms (intern name)))
- (cons (semantic-tag-name tag)
- (semantic-tag-get-attribute tag :rest))))
+ (mapcar #'(lambda (name)
+ (add-to-list 'terms (intern name)))
+ (cons (semantic-tag-name tag)
+ (semantic-tag-get-attribute tag :rest))))
(semantic--find-tags-by-function
#'(lambda (tag)
- (memq (semantic-tag-class tag) '(token keyword)))
+ (memq (semantic-tag-class tag) '(token keyword)))
(current-buffer)))
(nreverse terms)))
;; DAMAGE.")
(defvar wisent-make-parsers--parser-file-name
- `(("semantic-grammar-wy.el"
- "semantic/grammar-wy")
- ("srecode-template-wy.el"
- "srecode/srt-wy")
- ("wisent-javascript-jv-wy.el"
- "semantic/wisent/js-wy"
+ `(("semantic/grammar-wy.el")
+ ("srecode/srt-wy.el")
+ ("semantic/wisent/js-wy.el"
"Copyright (C) 1998-2011 Ecma International."
,wisent-make-parsers--ecmascript-license)
- ("wisent-java-tags-wy.el"
- "semantic/wisent/javat-wy")
- ("wisent-python-wy.el"
- "semantic/wisent/python-wy"
- "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Python Software Foundation; All Rights Reserved."
+ ("semantic/wisent/javat-wy.el")
+ ("semantic/wisent/python-wy.el"
+ "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
+\;; 2009, 2010 Python Software Foundation; All Rights Reserved"
,wisent-make-parsers--python-license)))
(defun wisent-make-parsers ()
"Generate Emacs' built-in Wisent-based parser files."
+ (interactive)
(semantic-mode 1)
;; Loop through each .wy file in current directory, and run
;; `semantic-grammar-batch-build-one-package' to build the grammar.
(error (message "%s" (error-message-string err)) nil)))
output-data)
(when (setq output-data (assoc packagename wisent-make-parsers--parser-file-name))
- (let ((require-name (nth 1 output-data))
- (additional-copyright (nth 2 output-data))
- (additional-license (nth 3 output-data))
+ (let ((additional-copyright (nth 1 output-data))
+ (additional-license (nth 2 output-data))
+ (filename (progn (string-match ".*/\\(.*\\)" packagename) (match-string 1 packagename)))
copyright-end)
;; Touch up the generated parsers for Emacs integration.
(with-temp-buffer
- (insert-file-contents packagename)
+ (insert-file-contents filename)
;; Fix copyright header:
(goto-char (point-min))
- (when additional-copyright
+ (when additional-copyright
(re-search-forward "Copyright (C).*$")
(insert "\n;; " additional-copyright))
(re-search-forward "^;; Author:")
f ".")
(when additional-license
(insert "\n" additional-license))
- (insert "\n\n;;; Code:\n
-\(require 'semantic/lex)\n")
+ (insert "\n\n;;; Code:\n")
(goto-char (point-min))
(delete-region (point-min) (line-end-position))
- (insert ";;; " require-name
- ".el --- Generated parser support file")
+ (insert ";;; " packagename
+ " --- Generated parser support file")
+ (re-search-forward ";;; \\(.*\\) ends here")
+ (replace-match packagename nil nil nil 1)
(delete-trailing-whitespace)
- (re-search-forward ";;\n(require 'semantic/lex)\n")
- (delete-region (match-beginning 0) (match-end 0))
- ;; Fix footer:
- (goto-char (point-max))
- (re-search-backward "^(provide")
- (delete-region (match-beginning 0) (point-max))
- (goto-char (point-max))
- (insert "(provide '" require-name ")\n\n")
- (insert ";;; " require-name ".el ends here\n")
- (write-region nil nil (expand-file-name packagename))))))))
+ (write-region nil nil (expand-file-name filename))))))))
;;; wisent-grammar.el ends here
+2012-10-01 Eric Ludlam <zappo@gnu.org>
+
+ * ede.texi (Quick Start, Project Local Variables)
+ (Miscellaneous commands, ede-java-root, Development Overview)
+ (Detecting a Project): New nodes.
+ (Simple projects): Node deleted.
+
+ * eieio.texi (Building Classes): Some slot attributes cannot be
+ overridden.
+ (Slot Options): Remove an example.
+ (Method Invocation, Documentation): New nodes.
+
2012-10-01 Glenn Morris <rgm@gnu.org>
* Makefile.in ($(buildinfodir)/reftex$(INFO_EXT)), reftex.dvi)
@menu
* EDE Project Concepts:: @ede{} Project Concepts
* EDE Mode:: Turning on @ede{} mode.
+* Quick Start:: Quick start to building a project.
* Creating a project:: Creating a project.
* Modifying your project:: Adding and removing files and targets.
* Building and Debugging:: Initiating a build or debug session.
* Miscellaneous commands:: Other project related commands.
-* Simple projects:: Projects not managed by @ede{}.
* Extending EDE:: Programming and extending @ede{}.
@end menu
documentation or interface files. @ede{} can provide this
information.
-@node EDE Mode, Creating a project, EDE Project Concepts, top
+@node EDE Mode, Quick Start, EDE Project Concepts, top
@chapter @ede{} Mode
@ede{} is implemented as a minor mode, which augments other modes such
commands. These menu items, and their corresponding keybindings, are
independent of the type of project you are actually working on.
-@node Creating a project, Modifying your project, EDE Mode, top
+@node Quick Start, Creating a project, EDE Mode, top
+@chapter Quick Start
+
+Once you have @ede{} enabled, you can create a project. This chapter
+provides an example C++ project that will create Automake files for
+compilation.
+
+@section Step 1: Create root directory
+
+First, lets create a directory for our project. For this example,
+we'll start with something in @file{/tmp}.
+
+@example
+C-x C-f /tmp/myproject/README RET
+M-x make-directory RET RET
+@end example
+
+Now put some plain text in your README file to start.
+
+Now, lets create the project:
+
+@example
+M-x ede-new RET Automake RET myproject RET
+@end example
+
+
+Nothing visible happened, but if you use @code{dired} to look at the
+directory, you should see this:
+
+@example
+ /tmp/myproject:
+ total used in directory 32 available 166643476
+ drwxr-xr-x 2 zappo users 4096 2012-02-23 22:10 .
+ drwxrwxrwt 73 root root 20480 2012-02-23 22:10 ..
+ -rw-r--r-- 1 zappo users 195 2012-02-23 22:10 Project.ede
+ -rw-r--r-- 1 zappo users 10 2012-02-23 22:09 README
+@end example
+
+@section Step 2: Create Subdirectories and Files
+
+We'll make a more complex project, so use dired to create some more
+directories using the @kbd{+} key, and typing in new directories:
+
+@example
++ include RET
++ src RET
+@end example
+
+Now I'll short-cut in this tutorial. Create the following files:
+
+@file{include/myproj.hh}
+@example
+/** myproj.hh ---
+ */
+
+#ifndef myproj_hh
+#define myproj_hh 1
+
+#define IMPORTANT_MACRO 1
+
+int my_lib_function();
+
+#endif // myproj_hh
+@end example
+
+
+@file{src/main.cpp}
+@example
+/** main.cpp ---
+ */
+
+#include <iostream>
+#include "myproj.hh"
+
+int main() @{
+
+@}
+
+#ifdef IMPORTANT_MACRO
+int my_fcn() @{
+
+@}
+#endif
+@end example
+
+@file{src/mylib.cpp}
+@example
+/** mylib.cpp ---
+ *
+ * Shared Library to build
+ */
+
+int my_lib_function() @{
+
+@}
+@end example
+
+@section Step 3: Create subprojects
+
+@ede{} needs subdirectories to also have projects in them. You can
+now create those projects.
+
+With @file{main.cpp} as your current buffer, type:
+
+@example
+M-x ede-new RET Automake RET src RET
+@end example
+
+and in @file{myproj.hh} as your current buffer, type:
+
+@example
+M-x ede-new RET Automake RET include RET
+@end example
+
+These steps effectively only create the Project.ede file in which you
+will start adding targets.
+
+@section Step 4: Create targets
+
+In order to build a program, you must have targets in your @ede{}
+Projects. You can create targets either from a buffer, or from a
+@code{dired} directory buffer.
+
+Note: If for some reason a directory list buffer, or file does not have the
+@samp{Project} menu item, or if @ede{} keybindings don't work, just
+use @kbd{M-x revert-buffer RET} to force a refresh. Sometimes
+creating a new project doesn't restart buffers correctly.
+
+Lets start with the header file. In @file{include/myproj.hh}, you
+could use the menu, but we will now start using the @ede{} command prefix
+which is @kbd{C-c .}.
+
+@example
+C-c . t includes RET miscellaneous RET y
+@end example
+
+
+This creates a misc target for holding your includes, and then adds
+myproj.hh to the target. Automake (the tool) has better ways to do
+this, but for this project, it is sufficient.
+
+Next, visit the @file{src} directory using dired. There should be a
+@samp{Project} menu. You can create a new target with
+
+@example
+. t myprogram RET program RET
+@end example
+
+Note that @kbd{. t} is a command for creating a target. This command
+is also in the menu. This will create a target that will build a
+program. If you want, visit @file{Project.ede} to see the structure
+built so far.
+
+Next, place the cursor on @file{main.cpp}, and use @kbd{. a} to add
+that file to your target.
+
+@example
+. a myprogram RET
+@end example
+
+Note that these promps often have completion, so you can just press
+@kbd{TAB} to complete the name @file{myprogram}.
+
+If you had many files to add to the same target, you could mark them
+all in your dired buffer, and add them all at the same time.
+
+Next, do the same for the library by placing the cursor on @file{mylib.cpp}.
+
+@example
+. t mylib RET sharedobject RET
+. a mylib RET
+@end example
+
+@section Step 5: Compile, and fail
+
+Next, we'll try to compile the project, but we aren't done yet, so it
+won't work right away.
+
+Visit @file{/tmp/myproject/Project.ede}. We're starting here because
+we don't have any program files in this directory yet. Now we can use
+the compile command:
+
+@example
+C-c . C
+@end example
+
+Because this is the very first time, it will create a bunch of files
+for you that are required by Automake. It will then use automake to
+build the support infrastructure it needs. This step is skipped if
+you choose just a @file{Makefile} build system.
+
+After the Automake init, it runs compile. You will immediately
+discover the error in main.cpp can't find @file{myproj.hh}. We need
+to go fix this.
+
+@section Step 6: Customizing your project
+
+To fix the failed compile, we need to add
+@file{/tmp/myproject/include} to the include path.
+
+Visit @file{main.cpp}.
+
+@example
+M-x customize-project RET
+@end example
+
+Select the @samp{[Settings]} subgroup of options. Under
+@samp{Variable :} click @samp{[INS]}. At this point, you need to be
+somewhat savvy with Automake. Add a variable named @samp{CPPFLAGS},
+and set the value to @samp{../include}.
+
+You should see something like this:
+
+@example
+Variables :
+[INS] [DEL] Cons-cell:
+ Name: AM_CPPFLAGS
+ Value: -I../include
+[INS]
+Variables to set in this Makefile.
+@end example
+
+Click @samp{[Apply]}. Feel free to visit @file{Project.ede} to see
+how it changed the config file.
+
+Compile the whole project again with @kbd{C-c . C} from
+@file{main.cpp}. It should now compile.
+
+@section Step 7: Shared library dependency
+
+Note: Supporting shared libraries for Automake in this way is easy,
+but doing so from a project of type Makefile is a bit tricky. If you
+are creating shared libraries too, stick to Automake projects.
+
+Next, lets add a dependency from @file{main.cpp} on our shared
+library. To do that, update main like this:
+
+@example
+int main() @{
+
+ my_lib_function();
+
+@}
+@end example
+
+Now compile with:
+
+@example
+C-c . c
+@end example
+
+where the lower case @kbd{c} compiles just that target. You should
+see an error.
+
+This time, we need to add a dependency from @file{main.cpp} on our shared
+library. To do that, we need to customize our target instead of the
+project. This is because variables such as the include path are
+treated globally, whereas dependencies for a target are target specific.
+
+@example
+M-x customize-target RET
+@end example
+
+On the first page, you will see an Ldlibs-local section. Add mylib to
+it by first clicking @samp{[INS]}, and they adding the library. It
+should look like this:
+
+@example
+Ldlibs-Local :
+[INS] [DEL] Local Library: libmylib.la
+[INS]
+Libraries that are part of this project. [Hide Rest]
+The full path to these libraries should be specified, such as:
+../lib/libMylib.la or ../ar/myArchive.a
+@end example
+
+You will also see other variables for library related flags and system
+libraries if you need them. Click @samp{[Accept]}, and from
+@file{main.cpp}, again compile the whole project to force all
+dependent elements to compile:
+
+@example
+C-c . C
+@end example
+
+@section Step 8: Run your program
+
+You can run your program directly from @ede{}.
+
+@example
+C-c . R RET RET
+@end example
+
+If your program takes command line arguments, you can type them in
+when it offers the command line you want to use to run your program.
+
+@node Creating a project, Modifying your project, Quick Start, top
@chapter Creating a project
To create a new project, first visit a file that you want to include
* Add/Remove target::
* Add/Remove files::
* Customize Features::
+* Project Local Variables::
* EDE Project Features::
@end menu
You can customize this behavior with the variable
@command{ede-auto-add-method}.
-@node Customize Features, EDE Project Features, Add/Remove files, Modifying your project
+@node Customize Features, Project Local Variables, Add/Remove files, Modifying your project
@section Customize Features
A project, and its targets, are objects using the @samp{EIEIO} object
(@code{ede-edit-file-target}). You should ``rescan'' the project
afterwards (@pxref{Miscellaneous commands}).
-@node EDE Project Features, , Customize Features, Modifying your project
+@node Project Local Variables, EDE Project Features, Customize Features, Modifying your project
+@section Project Local Variables
+
+EDE projects can store and manager project local variables. The
+variables are stored in the project, and will be restored when a
+project reloads.
+
+Projects which are not stored on disk WILL NOT restore your project
+local variables later.
+
+You can use @ref{Customize Features} to of the project to edit the
+project local variables. They are under the 'Settings' group as
+``Project Local Variables''.
+
+You can also use @kbd{M-x ede-set} to set a new variable local in the
+mini buffer.
+
+In multi-level projects such as Automake and Make generating projects,
+project local variables are installed from both the TOP most project,
+and the local directory's project. In that way, you can have some
+variables across your whole project, and some specific to a
+subdirectory.
+
+You can use project local variables to set any Emacs variable so that
+buffers belonging to different projects can have different settings.
+
+NOTE: When you use project-local variables with @ref{ede-cpp-root},
+the format is an association list. For example:
+
+@example
+(ede-cpp-root-project "SOMENAME"
+ :file "/dir/to/some/file"
+ :local-variables
+ '((grep-command . "grep -nHi -e ")
+ (compile-command . "make -f MyCustomMakefile all")))
+@end example
+
+The same is true when you use project-local variables with
+@ref{ede-java-root}. For example:
+
+@example
+(ede-java-root-project "SOMENAME"
+ :file "/dir/to/some/file"
+ :local-variables
+ '((grep-command . "grep -nHi -e ")
+ (compile-command . "ant")))
+@end example
+
+@node EDE Project Features, , Project Local Variables, Modifying your project
@section EDE Project Features
This section details user facing features of an @ede{} @samp{Make}
These commands are also available from the @samp{Development} menu.
-@node Miscellaneous commands, Simple projects, Building and Debugging, top
+@node Miscellaneous commands, Extending EDE, Building and Debugging, top
@chapter Miscellaneous commands
If you opt to go in and edit @ede{} project files directly---for
To activate the speedbar in this mode, type @kbd{C-c . s}
(@code{ede-speedbar}).
-@node Simple projects, Extending EDE, Miscellaneous commands, top
+@menu
+* Make and Automake projects:: Project types of @samp{ede-project}
+* Automake direct projects:: Project interface on hand-written automake files.
+* Android projects:: Projects for Android development
+* Arduino projects:: Projects for Arduino sketches
+* Simple projects:: Projects @ede{} doesn't manage.
+@end menu
+
+@node Make and Automake projects
+@section Make and Automake projects
+
+A project of @samp{ede-project} type creates a file called
+@file{Project.ede} in every project directory. This is used to track
+your configuration information. If you configure this project to be
+in @samp{Makefile} mode, then this project will autogenerate a
+@file{Makefile}. If you configure it in @samp{Automake} mode a
+@file{Makefile.am} file will be created. The automake bootstrapping
+routines will also import and maintain a configure.am script and a
+host of other files required by Automake.
+
+@node Automake direct projects
+@section Automake direct projects
+
+The project type that reads @file{Makefile.am} directly is derived
+from the sources of the original @file{project-am.el} mode that was
+distributed independently. This mode eventually became @ede{}. The
+@samp{project-am} project will read existing automake files, but will
+not generate them automatically, or create new ones. As such, it is
+useful as a browsing tool, or as maintenance in managing file lists.
+
+@node Android projects
+@section Android projects
+
+An Android project of type @samp{ede-android-project} will detect and
+support development of Android apps. Android projects use an
+@file{AndroidManifest.xml} file. Always load your Manifest first in a
+running Emacs to make sure the project is identified correctly.
+
+Android projects can be created with @code{ede-new} but depend on a
+correctly configured Android SDK via @cedet{} support.
+
+@defun cedet-android-sdk-root
+@anchor{cedet-android-sdk-root}
+The root to the android @var{SDK}.
+@end defun
+
+Android projects support different configurations including compile,
+and install, which will upload a program to your Android device. It
+also supports several debugging tools via @file{android.el}.
+
+@node Arduino projects
+@section Arduino projects
+
+An arduino project of type @samp{ede-arduino-project} will read your
+@file{~/.arduino/preferences.txt} file, and identify your sketches.
+You will still need the Arduino IDE to set up your preferences and
+locate your arduino. After quiting the IDE, Emacs will be able to
+find your sketches, compile them, and upload them to your arduino.
+
+If you have the @file{arduino} command on your path, @ede{} will be
+able to find your SDK and compile your programs.
+
+@node Simple projects
@section Simple Projects
There is a wide array of Simple projects. The root for simple
lookup for @semantic{}, improving code completion performance.
@menu
-* ede-cpp-root:: This project marks the root of a C/C++ code project.
-* ede-simple subclassing:: Create your own simple project.
-* ede-emacs:: A project for working with Emacs.
-* ede-linux:: A project for working with Linux kernels.
-* Custom Locate:: Customizing how to locate files in a simple project
+* ede-cpp-root:: This project marks the root of a C/C++ code project.
+* ede-java-root:: This project marks the root of a Java project.
+* ede-emacs:: A project for working with Emacs.
+* ede-linux:: A project for working with Linux kernels.
+* Custom Locate:: Customizing how to locate files in a simple project
@end menu
-@node ede-cpp-root
+@node ede-cpp-root, ede-java-root, Simple projects, Simple projects
@subsection ede-cpp-root
The @code{ede-cpp-root} project type allows you to create a single
The directory root for this cpp-root project.
@end table
+When creating a project with @code{ede-cpp-root}, you can get
+additional configurations via @ref{Project Local Variables}. Be aware
+that the format for project local variables is an association list.
+You cannot use @kbd{M-x ede-set} and have your project local variables
+persist between sessions.
If the cpp-root project style is right for you, but you want a dynamic
loader, instead of hard-coding path name values in your @file{.emacs}, you
@xref{ede-cpp-root-project}, for details about the class that defines
the @code{ede-cpp-root} project type.
-@node ede-simple subclassing
-@subsection ede-simple Subclassing
+@node ede-java-root, ede-emacs, ede-cpp-root, Simple projects
+@subsection ede-java-root
+
+Much like the project type @ref{ede-cpp-root}, the java variant is
+can be setup in your @file{.emacs} file and just marks a directory as
+the root of a java source tree.
+
+The @code{ede-java-root} project class knows a few things about Java
+projects. In particular, you can use it to control your classpath at
+both the system level, and for your project. If it is insufficient,
+you can subclass @code{ede-java-root-project} and add your own tweaks
+in just a few lines. See @ref{ede-cpp-root} for an example using the
+C++ variant.
+
+In the most basic case, add this to your @file{.emacs} file, modifying
+appropriate bits as needed.
+
+@example
+(ede-java-root-project "SOMENAME" :file "/dir/to/some/file" :srcroot '("src"))
+@end example
+
+Replace @var{SOMENAME} with whatever name you want, and the filename
+to an actual file at the root of your project. It might be a
+Makefile, a README file. Whatever. It doesn't matter. It's just a
+key to hang the rest of @ede{} off of.
+
+Replace the value of :srcroot with a list of directories under the
+project root which contains Java sources. For example, if you have:
+
+@example
+~/myprojects/P1/
+~/myprojects/P1/src/
+~/myprojects/P1/src/com/ericsoft/MyCode.java
+~/myprojects/P1/doc/
+@end example
+
+Then @file{src} represents the directory under which all your Java
+code is. It is important that @file{src} is one step above the
+directory that is the base of your package name, such as
+@file{com/ericsoft} in the example above so that new files can be
+discovered via fully qualified name. You can have multiple such
+directories in one project, and each will be accessible.
+
+You can specify your classpath like this:
-todo - Write some doc.
+@example
+(ede-java-root-project "NAME" :file "FILENAME"
+ :srcroot '("src")
+ :classpath '("/absolute/path.jar")
+ :localclasspath '( "/relative/path.jar" ))
+@end example
+
+In this example, @code{:classpath} specifies absolute paths somewhere
+on your system, and the explicit jar or source root directories
+@semantic{} will search when performing completions.
+
+The @code{:localclasspath} is like @code{:classpath}, but it will
+contain path names relative to the root of your project.
+
+If you want to override the file-finding tool with your own
+function you can do this:
+
+@example
+(ede-java-root-project "NAME" :file "FILENAME" :locate-fcn 'MYFCN)
+@end example
+
+Where @var{MYFCN} is a symbol for a function. The locate function can
+be used in place of @code{ede-expand-filename} so you can quickly
+customize your custom target to use specialized local routines instead
+of the default @ede{} routines. The function symbol must take two
+arguments:
+
+@table @var
+@item NAME
+The name of the file to find.
+@item DIR
+The directory root for this java-root project.
+@end table
- In the meantime look in the commentary of ede-simple.el
+If you would like to create your Java projects dynamically, instead of
+putting them all in your @file{.emacs}, you can do that too. See
+@ref{ede-cpp-root} for details that can be applied to this project type.
-@node ede-emacs
+@node ede-emacs, ede-linux, ede-java-root, Simple projects
@subsection ede-emacs
The @code{ede-emacs} project automatically identifies an Emacs source
It pre-populates the C Preprocessor symbol map for correct parsing,
and has an optimized include file identification function.
-@node ede-linux
+@node ede-linux, Custom Locate, ede-emacs, Simple projects
@subsection ede-linux
The @code{ede-linux} project will automatically identify a Linux
It pre-populates the C Preprocessor symbol map for reasonable parsing,
and has an optimized include file identification function.
-@node Custom Locate
+@node Custom Locate, , ede-linux, Simple projects
@subsection Custom Locate
The various simple project styles all have one major drawback, which
methods. See the code in @file{ede-locate.el} for GNU Global as a
simple example.
-@node Extending EDE, , Simple projects, top
+@node Extending EDE, , Miscellaneous commands, top
@chapter Extending @ede{}
This chapter is intended for users who want to write new parts or fix
examples.
@menu
+* Development Overview::
+* Detecting a Project::
* User interface methods:: Methods associated with keybindings
* Base project methods:: The most basic methods on @ede{} objects.
* Sourcecode objects:: Defining new sourcecode classes.
* Compilers:: Details of compiler classes.
@end menu
-@node User interface methods
+@node Development Overview, Detecting a Project, Extending EDE, Extending EDE
+@section Development Overview
+
+@ede{} is made up of a series of classes implemented with @eieio{}.
+These classes define an interface that can be used to create different
+types of projects.
+
+@ede{} defines two superclasses which are @code{ede-project} and
+@code{ede-target}. All commands in @ede{} are usually meant to
+address the current project, or current target.
+
+All specific projects in @ede{} derive subclasses of the @ede{} superclasses.
+In this way, specific behaviors such as how a project is saved, or how a
+target is compiled can be customized by a project author in detail. @ede{}
+communicates to these project objects via an API using methods. The
+commands you use in @ede{} mode are high-level functional wrappers over
+these methods.
+
+Some example project types are:
+
+@table @code
+@item project-am
+Autmake project which reads existing Automake files.
+@item ede-proj-project
+This project type will create @file{Makefiles},
+or @file{Makefile.am} files to compile your project.
+@item ede-linux
+This project type will detect linux source trees.
+@item ede-emacs
+This proejct will detect an Emacs source tree.
+@end table
+
+There are several other project types as well.
+
+The first class you need to know to create a new project type is
+@code{ede-project-autoload}. New instances of this class are needed
+to define how Emacs associates different files/buffers with different
+project types. All the autoloads are kept in the variable
+@code{ede-project-class-files}.
+
+The next most important class to know is @code{ede-project}. This is
+the baseclass defines how all projects behave. The basic pattern for
+a project is that there is one project per directory, and the topmost
+project or directory defines the project as a whole.
+
+Key features of @code{ede-project} are things like name and version
+number. It also holds a list of @code{ede-target} objects and a list
+of sub projects, or more @code{ede-project} objects.
+
+New project types must subclass @code{ede-project} to add special
+behavior. New project types also need to subclass @code{ede-target} to
+add specialty behavior.
+
+In this way, the common @ede{} interface is designed to work against
+@code{ede-project}, and thus all subclasses.
+
+@code{ede-project} subclasses @code{ede-project-placeholder}. This is
+the minimum necessary project needed to be cached between runs of
+Emacs. This way, Emacs can track all projects ever seen, without
+loading those projects into memory.
+
+Here is a high-level UML diagram for the @ede{} system created with @cogre{}..
+
+@example
++-----------------------+ +-----------------------+
+| | |ede-project-placeholder|
+|ede-project-class-files| +-----------------------+
+| | +-----------------------+
++-----------------------+ +-----------------------+
+ /\ ^
+ \/ /_\
+ | |
+ +--------------------+ +-----------+ +----------+
+ |ede-project-autoload| |ede-project| |ede-target|
+ +--------------------+<>--------------+-----------+<>-------+----------+
+ +--------------------+ +-----------+ +----------+
+ +--------------------+ +-----------+ +----------+
+ ^
+ /_\
+ |
+ +---------------------+-----------------+
+ | | |
+ | | |
+ | | |
+ +----------------+ +-------------------+ +---------+
+ |ede-proj-project| |project-am-makefile| |ede-emacs|
+ +----------------+ +-------------------+ +---------+
+ +----------------+ +-------------------+ +---------+
+ +----------------+ +-------------------+ +---------+
+@end example
+
+
+@node Detecting a Project, User interface methods, Development Overview, Extending EDE
+@section Detecting a Project
+
+Project detection happens with the list of @code{ede-project-autoload}
+instances stored in @code{ede-project-class-files}. The full project
+detection scheme works like this:
+
+@table @asis
+@item Step 1:
+@code{find-file-hooks} calls @code{ede-turn-on-hook} on BUFFER.
+@item Step 2:
+@code{ede-turn-on-hook} turns on @code{ede-minor-mode}
+@item Step 3:
+@code{ede-minor-mode} looks to see if BUFFER is associated with any
+open projects. If not, it calls @code{ede-load-project-file} to find
+a project associated with the current directory BUFFER is in.
+@item Step 4:
+@code{ede-minor-mode} associates the found project with the current
+buffer with a series of variables, such as @code{ede-object}, and
+@code{ede-object-project} and @code{ede-object-root-project}.
+@end table
+
+Once a buffer is associated, @ede{} minor mode commands will operate
+on that buffer.
+
+The function @code{ede-load-project-file} is at the heart of detecting
+projects, and it works by looping over all the known project autoload
+types in @code{ede-project-autoload} using the utility
+@code{ede-directory-project-p}.
+
+The function @code{ede-directory-project-p} will call
+@code{ede-dir-to-projectfile} on every @code{ede-project-autoload}
+until one of them returns true. The method
+@code{ede-dir-to-projectfile} in turn gets the @code{:proj-file} slot
+from the autoload. If it is a string (ie, a project file name), it
+checks to see if that exists in BUFFER's directory. If it is a
+function, then it calls that function and expects it to return a file
+name or nil. If the file exists, then this directory is assumed to be
+part of a project, and @code{ede-directory-project-p} returns the
+instance of @code{ede-project-autoload} that matched.
+
+If the current directory contains the file @code{.ede-ignore} then
+that directory is automatically assumed to contain no projects, even
+if there is a matching pattern. Use this type of file in a directory
+that may contain many other sub projects, but still has a Makefile of
+some sort.
+
+If the current directory is a project, then @ede{} scans upwards till
+it finds the top of the project. It does this by calling
+@code{ede-toplevel-project}. If this hasn't already been discovered,
+the directories as scanned upward one at a time until a directory with
+no project is found. The last found project becomes the project
+root. If the ofund instance of @code{ede-project-autoload} has a
+valid @code{proj-root} slot value, then that function is called instead
+of scanning the project by hand. Some project types have a short-cut
+for determining the root of a project, so this comes in handy.
+
+Getting back to @code{ede-load-project-file}, this now has an instance
+of @code{ede-project-autoload}. It uses the @code{load-type} slot to
+both autoload in the project type, and to create a new instance of the
+project type found for the root of the project. That project is added
+to the global list of all projects. All subprojects are then created
+and assembled into the project data structures.
+
+
+@node User interface methods, Base project methods, Detecting a Project, Extending EDE
@section User interface methods
These methods are core behaviors associated with user commands.
Rescan a project file, changing the data in the existing objects.
@end table
-@node Base project methods
+@node Base project methods, Sourcecode objects, User interface methods, Extending EDE
@section Base project methods
These methods are important for querying base information from project
List all documentation a project or target is responsible for.
@end table
-@node Sourcecode objects
+@node Sourcecode objects, Compiler and Linker objects, Base project methods, Extending EDE
@section Sourcecode objects
@ede{} projects track source file / target associates via source code
@xref{Sourcecode}.
-@node Compiler and Linker objects
+@node Compiler and Linker objects, Project, Sourcecode objects, Extending EDE
@section Compiler and Linker objects
In order for a target to create a @file{Makefile}, it must know how to
@defindex sc
@defindex cm
-@node Project
+@node Project, Targets, Compiler and Linker objects, Extending EDE
@section Project
@menu
-* ede-project-placeholder ::
-* ede-project ::
-* ede-cpp-root-project ::
-* ede-simple-project ::
-* ede-simple-base-project ::
-* ede-proj-project ::
-* project-am-makefile ::
-* ede-step-project ::
+* ede-project-placeholder::
+* ede-project::
+* ede-cpp-root-project::
+* ede-simple-project::
+* ede-simple-base-project::
+* ede-proj-project::
+* project-am-makefile::
+* ede-step-project::
@end menu
-@node ede-project-placeholder
+@node ede-project-placeholder, ede-project, Project, Project
@subsection ede-project-placeholder
@pjindex ede-project-placeholder
Make sure placeholder @var{THIS} is replaced with the real thing, and pass through.
@end deffn
-@node ede-project
+@node ede-project, ede-cpp-root-project, ede-project-placeholder, Project
@subsection ede-project
@pjindex ede-project
Commit change to local variables in @var{PROJ}.
@end deffn
-@node ede-cpp-root-project
+@node ede-cpp-root-project, ede-simple-project, ede-project, Project
@subsection ede-cpp-root-project
@pjindex ede-cpp-root-project
This knows details about or source tree.
@end deffn
-@node ede-simple-project
+@node ede-simple-project, ede-simple-base-project, ede-cpp-root-project, Project
@subsection ede-simple-project
@pjindex ede-simple-project
Commit any change to @var{PROJ} to its file.
@end deffn
-@node ede-simple-base-project
+@node ede-simple-base-project, ede-proj-project, ede-simple-project, Project
@subsection ede-simple-base-project
@pjindex ede-simple-base-project
@table @asis
@end table
-@node ede-proj-project
+@node ede-proj-project, project-am-makefile, ede-simple-base-project, Project
@subsection ede-proj-project
@pjindex ede-proj-project
Commit change to local variables in @var{PROJ}.
@end deffn
-@node project-am-makefile
+@node project-am-makefile, ede-step-project, ede-proj-project, Project
@subsection project-am-makefile
@pjindex project-am-makefile
buffer being in order to provide a smart default target type.
@end deffn
-@node ede-step-project
+@node ede-step-project, , project-am-makefile, Project
@subsection ede-step-project
@pjindex ede-step-project
Commit change to local variables in @var{PROJ}.
@end deffn
-@node Targets
+@node Targets, Sourcecode, Project, Extending EDE
@section Targets
@menu
-* ede-target ::
-* ede-proj-target ::
-* ede-proj-target-makefile ::
-* semantic-ede-proj-target-grammar ::
-* ede-proj-target-makefile-objectcode ::
-* ede-proj-target-makefile-archive ::
-* ede-proj-target-makefile-program ::
-* ede-proj-target-makefile-shared-object ::
-* ede-proj-target-elisp ::
-* ede-proj-target-elisp-autoloads ::
-* ede-proj-target-makefile-miscelaneous ::
-* ede-proj-target-makefile-info ::
-* ede-proj-target-scheme ::
-* project-am-target ::
-* project-am-objectcode ::
-* project-am-program ::
-* project-am-header-noinst ::
-* project-am-header-inst ::
-* project-am-lisp ::
-* project-am-texinfo ::
-* project-am-man ::
+* ede-target::
+* ede-proj-target::
+* ede-proj-target-makefile::
+* semantic-ede-proj-target-grammar::
+* ede-proj-target-makefile-objectcode::
+* ede-proj-target-makefile-archive::
+* ede-proj-target-makefile-program::
+* ede-proj-target-makefile-shared-object::
+* ede-proj-target-elisp::
+* ede-proj-target-elisp-autoloads::
+* ede-proj-target-makefile-miscelaneous::
+* ede-proj-target-makefile-info::
+* ede-proj-target-scheme::
+* project-am-target::
+* project-am-objectcode::
+* project-am-program::
+* project-am-header-noinst::
+* project-am-header-inst::
+* project-am-lisp::
+* project-am-texinfo::
+* project-am-man::
@end menu
-@node ede-target
+@node ede-target, ede-proj-target, Targets, Targets
@subsection ede-target
@tgindex ede-target
Retrieves the slot @code{menu} from an object of class @code{ede-target}
@end deffn
-@node ede-proj-target
+@node ede-proj-target, ede-proj-target-makefile, ede-target, Targets
@subsection ede-proj-target
@tgindex ede-proj-target
@end deffn
-@node ede-proj-target-makefile
+@node ede-proj-target-makefile, semantic-ede-proj-target-grammar, ede-proj-target, Targets
@subsection ede-proj-target-makefile
@tgindex ede-proj-target-makefile
Use @var{CONFIGURATION} as the current configuration to query.
@end deffn
-@node semantic-ede-proj-target-grammar
+@node semantic-ede-proj-target-grammar, ede-proj-target-makefile-objectcode, ede-proj-target-makefile, Targets
@subsection semantic-ede-proj-target-grammar
@tgindex semantic-ede-proj-target-grammar
@end deffn
-@node ede-proj-target-makefile-objectcode
+@node ede-proj-target-makefile-objectcode, ede-proj-target-makefile-archive, semantic-ede-proj-target-grammar, Targets
@subsection ede-proj-target-makefile-objectcode
@tgindex ede-proj-target-makefile-objectcode
@end deffn
-@node ede-proj-target-makefile-archive
+@node ede-proj-target-makefile-archive, ede-proj-target-makefile-program, ede-proj-target-makefile-objectcode, Targets
@subsection ede-proj-target-makefile-archive
@tgindex ede-proj-target-makefile-archive
@end deffn
-@node ede-proj-target-makefile-program
+@node ede-proj-target-makefile-program, ede-proj-target-makefile-shared-object, ede-proj-target-makefile-archive, Targets
@subsection ede-proj-target-makefile-program
@tgindex ede-proj-target-makefile-program
@end deffn
-@node ede-proj-target-makefile-shared-object
+@node ede-proj-target-makefile-shared-object, ede-proj-target-elisp, ede-proj-target-makefile-program, Targets
@subsection ede-proj-target-makefile-shared-object
@tgindex ede-proj-target-makefile-shared-object
@end deffn
-@node ede-proj-target-elisp
+@node ede-proj-target-elisp, ede-proj-target-elisp-autoloads, ede-proj-target-makefile-shared-object, Targets
@subsection ede-proj-target-elisp
@tgindex ede-proj-target-elisp
@end deffn
@deffn Method ede-proj-flush-autoconf :AFTER this
-Flush the configure file (current buffer) to accommodate @var{THIS}.
+Flush the configure file (current buffer) to accomodate @var{THIS}.
@end deffn
@deffn Method ede-buffer-mine :AFTER this buffer
is found, such as a @code{-version} variable, or the standard header.
@end deffn
-@node ede-proj-target-elisp-autoloads
+@node ede-proj-target-elisp-autoloads, ede-proj-target-makefile-miscelaneous, ede-proj-target-elisp, Targets
@subsection ede-proj-target-elisp-autoloads
@tgindex ede-proj-target-elisp-autoloads
@end deffn
-@node ede-proj-target-makefile-miscelaneous
+@node ede-proj-target-makefile-miscelaneous, ede-proj-target-makefile-info, ede-proj-target-elisp-autoloads, Targets
@subsection ede-proj-target-makefile-miscelaneous
@tgindex ede-proj-target-makefile-miscelaneous
@end deffn
-@node ede-proj-target-makefile-info
+@node ede-proj-target-makefile-info, ede-proj-target-scheme, ede-proj-target-makefile-miscelaneous, Targets
@subsection ede-proj-target-makefile-info
@tgindex ede-proj-target-makefile-info
when working in Automake mode.
@end deffn
-@node ede-proj-target-scheme
+@node ede-proj-target-scheme, project-am-target, ede-proj-target-makefile-info, Targets
@subsection ede-proj-target-scheme
@tgindex ede-proj-target-scheme
@end deffn
-@node project-am-target
+@node project-am-target, project-am-objectcode, ede-proj-target-scheme, Targets
@subsection project-am-target
@tgindex project-am-target
Edit the target associated w/ this file.
@end deffn
-@node project-am-objectcode
+@node project-am-objectcode, project-am-program, project-am-target, Targets
@subsection project-am-objectcode
@tgindex project-am-objectcode
There are no default header files.
@end deffn
-@node project-am-program
+@node project-am-program, project-am-header-noinst, project-am-objectcode, Targets
@subsection project-am-program
@tgindex project-am-program
@end table
@end table
-@node project-am-header-noinst
+@node project-am-header-noinst, project-am-header-inst, project-am-program, Targets
@subsection project-am-header-noinst
@tgindex project-am-header-noinst
Return the default macro to 'edit' for this object.
@end deffn
-@node project-am-header-inst
+@node project-am-header-inst, project-am-lisp, project-am-header-noinst, Targets
@subsection project-am-header-inst
@tgindex project-am-header-inst
Return the default macro to 'edit' for this object.
@end deffn
-@node project-am-lisp
+@node project-am-lisp, project-am-texinfo, project-am-header-inst, Targets
@subsection project-am-lisp
@tgindex project-am-lisp
Return the default macro to 'edit' for this object.
@end deffn
-@node project-am-texinfo
+@node project-am-texinfo, project-am-man, project-am-lisp, Targets
@subsection project-am-texinfo
@tgindex project-am-texinfo
@end deffn
@deffn Method project-compile-target-command :AFTER this
-Default target t- use when compiling a texinfo file.
+Default target t- use when compling a texinfo file.
@end deffn
@deffn Method ede-documentation :AFTER this
files in the project.
@end deffn
-@node project-am-man
+@node project-am-man, , project-am-texinfo, Targets
@comment node-name, next, previous, up
@subsection project-am-man
@tgindex project-am-man
Return the default macro to 'edit' for this object type.
@end deffn
-@node Sourcecode
+@node Sourcecode, Compilers, Targets, Extending EDE
@section Sourcecode
The source code type is an object designed to associated files with
targets.
@menu
-* ede-sourcecode ::
+* ede-sourcecode::
@end menu
-@node ede-sourcecode
+@node ede-sourcecode, , Sourcecode, Sourcecode
@subsection ede-sourcecode
@scindex ede-sourcecode
Return non-@code{nil} if @var{THIS} will take @var{FILENAME} as an auxiliary .
@end deffn
-@node Compilers
+@node Compilers, , Sourcecode, Extending EDE
@section Compilers
The compiler object is designed to associate source code with
compile commands.
@menu
-* ede-compilation-program ::
-* ede-compiler ::
-* ede-object-compiler ::
-* ede-linker ::
+* ede-compilation-program::
+* ede-compiler::
+* ede-object-compiler::
+* ede-linker::
@end menu
-@node ede-compilation-program
+@node ede-compilation-program, ede-compiler, Compilers, Compilers
@subsection ede-compilation-program
@cmindex ede-compilation-program
@end deffn
-@node ede-compiler
+@node ede-compiler, ede-object-compiler, ede-compilation-program, Compilers
@subsection ede-compiler
@cmindex ede-compiler
@end deffn
-@node ede-object-compiler
+@node ede-object-compiler, ede-linker, ede-compiler, Compilers
@subsection ede-object-compiler
@cmindex ede-object-compiler
Insert variables needed by the compiler @var{THIS}.
@end deffn
-@node ede-linker
+@node ede-linker, , ede-object-compiler, Compilers
@subsection ede-linker
@cmindex ede-linker
* Making New Objects:: How to construct new objects.
* Accessing Slots:: How to access a slot.
* Writing Methods:: How to write a method.
-@c * Method Invocation:: How methods are invoked.
+* Method Invocation:: How methods are invoked.
* Predicates:: Class-p, Object-p, etc-p.
* Association Lists:: List of objects as association lists.
* Customizing:: Customizing objects.
* Base Classes:: Additional classes you can inherit from.
* Browsing:: Browsing your class lists.
* Class Values:: Displaying information about a class or object.
+* Documentation:: Automatically creating texinfo documentation.
* Default Superclass:: The root superclasses.
-* Signals:: When you make errors
+* Signals:: When you make errors.
* Naming Conventions:: Name your objects in an Emacs friendly way.
* CLOS compatibility:: What are the differences?
* Wish List:: Things about EIEIO that could be improved.
the @var{superclass-list} first sets the tags for that slot. If the
new class has a slot with the same name as the parent, the new slot
overrides the parent's slot.
+
+When overriding a slot, some slot attributes cannot be overridden
+because they break basic OO rules. You cannot override @code{:type}
+or @code{:protection}.
@end defmac
@noindent
@end defvar
@menu
-* Inheritance:: How to specify parents classes
+* Inheritance:: How to specify parents classes.
* Slot Options:: How to specify features of a slot.
* Class Options:: How to specify features for this class.
@end menu
:initform +
@end example
will set the initial value as that symbol.
-A function that is a lambda expression, like this:
-@example
-:initform (lambda () some-variablename)
-@end example
-
-will be evaluated at instantiation time to the value of
-@code{some-variablename}.
-@c This feature was more annoying than useful. Use the
-@c `initialize-instance' function to do this.
-@c
-@c On the other hand, if you need code to be
-@c executed at instantiation time as the initform, code like this:
-@c @example
-@c :initform (lambda () (+ 1 some-global-var))
-@c @end example
-@c will be identified as a function call, and be executed in place.
-
-@cindex lambda-default
-
-
-Lastly, using the function @code{lambda-default} instead of
-@code{lambda} will let you specify a lambda expression to use as the
-value, without evaluation, thus:
-@example
-:initform (lambda-default () some-variablename)
-@end example
-@c @@TODO - This will be deleted after fair warning.
-will not be evaluated at instantiation time, and the value in this
-slot will instead be @code{(lambda () some-variablename)}.
After a class has been created with @code{defclass}, you can change
that default value with @code{oset-default}. @ref{Accessing Slots}.
An object of your class type.
@item (or null symbol)
A symbol, or nil.
- @item function
- A function symbol, or a @code{lambda-default} expression.
-
@end table
@item :allocation
This is the default.
@item :depth-first
Search for methods in the class hierarchy in a depth first order.
+@item :c3
+Searches for methods in in a learnarized way that most closely matches
+what CLOS does when a monotonic class structure is defined.
@end table
-@c @xref{Method Invocation}, for more on method invocation order.
+@xref{Method Invocation}, for more on method invocation order.
@item :metaclass
Unsupported CLOS option. Enables the use of a different base class other
@c TODO - Write some more about static methods here
-@c @node Method Invocation
-@c @chapter Method Invocation
+@node Method Invocation
+@chapter Method Invocation
-@c TODO - writeme
+When classes are defined, you can specify the
+@code{:method-invocation-order}. This is a feature specific to EIEIO.
+
+This controls the order in which method resolution occurs for
+@code{:primary} methods in cases of multiple inheritance. The order
+affects which method is called first in a tree, and if
+@code{call-next-method} is used, it controls the order in which the
+stack of methods are run.
+
+The original EIEIO order turned out to be broken for multiple
+inheritance, but some programs depended on it. As such this option
+was added when the default invocation order was fixed to something
+that made more sense in that case.
+
+Valid values are:
+
+@table @code
+@item :breadth-first
+Search for methods in the class hierarchy in breadth first order.
+This is the default.
+@item :depth-first
+Search for methods in the class hierarchy in a depth first order.
+@item :c3
+Searches for methods in in a learnarized way that most closely matches
+what CLOS does when CLOS when a monotonic class structure is defined.
+
+This is derived from the Dylan language documents by
+Kim Barrett et al.: A Monotonic Superclass Linearization for Dylan
+Retrieved from: http://192.220.96.201/dylan/linearization-oopsla96.html
+@end table
@node Predicates
@comment node-name, next, previous, up
provided.
@end defmethod
-@defun eieio-persistent-read filename
-Read @var{filename} which contains an @code{eieio-persistent} object
-previously written with @code{eieio-persistent-save}.
+@defun eieio-persistent-read filename &optional class allow-subclass
+Read a persistent object from @var{filename}, and return it.
+Signal an error if the object in @var{FILENAME} is not a constructor
+for @var{CLASS}. Optional @var{allow-subclass} says that it is ok for
+@code{eieio-peristent-read} to load in subclasses of class instead of
+being pendantic."
@end defun
@node eieio-named
class symbol, or an object. The resulting buffer will display all slot
names.
-Additionally, all methods defined to have functionality on this class
-are displayed.
+Additionally, all methods defined to have functionality on this class is
+displayed.
+
+@node Documentation
+@comment node-name, next, previous, up
+@chapter Documentation
+
+It is possible to automatically create documentation for your classes in
+texinfo format by using the tools in the file @file{eieio-doc.el}
+
+@deffn Command eieiodoc-class class indexstring &optional skiplist
+
+This will start at the current point, and created an indented menu of
+all the child classes of, and including @var{class}, but skipping any
+classes that might be in @var{skiplist} It will then create nodes for
+all these classes, subsection headings, and indexes.
+
+Each class will be indexed using the texinfo labeled index
+@var{indexstring} which is a two letter description.
+@xref{(texinfo) New Indices}.
+
+To use this command, the texinfo macro
+
+@example
+@@defindex @@var @{ indexstring @}
+@end example
+
+@noindent
+where @var{indexstring} is replaced with the two letter code.
+
+Next, an inheritance tree will be created listing all parents of that
+section's class.
+
+Then,all the slots will be expanded in tables, and described
+using the documentation strings from the code. Default values will also
+be displayed. Only those slots with @code{:initarg} specified will be
+expanded, others will be hidden. If a slot is inherited from a parent,
+that slot will also be skipped unless the default value is different.
+If there is a change, then the documentation part of the slot will be
+replace with an @@xref back to the parent.
+
+This command can only display documentation for classes whose
+definitions have been loaded in this Emacs session.
+
+@end deffn
@node Default Superclass
@comment node-name, next, previous, up
+2012-10-01 Eric Ludlam <zappo@gnu.org>
+
+ * srecode/cc.srt, srecode/ede-autoconf.srt: New files.
+
+ * srecode/cpp.srt: Move parts to c.srt.
+
+ * srecode/ede-make.srt: Extra templates for Arduino Makefiles.
+
+2012-10-01 Ralf Mattes <rm@mh-freiburg.de> (tiny change)
+
+ * srecode/el.srt (variable-option): Add missing quote.
+
2012-10-01 Chong Yidong <cyd@gnu.org>
* images/icons/hicolor/32x32/apps/emacs22.png:
--- /dev/null
+;;; c.srt --- SRecode templates for c-mode
+
+;; Copyright (C) 2007, 2008, 2009, 2010, 2012 Free Software Foundation, Inc.
+
+;; Author: Eric M. Ludlam <eric@siege-engine.com>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
+
+set mode "c-mode"
+
+set comment_start "/**"
+set comment_end " */"
+set comment_prefix " *"
+
+;; OVERRIDE THIS in your user or project template file to whatever
+;; you use for your project.
+set HEADEREXT ".h"
+
+context file
+
+template empty :time :user :file :c
+----
+{{>:filecomment}}
+
+{{#NOTHEADER}}
+
+{{^}}
+{{/NOTHEADER}}
+{{#HEADER}}
+{{>:header_guard}}
+{{/HEADER}}
+----
+
+template header_guard :file :blank
+----
+#ifndef {{FILENAME_SYMBOL}}
+#define {{FILENAME_SYMBOL}} 1
+
+{{^}}
+
+#endif // {{FILENAME_SYMBOL}}
+----
+
+context misc
+
+template arglist
+"Insert an argument list for a function.
+@todo - Support smart CR in a buffer for not too long lines."
+----
+({{#ARGS}}{{TYPE}} {{NAME}}{{#NOTLAST}},{{/NOTLAST}}{{/ARGS}})
+----
+
+context declaration
+
+prompt TYPE "Return Type: "
+
+template function :indent :blank
+"Insert a function declaration."
+----
+{{?TYPE}} {{?NAME}}{{>:misc:arglist}}
+{{#INITIALIZERS}}{{>B:initializers}}{{/INITIALIZERS}}
+{
+{{^}}
+}
+----
+bind "f"
+
+template function-prototype :indent :blank
+"Insert a function declaration."
+----
+{{?TYPE}} {{?NAME}}{{>:misc:arglist}};
+----
+
+
+prompt TYPE "Data Type: "
+
+template variable :indent :blank
+"Insert a variable declaration."
+----
+{{?TYPE}} {{?NAME}}{{#HAVEDEFAULT}} = {{DEFAULT}}{{/HAVEDEFAULT}};
+----
+bind "v"
+
+template variable-prototype :indent :blank
+"Insert a variable declaration."
+----
+{{?TYPE}} {{?NAME}};
+----
+bind "v"
+
+
+template include :blank
+"An include statement."
+----
+#include "{{?NAME}}"
+----
+bind "i"
+
+template system-include :blank
+"An include statement."
+----
+#include <{{?NAME}}>
+----
+bind "i"
+
+template label :blank :indent
+----
+ {{?NAME}}:
+----
+
+context declaration
+
+template comment-function :indent :blank
+"Used to put a nice comment in front of a function.
+Override this with your own preference to avoid using doxygen"
+----
+{{>A:declaration:doxygen-function}}
+----
+
+;;; DOXYGEN FEATURES
+;;
+;;
+context declaration
+
+template doxygen-function :indent :blank
+----
+/**
+ * @name {{NAME}} - {{DOC}}{{^}}{{#ARGS}}
+ * @param {{NAME}} - {{DOC}}{{/ARGS}}
+ * @return {{TYPE}}
+ */
+----
+
+template doxygen-variable-same-line
+----
+/**< {{DOC}}{{^}} */
+----
+
+template doxygen-section-comment :blank :indent
+"Insert a comment that separates sections of an Emacs Lisp file."
+----
+\f
+/** {{?TITLE}}
+ *
+ * {{^}}
+ */
+
+----
+
+
+;; end
set comment_end " */"
set comment_prefix " *"
-;; OVERRIDE THIS in your user or project template file to whatever
-;; you use for your project.
-set HEADEREXT ".h"
-
-context file
-
-template empty :time :user :file :cpp
-----
-{{>:filecomment}}
-
-{{#NOTHEADER}}
-
-{{^}}
-{{/NOTHEADER}}
-{{#HEADER}}
-{{>:header_guard}}
-{{/HEADER}}
-----
-
-template header_guard :file :blank
-----
-#ifndef {{FILENAME_SYMBOL}}
-#define {{FILENAME_SYMBOL}} 1
-
-{{^}}
-
-#endif // {{FILENAME_SYMBOL}}
-----
-
-context misc
-
-template arglist
-"Insert an argument list for a function.
-@todo - Support smart CR in a buffer for not too long lines."
-----
-({{#ARGS}}{{TYPE}} {{NAME}}{{#NOTLAST}},{{/NOTLAST}}{{/ARGS}})
-----
-
context declaration
-prompt TYPE "Return Type: "
-
-template function :indent :blank
-"Insert a function declaration."
-----
-{{?TYPE}} {{?NAME}}{{>:misc:arglist}}
-{{#INITIALIZERS}}{{>B:initializers}}{{/INITIALIZERS}}
-{
-{{^}}
-}
-----
-bind "f"
-
-template function-prototype :indent :blank
-"Insert a function declaration."
-----
-{{?TYPE}} {{?NAME}}{{>:misc:arglist}};
-----
-
-
-prompt TYPE "Data Type: "
-
-template variable :indent :blank
-"Insert a variable declaration."
-----
-{{?TYPE}} {{?NAME}}{{#HAVEDEFAULT}} = {{DEFAULT}}{{/HAVEDEFAULT}};
-----
-bind "v"
-
-template variable-prototype :indent :blank
-"Insert a variable declaration."
-----
-{{?TYPE}} {{?NAME}};
-----
-bind "v"
-
template class :indent :blank
"Insert a C++ class. For use by user insertion.
Override this template to change contents of a class.
}
----
-template include :blank
-"An include statement."
-----
-#include "{{?NAME}}"
-----
-bind "i"
-
-template label :blank :indent
-----
- {{?NAME}}:
-----
-
context classdecl
template constructor-tag :indent :blank
{{>A:classdecl:doxygen-function-group-end}}
----
-context declaration
-
-template comment-function :indent :blank
-"Used to put a nice comment in front of a function.
-Override this with your own preference to avoid using doxygen"
-----
-{{>A:declaration:doxygen-function}}
-----
-
;;; DOXYGEN FEATURES
;;
;;
----
-context declaration
-
-template doxygen-function :indent :blank
-----
-/**
- * @name {{NAME}} - {{DOC}}{{^}}{{#ARGS}}
- * @param {{NAME}} - {{DOC}}{{/ARGS}}
- * @return {{TYPE}}
- */
-----
-
-template doxygen-variable-same-line
-----
-/**< {{DOC}}{{^}} */
-----
-
-template doxygen-section-comment :blank :indent
-"Insert a comment that separates sections of an Emacs Lisp file."
-----
-\f
-/** {{?TITLE}}
- *
- * {{^}}
- */
-
-----
-
-
;; end
--- /dev/null
+;; ede/templates/autoconf.srt --- Templates for autoconf used by EDE.
+;;
+;; Copyright (C) 2010 Eric M. Ludlam
+;;
+;; Author: Eric M. Ludlam <eric@siege-engine.com>
+;;
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 2, or (at
+;; your option) any later version.
+
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+set mode "autoconf-mode"
+set escape_start "{{"
+set escape_end "}}"
+set comment_start "#"
+set comment_prefix "#"
+set application "ede"
+
+context file
+
+template ede-empty
+"Start a new EDE generated configure.in/ac file."
+----
+{{comment_prefix}} Automatically Generated/Maintained {{FILE}} by EDE.
+{{comment_prefix}}
+{{comment_prefix}} YOU MAY MODIFY THIS FILE
+{{comment_prefix}} Hand made changes in some sections will be preserved
+{{comment_prefix}} by EDE when this file is updated.
+{{comment_prefix}}
+{{comment_prefix}} EDE is the Emacs Development Environment.
+{{comment_prefix}} http://cedet.sourceforge.net/ede.shtml
+{{comment_prefix}}
+{{comment_prefix}} Process this file with autoconf to produce a configure script
+
+AC_INIT({{TEST_FILE}})
+AM_INIT_AUTOMAKE([{{PROGRAM}}], 0)
+AM_CONFIG_HEADER(config.h)
+
+{{comment_prefix}} End the configure script.
+AC_OUTPUT(Makefile, [date > stamp-h] )
+----
+
+
+;; end
{{NAME}}={{#VALUE}} {{VAL}}{{/VALUE}}{{/VARIABLE}}
----
+;; Some extra templates for Arduino based Makefiles.
+;; Perhaps split this out someday in the future.
+context arduino
+
+template ede-empty :file
+----
+# Automatically Generated {{FILE}} by EDE.
+# For use with Make for an Arduino project.
+#
+# DO NOT MODIFY THIS FILE OR YOUR CHANGES MAY BE LOST.
+# EDE is the Emacs Development Environment.
+# http://cedet.sourceforge.net/ede.shtml
+
+ARDUINO_DIR = {{ARDUINO_HOME}}
+
+TARGET = {{TARGET}}
+ARDUINO_LIBS = {{ARDUINO_LIBS}}
+
+MCU = {{MCU}}
+F_CPU = {{F_CPU}}
+ARDUINO_PORT = {{PORT}}
+BOARD_TAG = {{BOARD}}
+
+AVRDUDE_ARD_BAUDRATE = {{AVRDUDE_ARD_BAUDRATE}}
+AVRDUDE_ARD_PROGRAMMER = {{AVRDUDE_ARD_PROGRAMMER}}
+
+include {{ARDUINO_MK}}
+
+# End of Makefile
+----
+
+
;; end
----
(defcustom $?NAME$ $^$
"*$DOC$"
- :group $GROUP$
+ :group '$GROUP$
:type $?CUSTOMTYPE$)
----
bind "o"
+2012-10-01 David Engster <deng@randomsample.de>
+
+ * emacs-lisp/eieio-opt.el (eieio-describe-class): Add filename
+ from symbol property and change message to be more consistent with
+ Emacs proper.
+ (eieio-describe-generic): Add filename for each implementation.
+ Fix indices for generic and normal methods.
+ (eieio-method-def, eieio-class-def): New buttons.
+ (eieio-help-find-method-definition)
+ (eieio-help-find-class-definition): New functions.
+ (eieio-help-mode-augmentation-maybee): Add buttons to filenames of
+ class, constructor and method definitions.
+
+ * emacs-lisp/eieio.el (eieiomt-add, eieio-defclass): Save file
+ information in symbol property.
+ (scoped-class): Remove.
+ (eieio-slot-name-index, call-next-method): Check if it is bound.
+
+2012-10-01 Leo P. White <lpw25@cam.ac.uk>
+
+ * emacs-lisp/eieio-custom.el (eieio-custom-mode-map): New option.
+ (eieio-custom-mode): New major mode.
+ (eieio-customize-object): Use it.
+
+2012-10-01 Eric Ludlam <zappo@gnu.org>
+
+ * emacs-lisp/eieio-base.el (eieio-persistent-read): New input args
+ specifying the expected class, and whether subclassing is allowed.
+ (eieio-persistent-convert-list-to-object):
+ (eieio-persistent-validate/fix-slot-value)
+ (eieio-persistent-slot-type-is-class-p): New functions.
+ (eieio-named::slot-missing): Doc fix.
+
+ * emacs-lisp/eieio-datadebug.el (data-debug/eieio-insert-slots):
+ Stop using unused publd variable.
+
+ * emacs-lisp/eieio-speedbar.el (eieio-speedbar-handle-click):
+ (eieio-speedbar-description, eieio-speedbar-derive-line-path)
+ (eieio-speedbar-object-buttonname, eieio-speedbar-make-tag-line)
+ (eieio-speedbar-handle-click): Do not specify a class for the
+ method. Fixes method invocation order problems with EDE.
+
2012-10-01 Stefan Monnier <monnier@iro.umontreal.ca>
* emacs-lisp/bytecomp.el (byte-compiler-abbreviate-file): New function.
+2012-10-01 Chong Yidong <cyd@gnu.org>
+
+ * semantic/bovine/c-by.el: Regenerate.
+ * semantic/bovine/make-by.el:
+ * semantic/bovine/scm-by.el:
+ * semantic/grammar-wy.el:
+ * semantic/wisent/javat-wy.el:
+ * semantic/wisent/js-wy.el:
+ * srecode/srt-wy.el:
+
+2012-10-01 Eric Ludlam <zappo@gnu.org>
+
+ * cedet.el (cedet-version, cedet-packages): Update.
+
+ * cedet-global.el (cedet-gnu-global-version-check): Support newer
+ versions that have extra (parens) in the version string.
+
+ * cedet-idutils.el (cedet-idutils-version-check): Make sure a
+ version number was found before calling inversion-check-version.
+
+ * data-debug.el (data-debug-insert-thing): Bind inhibit-read-only
+ while inserting the thing, then clear modified bit.
+ (data-debug-map): Suppress the keymap.
+ (data-debug-mode, data-debug-new-buffer): Make buffer read-only.
+ (data-debug-contract-current-line): Inhibit read-only, then clear
+ modified bit.
+
+ * ede.el (ede-buffer-belongs-to-project-p): Use ede-object-project
+ to allow use in more kinds of buffers.
+ (ede-project-forms-menu): Add `Default configuration' menu item.
+ (ede-configuration-forms-menu): New, for use in above.
+ (ede-project-configurations-set): New command used from menu.
+ (ede-java-classpath): New conveninece for Java support.
+ (ede-apply-object-keymap): Combine keybindings from the project
+ and the target, not just whatever is local to the buffer.
+ (ede-apply-target-options): Call fcn to apply project local
+ variables.
+ (ede-reset-all-buffers): Remove arg.
+ (ede, ede-rescan-toplevel): Callers changed.
+ (ede-new-target): Fix bug where you couldn't call this from Dired.
+ (ede-add-file): Replace assignment of ede-object with generic call
+ to re-init the buffer.
+ (ede-find-target): If ede-object is set, run short-cut code
+ instead of `or' shortcut.
+ (ede-project-buffers): Return buffers belonging to input project,
+ not any buffer belonging to any project.
+ (ede-system-include-path, ede-apply-project-local-variables)
+ (ede-set-project-local-variable): New functions.
+ (ede-make-project-local-variable): Apply to toplevel if none
+ specified.
+ (ede-set): Make it interactive.
+
+ * ede/auto.el (ede-project-autoload): New class.
+ (ede-do-dirmatch): New method.
+ (ede-project-dirmatch-p): New function.
+ (ede-project-root-directory): Call it.
+ (ede-dir-to-projectfile): Don't call project file function if we
+ didn't match the root.
+ (ede-project-root-directory): Don't call a project's root function
+ if the tool in question isn't installed.
+ (ede-dir-to-projectfile): Don't call project file function if we
+ didn't match the root.
+
+ * ede/autoconf-edit.el (autoconf-parameter-strip): Remove any
+ trailing `\' mid string, and replace with a space.
+ (autoconf-parameter-count): New function.
+ (autoconf-set-version): Use it.
+
+ * ede/base.el (ede-project): The :type of targets is now a list of
+ target base classes.
+
+ * ede/emacs.el (ede-emacs-load): Fix typo.
+
+ * ede/files.el (ede-flush-project-hash, ede-flush-directory-hash):
+ Protect against missing locator object.
+ (ede-get-locator-object): Protect against missing project.
+ (ede-flush-directory-hash): New command.
+ (ede-get-locator-object): Protect against missing project.
+
+ * ede/generic.el (ede-generic-config): Add configurable
+ `run-command' slot.
+ (project-compile-project, project-compile-target)
+ (project-debug-target, project-run-target): New methods.
+ (ede-generic-get-configuration): Specify the class to load.
+ (ede-generic-new-autoloader): Use ede-add-project-autoload.
+ (ede-enable-generic-projects): Rename projects so as to never
+ match the edeproject-* projects.
+
+ * ede/makefile-edit.el (makefile-macro-file-list): Case sensitive
+ searches. Protect against "SUBDIRS=$(subdirs)" infloop.
+
+ * ede/proj-elisp.el (ede-proj-tweak-autoconf)
+ (ede-proj-flush-autoconf): Disable local variables when loading
+ the autoconf lisp compile script.
+
+ * ede/proj.el (ede-proj-target-aux, -elisp, -elisp-autoloads)
+ (-scheme, -makefile-misc, ede-proj-target-makefile-program)
+ (-makefile-archive, -makefile-shared-object)
+ (ede-proj-target-makefile-info, -grammar): New autoloads.
+ (ede-proj-project): Inherit from eieio-persistent-read. Specify
+ extension and header line.
+ (ede-proj-load, ede-proj-save): Replace with impl using
+ eieio-persistent-read.
+
+ * ede/project-am.el (project-add-file): Use ede-target-parent
+ instead of loading the project file.
+
+ * semantic.el (semantic-version): Update.
+ (semantic-new-buffer-setup-functions): Add f90-mode, texinfo-mode.
+ (navigate-menu): Add menu item for Stickyfunc mode.
+
+ * semantic/analyze/debug.el
+ (semantic-analyzer-debug-insert-include-summary): Before
+ dereferencing tableinner, make sure it has a value.
+
+ * semantic/analyze/refs.el
+ (semantic-analyze-tag-references-default): When doing a lookup,
+ specify noerror.
+ (semantic--analyze-refs-full-lookup): Add optional noerror input
+ argument. Pass to to full-lookup-simple.
+ (semantic-analyze-refs-impl, semantic-analyze-refs-proto): Ignore
+ :typemodifiers during compare.
+
+ * semantic/bovine/c.el (semantic-lex-cpp-define): Specify limits
+ to looking back for comment chars.
+ (semantic--tag-similar-names-p, semantic--tag-similar-names-p-default)
+ (semantic--tag-attribute-similar-p): New.
+ (semantic-c-describe-environment): Handle list value of ede-object.
+ (semantic-lex-c-preprocessor-symbol-map-builtin): Add
+ __attribute_pure__.
+
+ * semantic/bovine/scm.el (semantic-format-tag-prototype): Add
+ parent and color argument. Pass them through.
+
+ * semantic/complete.el (semantic-collector-calculate-completions):
+ Search for more matches if new prefix is a substring of old one.
+ (semantic-complete-inline-project): New function.
+
+ * semantic/db-el.el (object-print): New method.
+
+ * semantic/db-file.el (semanticdb-load-database): Specify class.
+
+ * semantic/db-typecache.el
+ (semanticdb-abstract-table::semanticdb-typecache-find-method):
+ Allow proxied tags to be resolved during the search.
+ (semanticdb-typecache-complete-flush): Support missing or empty
+ pointmax slot, to allow for more database types.
+
+ * semantic/db.el (semanticdb-abstract-table): Add db-refs slot.
+ (object-print): Allow child classes to overwrite the display of
+ the (%d tags) extra string.
+ (semanticdb-project-database): Specify :type for table.
+ (semanticdb-create-table-for-file): Specify file-truename.
+ (semanticdb-synchronize, semanticdb-partial-synchronize): Restore
+ code that refreshes references to include files.
+
+ * semantic/decorate/include.el
+ (semantic-decoration-on-fileless-includes): New face.
+ (semantic-decoration-on-fileless-include-map)
+ (semantic-decoration-on-fileless-include-menu): New variables.
+ (semantic-decoration-on-includes-highlight-default): Support
+ includes that have a table, but are not associated with a file.
+ (semantic-decoration-fileless-include-describe)
+ (semantic-decoration-fileless-include-menu): New functions.
+ (semantic-decoration-all-include-summary): Add arrows to indicate
+ the file associated with an include name.
+
+ * semantic/find.el
+ (semantic-find-tags-by-scope-protection-default): Also filter on
+ package protection of the slot.
+
+ * semantic/java.el (semantic-java-expand-tag): If some type has a
+ fully qualified name, bust it up into one package and the type
+ with a short name.
+
+ * semantic/lex.el (define-lex-block-analyzer): Protect against
+ random extra close parenthesis.
+
+ * semantic/symref.el (semantic-symref-result-get-tags): Make sure
+ the cursor is on the matched name.
+
+ * semantic/symref/list.el (semantic-symref-results-mode-map):
+ Suppress keymap.
+
+ * semantic/tag-ls.el (semantic--tag-similar-names-p)
+ (semantic--tag-attribute-similar-p)
+ (semantic--tag-similar-types-p): New functions.
+ (semantic-tag-similar-ignorable-attributes): New variable.
+ (semantic-tag-protection-default): Add package concept to return
+ value.
+ (semantic-tag-package-protected-p): New function.
+ (semantic-tag-full-package): New overload method.
+ (semantic-tag-full-package-default): New default for above.
+ (semantic-tag-full-name-default): Look for the full package name.
+
+ * semantic/tag.el (semantic-create-tag-proxy)
+ (semantic-tag-set-proxy, semantic-tag-resolve-proxy): New.
+
+ * semantic/util.el (semantic-describe-buffer): Add
+ semantic-new-buffer-fcn-was-run.
+
+ * semantic/wisent/java-tags.el (semantic-get-local-variables): Add
+ `this' to the local variable context.
+ (semantic-analyze-split-name, semantic-analyze-unsplit-name): New.
+
+ * semantic/wisent/python.el (semantic-python-expand-tag): New
+ function.
+
+ * srecode/compile.el (srecode-compile-templates): Add "framework"
+ special variable support.
+ (srecode-compile-template-table): Support framework specifier.
+
+ * srecode/cpp.el (srecode-semantic-handle-:c)
+ (srecode-semantic-handle-:cpp): New functions.
+ (srecode-semantic-apply-tag-to-dict): Move from cpp-mode function
+ to c-mode function.
+ (srecode-c-apply-templates): Renamed from srecode-cpp-apply-templates.
+
+ * srecode/dictionary.el (initialize-instance): Remove bogus error
+ condition.
+ (srecode-create-section-dictionary): Remove unused function.
+
+ * srecode/java.el (srecode-semantic-handle-:java): Fix filename as
+ package variable. Add current_package variable.
+
+ * srecode/map.el (srecode-map-update-map): Specify the class.
+
+ * srecode/mode.el (srecode-minor-mode): Support the m3 menu.
+
+ * srecode/semantic.el (srecode-semantic-insert-tag): Support
+ system includes.
+
+ * srecode/srt-mode.el (srecode-font-lock-keywords): Update.
+
+ * srecode/table.el (srecode-template-table): Add :framework slot.
+ (srecode-dump): Dump it.
+ (srecode-mode-table): Add new modetables slot.
+ (srecode-get-mode-table): Find the mode, but also find all parent
+ modes, and merge the tables together in :tables from :modetables.
+ (srecode-make-mode-table): Init :modetables
+ (srecode-mode-table-find): Search in modetables.
+ (srecode-mode-table-new): Merge the differet files into the
+ modetables slot.
+
+2012-10-01 David Engster <deng@randomsample.de>
+
+ * ede.el (ede-apply-preprocessor-map): Check that
+ `semantic-lex-spp-macro-symbol-obarray' is non-nil.
+ (global-ede-mode): Fix call to `ede-reset-all-buffers'.
+
+ * ede/cpp-root.el (ede-preprocessor-map): Make sure we add the
+ lexical-table even when the table doesn't need to be refreshed.
+
+ * ede/dired.el (ede-dired-minor-mode): Use called-interactively-p.
+
+ * ede/pmake.el (ede-pmake-insert-variable-once): Wrap in
+ save-excursion.
+
+ * ede/proj-comp.el (ede-proj-makefile-insert-rules): Fix insertion
+ of phony rule.
+
+ * ede/proj-elisp.el (ede-proj-target-elisp): Remove
+ ede-emacs-preload-compiler.
+ (ede-proj-makefile-insert-rules, ede-proj-makefile-dependencies):
+ New methods.
+ (ede-emacs-compiler): Add 'require' macro to variables and pattern
+ rule. Add .elc object extension.
+ (ede-proj-elisp-packages-to-loadpath): Allow longer relative names.
+ (ede-proj-makefile-insert-variables): Do not insert preload items.
+ (ede-proj-target-elisp-autoloads): Don't depend on cedet-autogen.
+
+ * ede/util.el (ede-make-buffer-writable):
+ * semantic/debug.el (semantic-debug-mode): Set buffer-read-only
+ instead of calling toggle-read-only.
+
+ * semantic.el (semantic-fetch-tags): Use progress reporter only
+ when called interactively.
+ (semantic-submode-list): Add debugging modes.
+ (semantic-mode): Remove Semantic from after-change-functions.
+ Delete the cache, call semantic--tag-unlink-cache-from-buffer, and
+ set semantic-new-buffer-fcn-was-run to nil.
+
+ * semantic/analyze/fcn.el (semantic-analyze-tag-prototype-p)
+ (semantic-analyze-tag-prototype-p-default): Remove.
+ (semantic-analyze-type, semantic-analyze-dereference-metatype-1):
+ Use semantic-tag-prototype-p.
+
+ * semantic/bovine/c.el (semantic-c-reset-preprocessor-symbol-map):
+ Ensure semantic-mode is on before getting preprocessor symbols.
+ (semantic-c-skip-conditional-section): Use c-scan-conditionals.
+ (semantic-c-convert-spp-value-to-hideif-value)
+ (semantic-c-evaluate-symbol-for-hideif, semantic-c-hideif-lookup)
+ (semantic-c-hideif-defined): Revive hideif code from CEDET trunk.
+ (semantic-lex-c-if, semantic-c-do-lex-ifdef): Revert changes for
+ regular expression parsing.
+ (semantic-cpp-lexer): Add semantic-lex-c-ifdef.
+ (semantic-expand-c-tag): Check if tag is non-nil before adding it
+ to return list
+ (semantic-expand-c-extern-C, semantic-expand-c-complex-type): New
+ functions, copied from semantic-expand-c-tag.
+ (semantic-find-tags-included): New override which also searches
+ for include tags inside of namespaces.
+ (semantic-c-dereference-typedef): Use semantic-tag-prototype-p.
+ (semanticdb-find-table-for-include): New override.
+
+ * semantic/bovine/el.el: Remove emacs-lisp-mode-hook.
+
+ * semantic/complete.el (semantic-complete-post-command-hook): Exit
+ completion when user has deleted all characters from the prefix.
+ (semantic-displayor-focus-request): Return to previous window when
+ focussing tags.
+
+ * semantic/db-el.el (semanticdb-normalize-one-tag): Make obsolete.
+ (semanticdb-elisp-sym->tag): Use help-function-arglist instead.
+
+ * semantic/db-file.el (semanticdb-create-database): Use
+ semantic-tag-version instead of just semantic-version as the
+ initializer for the :semantic-tag-version slot.
+
+ * semantic/db-find.el (semanticdb-find-tags-by-class-method):
+ Delegate `include' to semantic-find-tags-included, which by
+ default will just call semantic-find-tags-by-class.
+
+ * semantic/db.el (semanticdb-refresh-table): Do not print warnings
+ when calling semantic-find-file-noselect. This avoids the "file
+ is write protected" messages when parsing system header files,
+ which might easily be mistaken to mean the currently loaded file.
+ (semanticdb-save-current-db, semanticdb-save-all-db): Only emit
+ message when running interactively.
+
+ * semantic/decorate/mode.el (semantic-decoration-mode): Activate
+ decoration of includes by default.
+
+ * semantic/doc.el (semantic-doc-snarf-comment-for-tag): Remove
+ comment delimiter at the end of the text.
+
+ * semantic/ede-grammar.el (semantic-ede-proj-target-grammar):
+ Change aux- and pre-load-packages.
+ (ede-proj-makefile-dependencies): Update pattern rule so that
+ resulting parsers are also byte-compiled.
+ (semantic-ede-grammar-compiler-bovine)
+ (semantic-ede-source-grammar-wisent): Remove .elc from gargage
+ pattern, since this is already covered by the elisp compiler.
+ (project-compile-target): Add compatibility code for Emacs 23,
+ which does not have `byte-recompile-file'.
+ (ede-proj-makefile-insert-rules): Add target specific EMACSFLAGS
+ to raise max-specpdl-size and max-lisp-eval-depth.
+
+ * semantic/find.el (semantic-find-tags-included): Make
+ overridable.
+
+ * semantic/fw.el (semantic-alias-obsolete)
+ (semantic-varalias-obsolete): Use byte-compile-warn.
+ (semantic-find-file-noselect): Disable font lock by calling
+ global-font-lock-mode.
+
+ * semantic/grammar.el (semantic-grammar-create-package): Fix
+ message.
+ (semantic-grammar-batch-build-one-package): When generating
+ parsers in batch-mode, ignore version control and make sure we do
+ not use cached versions.
+
+ * semantic/ia.el (semantic-ia-complete-symbol-menu): Bring back.
+
+ * semantic/lex-spp.el (semantic-lex-spp-symbol-merge): New fun.
+ (semantic-lex-spp-token-macro-to-macro-stream): Use it.
+ (semantic-lex-spp-lex-text-string): Instead of only setting the
+ lexer, call the major mode's setup function.
+
+ * semantic/scope.el (semantic-analyze-scoped-types-default): Use
+ semantic-tag-prototype-p.
+ (semantic-analyze-scope-nested-tags-default): Make sure we don't
+ return tags we already have in scopetypes.
+
+ * semantic/symref/filter.el
+ (semantic-symref-test-count-hits-in-tag): Restore.
+
+ * semantic/wisent/comp.el (wisent-BITS-PER-WORD): Use
+ most-positive-fixnum if available.
+
+ * semantic/wisent/javascript.el (semantic-tag-protection)
+ (semantic-analyze-scope-calculate-access)
+ (semantic-ctxt-current-symbol): New overrides.
+
+ * semantic/wisent/python.el (wisent-python-lex-beginning-of-line):
+ Rewrite to fix byte-compiler warning.
+
+2012-10-01 Robert Jarzmik <robert.jarzmik@free.fr>
+
+ * ede/linux.el (project-linux): New group.
+ (project-linux-compile-target-command)
+ (project-linux-compile-project-command): New options.
+ (project-compile-project, project-compiler-target): New methods.
+
+ * inversion.el (inversion-decoders): New regexps for SXEmacs.
+ (inversion-package-version): More verbose error message.
+ (inversion-<): Deal with new special cases.
+ (inversion-require-emacs): New argument sxemacs-ver; use it.
+
+2012-10-01 Nelson Ferreira <nelson.ferreira@ieee.org>
+
+ * ede/emacs.el (ede-emacs-version): Detect SXEmacs.
+
+2012-10-01 William Xu <william.xwl@gmail.com>
+
+ * semantic/bovine/gcc.el (semantic-gcc-query): Returns status when
+ there is an error.
+ (semantic-gcc-setup): If the first attempt at calling cpp fails,
+ try straight GCC.
+
+2012-10-01 Jan Moringen <jan.moringen@uni-bielefeld.de>
+
+ * semantic/idle.el
+ (semantic-idle-breadcrumbs--display-in-header-line): Escape
+ %-characters to avoid erroneous expansion in header line.
+ (semantic-idle-breadcrumbs--display-in-mode-line): Likewise.
+
+ * semantic/wisent/python.el (wisent-python-reconstitute-function-tag)
+ (wisent-python-reconstitute-class-tag, semantic-python-special-p)
+ (semantic-python-private-p, semantic-python-instance-variable-p)
+ (semantic-python-docstring-p): New functions.
+
+ * srecode/find.el (srecode-user-template-p): New function.
+ (srecode-all-template-hash): Accept new optional argument
+ predicate; return only templates matching the predicate.
+ (srecode-read-template-name): Only retrieve templates matching
+ srecode-user-template-p.
+
+ * srecode/insert.el (srecode-insert-show-error-report)
+ (srecode-insert-report-error): New functions.
+ (srecode-insert-variable-secondname-handler)
+ (srecode-insert-method, srecode-insert-ask-default)
+ (srecode-insert-variable-secondname-handler)
+ (srecode-insert-subtemplate, srecode-insert-method-helper)
+ (srecode-insert-include-lookup): Use them.
+
+2012-10-01 Thomas Bach <thbach@students.uni-mainz.de>
+
+ * semantic/wisent/python.el
+ (semantic-python-get-system-include-path): Add Python3k support.
+
+2012-10-01 Alexander Haeckel <_@_> (tiny change)
+
+ * srecode/getset.el (srecode-query-for-field): Return the first
+ tag found by name from all children tags.
+
+2012-10-01 Dale Sedivec <dale@codefu.org>
+
+ * semantic/wisent/python.el (wisent-python-string-start-re)
+ (wisent-python-string-re, wisent-python-forward-string)
+ (wisent-python-forward-line,wisent-python-lex-string): New
+ variables.
+ (wisent-python-forward-balanced-expression): New function.
+
+2012-10-01 Pete Beardmore <elbeardmorez@msn.com>
+
+ * semantic/complete.el (semantic-collector-calculate-completions):
+ Search for additional matches if new prefix is a substring of the
+ old prefix.
+ (semantic-displayor-next-action): Immediately show more
+ completions after user presses TAB the first time.
+ (semantic-displayor-tooltip-mode)
+ (semantic-displayor-tooltip-initial-max-tags)
+ (semantic-displayor-tooltip-max-tags): New defcustoms.
+ (semantic-displayor-tooltip): Use new variables as initforms. Use
+ new slot `mode' instead of `force-show'. Rename `max-tags' to
+ `max-tags-initial'.
+ (semantic-displayor-show-request): Display completions according
+ to new modes, and make variable names clearer.
+ (semantic-displayor-tooltip::semantic-displayor-scroll-request):
+ Use new max-tags-initial slot.
+
+ * semantic/idle.el (semantic-idle-local-symbol-highlight): Make
+ sure there actually is a tag at point.
+ (semantic-idle-completion-list-default): Report errors as messages
+ if semantic-idle-scheduler-verbose-flag is non-nil.
+
+2012-10-01 Richard Kim <emacs18@gmail.com>
+
+ * semantic/db-global.el (semanticdb-enable-gnu-global-databases):
+ Add optional NOERROR argument.
+
+2012-10-01 Alex Ott <alexott@gmail.com>
+
+ * semantic/idle.el (semantic-idle-scheduler-enabled-p): Fix
+ file-checking.
+
+2012-10-01 Darren Hoo <darren.hoo@gmail.com> (tiny change)
+
+ * semantic/db-find.el (semanticdb-find-default-throttle): Make
+ buffer-local.
+ (semanticdb-strip-find-results): Check for existing :filename
+ attribute, so that file information from GNU Global is not lost.
+
2012-08-07 Andreas Schwab <schwab@linux-m68k.org>
* ede/base.el (ede-with-projectfile): Use backquote forms.
(declare-function inversion-check-version "inversion")
-(defvar cedet-cscope-min-version "16.0"
+(defvar cedet-cscope-min-version "15.7"
"Minimum version of CScope required.")
(defcustom cedet-cscope-command "cscope"
nil)
(with-current-buffer b
(goto-char (point-min))
- (re-search-forward "GNU GLOBAL \\([0-9.]+\\)" nil t)
+ (re-search-forward "(?GNU GLOBAL)? \\([0-9.]+\\)" nil t)
(setq rev (match-string 1))
(if (inversion-check-version rev nil cedet-global-min-version)
(if noerror
nil)
(with-current-buffer b
(goto-char (point-min))
- (re-search-forward "fnid - \\([0-9.]+\\)" nil t)
- (setq rev (match-string 1))
+ (if (re-search-forward "fnid - \\([0-9.]+\\)" nil t)
+ (setq rev (match-string 1))
+ (setq rev "0"))
(if (inversion-check-version rev nil cedet-idutils-min-version)
(if noerror
nil
(declare-function inversion-find-version "inversion")
-(defconst cedet-version "1.0"
+(defconst cedet-version "1.1"
"Current version of CEDET.")
(defconst cedet-packages
`(
- ;;PACKAGE MIN-VERSION
- (cedet ,cedet-version)
- (eieio "1.3")
- (semantic "2.0")
- (srecode "1.0")
- (ede "1.0")
- (speedbar "1.0"))
- "Table of CEDET packages installed.")
+ ;;PACKAGE MIN-VERSION INSTALLDIR DOCDIR
+ (cedet ,cedet-version "common" "common" )
+ (eieio "1.4" nil "eieio" )
+ (semantic "2.1" nil "semantic/doc")
+ (srecode "1.1" nil "srecode" )
+ (ede "1.1" nil "ede" )
+ (speedbar "1.0.4" nil "speedbar" )
+ (cogre "1.1" nil "cogre" )
+ (cedet-contrib "1.1" "contrib" nil )
+ )
+ "Table of CEDET packages to install.")
(defvar cedet-menu-map ;(make-sparse-keymap "CEDET menu")
(let ((map (make-sparse-keymap "CEDET menu")))
PREBUTTONTEXT is some text to insert between prefix and the thing
that is not included in the indentation calculation of any children.
If PARENT is non-nil, it is somehow related as a parent to thing."
- (when (catch 'done
- (dolist (test data-debug-thing-alist)
- (when (funcall (car test) thing)
- (condition-case nil
- (funcall (cdr test) thing prefix prebuttontext parent)
- (error
- (funcall (cdr test) thing prefix prebuttontext)))
- (throw 'done nil))
- )
- nil)
- (data-debug-insert-simple-thing (format "%S" thing)
- prefix
- prebuttontext
- 'bold)))
+ (let ((inhibit-read-only t))
+ (when (catch 'done
+ (dolist (test data-debug-thing-alist)
+ (when (funcall (car test) thing)
+ (condition-case nil
+ (progn
+ (funcall (cdr test) thing prefix prebuttontext parent)
+ (throw 'done nil))
+ (error
+ (condition-case nil
+ (progn
+ (funcall (cdr test) thing prefix prebuttontext)
+ (throw 'done nil))
+ (error nil))))
+ ;; Only throw the 'done if no error was caught.
+ ;; If an error was caught, skip this predicate as being
+ ;; unsuccessful, and move on.
+ ))
+ nil)
+ (data-debug-insert-simple-thing (format "%S" thing)
+ prefix
+ prebuttontext
+ 'bold)))
+ (set-buffer-modified-p nil))
;;; MAJOR MODE
;;
(defvar data-debug-map
(let ((km (make-sparse-keymap)))
+ (suppress-keymap km)
(define-key km [mouse-2] 'data-debug-expand-or-contract-mouse)
(define-key km " " 'data-debug-expand-or-contract)
(define-key km "\C-m" 'data-debug-expand-or-contract)
(setq major-mode 'data-debug-mode
mode-name "DATA-DEBUG"
comment-start ";;"
- comment-end "")
+ comment-end ""
+ buffer-read-only t)
(set (make-local-variable 'comment-start-skip)
"\\(\\(^\\|[^\\\\\n]\\)\\(\\\\\\\\\\)*\\);+ *")
(set-syntax-table data-debug-mode-syntax-table)
(let ((b (get-buffer-create name)))
(pop-to-buffer b)
(set-buffer b)
+ (setq buffer-read-only nil) ; disable read-only
(erase-buffer)
(data-debug-mode)
b))
(when (or (not (data-debug-line-expandable-p))
(not (data-debug-current-line-expanded-p)))
;; If the next line is the same or less indentation, expand.
- (let ((fcn (get-text-property (point) 'ddebug-function)))
+ (let ((fcn (get-text-property (point) 'ddebug-function))
+ (inhibit-read-only t))
(when fcn
(funcall fcn (point))
(beginning-of-line)
;; Don't contract if the current line is not expandable.
(get-text-property (point) 'ddebug-function))
(let ((ti (current-indentation))
+ (inhibit-read-only t)
)
;; If next indentation is larger, collapse.
(end-of-line)
(error (setq end (point-max))))
(delete-region start end)
(forward-char -1)
- (beginning-of-line)))))
+ (beginning-of-line))))
+ (set-buffer-modified-p nil))
(defun data-debug-expand-or-contract ()
"Expand or contract anything at the current point."
(provide 'data-debug)
-(if (featurep 'eieio)
- (require 'eieio-datadebug))
-
;;; data-debug.el ends here
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Keywords: project, make
-;; Version: 1.0pre7
;; This file is part of GNU Emacs.
(define-key pmap "t" 'ede-new-target)
(define-key pmap "g" 'ede-rescan-toplevel)
(define-key pmap "s" 'ede-speedbar)
- (define-key pmap "l" 'ede-load-project-file)
(define-key pmap "f" 'ede-find-file)
(define-key pmap "C" 'ede-compile-project)
(define-key pmap "c" 'ede-compile-target)
(defun ede-buffer-belongs-to-project-p ()
"Return non-nil if this buffer belongs to at least one project."
(if (or (null ede-object) (consp ede-object)) nil
- (obj-of-class-p ede-object ede-project)))
+ (obj-of-class-p ede-object-project ede-project)))
(defun ede-menu-obj-of-class-p (class)
"Return non-nil if some member of `ede-object' is a child of CLASS."
(append
'( [ "Add Target" ede-new-target (ede-current-project) ]
[ "Remove Target" ede-delete-target ede-object ]
+ ( "Default configuration" :filter ede-configuration-forms-menu )
"-")
menu
))
menu)
)))))
+(defun ede-configuration-forms-menu (menu-def)
+ "Create a submenu for selecting the default configuration for this project.
+The current default is in the current object's CONFIGURATION-DEFAULT slot.
+All possible configurations are in CONFIGURATIONS.
+Argument MENU-DEF specifies the menu being created."
+ (easy-menu-filter-return
+ (easy-menu-create-menu
+ "Configurations"
+ (let* ((obj (ede-current-project))
+ (conf (when obj (oref obj configurations)))
+ (cdef (when obj (oref obj configuration-default)))
+ (menu nil))
+ (dolist (C conf)
+ (setq menu (cons (vector C (list 'ede-project-configurations-set C)
+ :style 'toggle
+ :selected (string= C cdef))
+ menu))
+ )
+ (nreverse menu)))))
+
+(defun ede-project-configurations-set (newconfig)
+ "Set the current project's current configuration to NEWCONFIG.
+This function is designed to be used by `ede-configuration-forms-menu'
+but can also be used interactively."
+ (interactive
+ (list (let* ((proj (ede-current-project))
+ (configs (oref proj configurations)))
+ (completing-read "New configuration: "
+ configs nil t
+ (oref proj configuration-default)))))
+ (oset (ede-current-project) configuration-default newconfig)
+ (message "%s will now build in %s mode."
+ (object-name (ede-current-project))
+ newconfig))
+
(defun ede-customize-forms-menu (menu-def)
"Create a menu of the project, and targets that can be customized.
Argument MENU-DEF is the definition of the current menu."
"Add target specific keybindings into the local map.
Optional argument DEFAULT indicates if this should be set to the default
version of the keymap."
- (let ((object (or ede-object ede-selected-object)))
+ (let ((object (or ede-object ede-selected-object))
+ (proj ede-object-project))
(condition-case nil
(let ((keys (ede-object-keybindings object)))
+ ;; Add keys for the project to whatever is in the current object
+ ;; so long as it isn't the same.
+ (when (not (eq object proj))
+ (setq keys (append keys (ede-object-keybindings proj))))
(while keys
(local-set-key (concat "\C-c." (car (car keys)))
(cdr (car keys)))
(defun ede-apply-target-options ()
"Apply options to the current buffer for the active project/target."
- (if (ede-current-project)
- (ede-set-project-variables (ede-current-project)))
+ (ede-apply-project-local-variables)
+ ;; Apply keymaps and preprocessor symbols.
(ede-apply-object-keymap)
(ede-apply-preprocessor-map)
)
(ede-apply-target-options)))))
-(defun ede-reset-all-buffers (onoff)
- "Reset all the buffers due to change in EDE.
-ONOFF indicates enabling or disabling the mode."
+(defun ede-reset-all-buffers ()
+ "Reset all the buffers due to change in EDE."
+ (interactive)
(let ((b (buffer-list)))
(while b
(when (buffer-file-name (car b))
(add-hook 'dired-mode-hook 'ede-turn-on-hook)
(add-hook 'kill-emacs-hook 'ede-save-cache)
(ede-load-cache)
- (ede-reset-all-buffers 1))
+ (ede-reset-all-buffers))
;; Turn off global-ede-mode
(define-key cedet-menu-map [cedet-menu-separator] nil)
(remove-hook 'semanticdb-project-predicate-functions 'ede-directory-project-p)
(remove-hook 'dired-mode-hook 'ede-turn-on-hook)
(remove-hook 'kill-emacs-hook 'ede-save-cache)
(ede-save-cache)
- (ede-reset-all-buffers -1)))
+ (ede-reset-all-buffers)))
(defvar ede-ignored-file-alist
'( "\\.cvsignore$"
;; the user chooses.
(if (ede-check-project-directory dir)
(progn
- ;; If there is a project in DIR, load it, otherwise do
- ;; nothing.
+ ;; Load the project in DIR, or make one.
(ede-load-project-file dir)
;; Check if we loaded anything on the previous line.
;; buffers may also be referring to this project.
;; Resetting all the buffers will get them to also point
;; at this new open project.
- (ede-reset-all-buffers 1)
+ (ede-reset-all-buffers)
;; ELSE
;; There was no project, so switch to `ede-new' which is how
(ede-deep-rescan t))
(project-rescan (ede-load-project-file toppath))
- (ede-reset-all-buffers 1))))
+ (ede-reset-all-buffers))))
(defun ede-new-target (&rest args)
"Create a new target specific to this type of project file.
a string \"y\" or \"n\", which answers the y/n question done interactively."
(interactive)
(apply 'project-new-target (ede-current-project) args)
- (setq ede-object nil)
- (setq ede-object (ede-buffer-object (current-buffer)))
- (ede-apply-target-options))
+ (when (and buffer-file-name
+ (not (file-directory-p buffer-file-name)))
+ (setq ede-object nil)
+ (setq ede-object (ede-buffer-object (current-buffer)))
+ (ede-apply-target-options)))
(defun ede-new-target-custom ()
"Create a new target specific to this type of project file."
(project-add-file target (buffer-file-name))
(setq ede-object nil)
- (setq ede-object (ede-buffer-object (current-buffer)))
+
+ ;; Setup buffer local variables.
+ (ede-initialize-state-current-buffer)
+
(when (not ede-object)
(error "Can't add %s to target %s: Wrong file type"
(file-name-nondirectory (buffer-file-name))
(defmethod ede-find-target ((proj ede-project) buffer)
"Fetch the target in PROJ belonging to BUFFER or nil."
(with-current-buffer buffer
- (or ede-object
- (if (ede-buffer-mine proj buffer)
- proj
- (let ((targets (oref proj targets))
- (f nil))
- (while targets
- (if (ede-buffer-mine (car targets) buffer)
- (setq f (cons (car targets) f)))
- (setq targets (cdr targets)))
- f)))))
+
+ ;; We can do a short-ut if ede-object local variable is set.
+ (if ede-object
+ ;; If the buffer is already loaded with good EDE stuff, make sure the
+ ;; saved project is the project we're looking for.
+ (when (and ede-object-project (eq proj ede-object-project)) ede-object)
+
+ ;; If the variable wasn't set, then we are probably initializing the buffer.
+ ;; In that case, search the file system.
+ (if (ede-buffer-mine proj buffer)
+ proj
+ (let ((targets (oref proj targets))
+ (f nil))
+ (while targets
+ (if (ede-buffer-mine (car targets) buffer)
+ (setq f (cons (car targets) f)))
+ (setq targets (cdr targets)))
+ f)))))
(defmethod ede-target-buffer-in-sourcelist ((this ede-target) buffer source)
"Return non-nil if object THIS is in BUFFER to a SOURCE list.
(pl nil))
(while bl
(with-current-buffer (car bl)
- (if (ede-buffer-belongs-to-project-p)
- (setq pl (cons (car bl) pl))))
+ (when (and ede-object (ede-find-target project (car bl)))
+ (setq pl (cons (car bl) pl))))
(setq bl (cdr bl)))
pl))
;;
;; These items are needed by ede-cpp-root to add better support for
;; configuring items for Semantic.
+
+;; Generic paths
+(defmethod ede-system-include-path ((this ede-project))
+ "Get the system include path used by project THIS."
+ nil)
+
+(defmethod ede-system-include-path ((this ede-target))
+ "Get the system include path used by project THIS."
+ nil)
+
+(defmethod ede-source-paths ((this ede-project) mode)
+ "Get the base to all source trees in the current projet for MODE.
+For example, <root>/src for sources of c/c++, Java, etc,
+and <root>/doc for doc sources."
+ nil)
+
+;; C/C++
(defun ede-apply-preprocessor-map ()
"Apply preprocessor tables onto the current buffer."
- (when (and ede-object (boundp 'semantic-lex-spp-macro-symbol-obarray))
+ (when (and ede-object
+ (boundp 'semantic-lex-spp-macro-symbol-obarray)
+ semantic-lex-spp-macro-symbol-obarray)
(let* ((objs ede-object)
(map (ede-preprocessor-map (if (consp objs)
(car objs)
"Get the pre-processor map for project THIS."
nil)
-(defmethod ede-system-include-path ((this ede-target))
- "Get the system include path used by project THIS."
- nil)
-
(defmethod ede-preprocessor-map ((this ede-target))
"Get the pre-processor map for project THIS."
nil)
+;; Java
+(defmethod ede-java-classpath ((this ede-project))
+ "Return the classpath for this project."
+ ;; @TODO - Can JDEE add something here?
+ nil)
+
\f
;;; Project-local variables
-;;
+
+(defun ede-set (variable value &optional proj)
+ "Set the project local VARIABLE to VALUE.
+If VARIABLE is not project local, just use set. Optional argument PROJ
+is the project to use, instead of `ede-current-project'."
+ (interactive "sVariable: \nxExpression: ")
+ (let ((p (or proj (ede-toplevel)))
+ a)
+ ;; Make the change
+ (ede-make-project-local-variable variable p)
+ (ede-set-project-local-variable variable value p)
+ (ede-commit-local-variables p)
+
+ ;; This is a heavy hammer, but will apply variables properly
+ ;; based on stacking between the toplevel and child projects.
+ (ede-map-buffers 'ede-apply-project-local-variables)
+
+ value))
+
+(defun ede-apply-project-local-variables (&optional buffer)
+ "Apply project local variables to the current buffer."
+ (with-current-buffer (or buffer (current-buffer))
+ ;; Always apply toplevel variables.
+ (if (not (eq (ede-current-project) (ede-toplevel)))
+ (ede-set-project-variables (ede-toplevel)))
+ ;; Next apply more local project's variables.
+ (if (ede-current-project)
+ (ede-set-project-variables (ede-current-project)))
+ ))
+
(defun ede-make-project-local-variable (variable &optional project)
"Make VARIABLE project-local to PROJECT."
- (if (not project) (setq project (ede-current-project)))
+ (if (not project) (setq project (ede-toplevel)))
(if (assoc variable (oref project local-variables))
nil
(oset project local-variables (cons (list variable)
- (oref project local-variables)))
- (dolist (b (ede-project-buffers project))
- (with-current-buffer b
- (make-local-variable variable)))))
+ (oref project local-variables)))))
+
+(defun ede-set-project-local-variable (variable value &optional project)
+ "Set VARIABLE to VALUE for PROJECT.
+If PROJ isn't specified, use the current project.
+This function only assigns the value within the project structure.
+It does not apply the value to buffers."
+ (if (not project) (setq project (ede-toplevel)))
+ (let ((va (assoc variable (oref project local-variables))))
+ (unless va
+ (error "Cannot set project variable until it is added with `ede-make-project-local-variable'"))
+ (setcdr va value)))
(defmethod ede-set-project-variables ((project ede-project) &optional buffer)
"Set variables local to PROJECT in BUFFER."
(with-current-buffer buffer
(dolist (v (oref project local-variables))
(make-local-variable (car v))
- ;; set its value here?
(set (car v) (cdr v)))))
-(defun ede-set (variable value &optional proj)
- "Set the project local VARIABLE to VALUE.
-If VARIABLE is not project local, just use set. Optional argument PROJ
-is the project to use, instead of `ede-current-project'."
- (let ((p (or proj (ede-current-project)))
- a)
- (if (and p (setq a (assoc variable (oref p local-variables))))
- (progn
- (setcdr a value)
- (dolist (b (ede-project-buffers p))
- (with-current-buffer b
- (set variable value))))
- (set variable value))
- (ede-commit-local-variables p))
- value)
-
(defmethod ede-commit-local-variables ((proj ede-project))
"Commit change to local variables in PROJ."
nil)
(declare-function ede-directory-safe-p "ede")
(declare-function ede-add-project-to-global-list "ede")
+(defclass ede-project-autoload-dirmatch ()
+ ((fromconfig :initarg :fromconfig
+ :initform nil
+ :documentation
+ "A config file within which the match pattern lives.")
+ (configregex :initarg :configregex
+ :initform nil
+ :documentation
+ "A regexp to identify the dirmatch pattern.")
+ (configregexidx :initarg :configregexidx
+ :initform nil
+ :documentation
+ "An index into the match-data of `configregex'.")
+ (configdatastash :initform nil
+ :documentation
+ "Save discovered match string.")
+ )
+ "Support complex matches for projects that live in named directories.
+For most cases, a simple string is sufficient. If, however, a project
+location is varied dependent on other complex criteria, this class
+can be used to define that match without loading the specific project
+into memory.")
+
+(defmethod ede-dirmatch-installed ((dirmatch ede-project-autoload-dirmatch))
+ "Return non-nil if the tool DIRMATCH might match is installed on the system."
+ (let ((fc (oref dirmatch fromconfig)))
+
+ (cond
+ ;; If the thing to match is stored in a config file.
+ ((stringp fc)
+ (file-exists-p fc))
+
+ ;; Add new types of dirmatches here.
+
+ ;; Error for wierd stuff
+ (t (error "Unknown dirmatch type.")))))
+
+
+(defmethod ede-do-dirmatch ((dirmatch ede-project-autoload-dirmatch) file)
+ "Does DIRMATCH match the filename FILE."
+ (let ((fc (oref dirmatch fromconfig)))
+
+ (cond
+ ;; If the thing to match is stored in a config file.
+ ((stringp fc)
+ (when (file-exists-p fc)
+ (let ((matchstring (oref dirmatch configdatastash)))
+ (unless matchstring
+ (save-current-buffer
+ (let* ((buff (get-file-buffer fc))
+ (readbuff
+ (let ((find-file-hook nil)) ;; Disable ede from recursing
+ (find-file-noselect fc))))
+ (set-buffer readbuff)
+ (save-excursion
+ (goto-char (point-min))
+ (when (re-search-forward (oref dirmatch configregex) nil t)
+ (setq matchstring
+ (match-string (or (oref dirmatch configregexidx) 0)))))
+ (if (not buff) (kill-buffer readbuff))))
+ ;; Save what we find in our cache.
+ (oset dirmatch configdatastash matchstring))
+ ;; Match against our discovered string
+ (and matchstring (string-match (regexp-quote matchstring) file))
+ )))
+
+ ;; Add new matches here
+ ;; ((stringp somenewslot ...)
+ ;; )
+
+ ;; Error if none others known
+ (t
+ (error "Unknown dirmatch object match style.")))
+ ))
+
+(declare-function ede-directory-safe-p "ede")
+(declare-function ede-add-project-to-global-list "ede")
+
(defclass ede-project-autoload ()
((name :initarg :name
:documentation "Name of this project type")
:documentation "The lisp file belonging to this class.")
(proj-file :initarg :proj-file
:documentation "Name of a project file of this type.")
+ (proj-root-dirmatch :initarg :proj-root-dirmatch
+ :initform ""
+ :type (or string ede-project-autoload-dirmatch)
+ :documentation
+ "To avoid loading a project, check if the directory matches this.
+For projects that use directory name matches, a function would load that project.
+Specifying this matcher will allow EDE to check without loading the project.")
(proj-root :initarg :proj-root
:type function
:documentation "A function symbol to call for the project root.
:documentation "Fn symbol used to load this project file.")
(class-sym :initarg :class-sym
:documentation "Symbol representing the project class to use.")
+ (generic-p :initform nil
+ :documentation
+ "Generic projects are added to the project list at the end.
+The add routine will set this to non-nil so that future non-generic placement will
+be successful.")
(new-p :initarg :new-p
:initform t
:documentation
:proj-file "Makefile.am"
:load-type 'project-am-load
:class-sym 'project-am-makefile
- :new-p nil))
+ :new-p nil
+ :safe-p t)
+ )
"List of vectors defining how to determine what type of projects exist.")
(put 'ede-project-class-files 'risky-local-variable t)
+(defun ede-add-project-autoload (projauto &optional flag)
+ "Add PROJAUTO, an EDE autoload definition to `ede-project-class-files'.
+Optional argument FLAG indicates how this autoload should be
+added. Possible values are:
+ 'generic - A generic project type. Keep this at the very end.
+ 'unique - A unique project type for a specific project. Keep at the very
+ front of the list so more generic projects don't get priority."
+ ;; First, can we identify PROJAUTO as already in the list? If so, replace.
+ (let ((projlist ede-project-class-files)
+ (projname (object-name-string projauto)))
+ (while (and projlist (not (string= (object-name-string (car projlist)) projname)))
+ (setq projlist (cdr projlist)))
+
+ (if projlist
+ ;; Stick the new one into the old slot.
+ (setcar projlist projauto)
+
+ ;; Else, see where to insert it.
+ (cond ((and flag (eq flag 'unique))
+ ;; Unique items get stuck right onto the front.
+ (setq ede-project-class-files
+ (cons projauto ede-project-class-files)))
+
+ ;; Generic Projects go at the very end of the list.
+ ((and flag (eq flag 'generic))
+ (oset projauto generic-p t)
+ (setq ede-project-class-files
+ (append ede-project-class-files
+ (list projauto))))
+
+ ;; Normal projects go at the end of the list, but
+ ;; before the generic projects.
+ (t
+ (let ((prev nil)
+ (next ede-project-class-files))
+ (while (and next (not (oref (car next) generic-p)))
+ (setq prev next
+ next (cdr next)))
+ (when (not prev)
+ (error "ede-project-class-files not initialized"))
+ ;; Splice into the list.
+ (setcdr prev (cons projauto next))))))))
+
;;; EDE project-autoload methods
;;
(defmethod ede-project-root ((this ede-project-autoload))
Allows for one-project-object-for-a-tree type systems."
nil)
+(defun ede-project-dirmatch-p (file dirmatch)
+ "Return non-nil if FILE matches DIRMATCH.
+DIRMATCH could be nil (no match), a string (regexp match),
+or an `ede-project-autoload-dirmatch' object."
+ ;; If dirmatch is a string, then we simply match it against
+ ;; the file we are testing.
+ (if (stringp dirmatch)
+ (string-match dirmatch file)
+ ;; if dirmatch is instead a dirmatch object, we test against
+ ;; that object instead.
+ (if (ede-project-autoload-dirmatch-p dirmatch)
+ (ede-do-dirmatch dirmatch file)
+ (error "Unknown project directory match type."))
+ ))
+
(defmethod ede-project-root-directory ((this ede-project-autoload)
&optional file)
"If a project knows its root, return it here.
(when (not file)
(setq file default-directory))
(when (slot-boundp this :proj-root)
- (let ((rootfcn (oref this proj-root)))
+ (let ((dirmatch (oref this proj-root-dirmatch))
+ (rootfcn (oref this proj-root))
+ (callfcn t))
(when rootfcn
- (condition-case nil
- (funcall rootfcn file)
- (error
- (funcall rootfcn)))
+ (if ;; If the dirmatch (an object) is not installed, then we
+ ;; always skip doing a match.
+ (and (ede-project-autoload-dirmatch-p dirmatch)
+ (not (ede-dirmatch-installed dirmatch)))
+ (setq callfcn nil)
+ ;; Other types of dirmatch:
+ (when (and
+ ;; If the Emacs Lisp file handling this project hasn't
+ ;; been loaded, we will use the quick dirmatch feature.
+ (not (featurep (oref this file)))
+ ;; If the dirmatch is an empty string, then we always
+ ;; skip doing a match.
+ (not (and (stringp dirmatch) (string= dirmatch "")))
+ )
+ ;; If this file DOES NOT match dirmatch, we set the callfcn
+ ;; to nil, meaning don't load the ede support file for this
+ ;; type of project. If it does match, we will load the file
+ ;; and use a more accurate programatic match from there.
+ (unless (ede-project-dirmatch-p file dirmatch)
+ (setq callfcn nil))))
+ ;; Call into the project support file for a match.
+ (when callfcn
+ (condition-case nil
+ (funcall rootfcn file)
+ (error
+ (funcall rootfcn))))
))))
(defmethod ede-dir-to-projectfile ((this ede-project-autoload) dir)
(let* ((d (file-name-as-directory dir))
(root (ede-project-root-directory this d))
(pf (oref this proj-file))
+ (dm (oref this proj-root-dirmatch))
(f (cond ((stringp pf)
(expand-file-name pf (or root d)))
((and (symbolp pf) (fboundp pf))
- (funcall pf (or root d)))))
+ ;; If there is a symbol to call, lets make extra
+ ;; sure we really can call it without loading in
+ ;; other EDE projects. This happens if the file is
+ ;; already loaded, or if there is a dirmatch, but
+ ;; root is empty.
+ (when (and (featurep (oref this file))
+ (or (not (stringp dm))
+ (not (string= dm "")))
+ root)
+ (funcall pf (or root d))))))
)
(when (and f (file-exists-p f))
f)))
(setq param (substring param (match-end 0))))
(when (string-match "\\s-*\\]?\\s-*\\'" param)
(setq param (substring param 0 (match-beginning 0))))
+ ;; Look for occurances of backslash newline
+ (while (string-match "\\s-*\\\\\\s-*\n\\s-*" param)
+ (setq param (replace-match " " t t param)))
param)
(defun autoconf-parameters-for-macro (macro &optional ignore-bol ignore-case)
(string= autoconf-deleted-text autoconf-inserted-text))
(set-buffer-modified-p nil))))
+(defun autoconf-parameter-count ()
+ "Return the number of parameters to the function on the current line."
+ (save-excursion
+ (beginning-of-line)
+ (let* ((end-of-cmd
+ (save-excursion
+ (if (re-search-forward "(" (point-at-eol) t)
+ (progn
+ (forward-char -1)
+ (forward-sexp 1)
+ (point))
+ ;; Else, just return EOL.
+ (point-at-eol))))
+ (cnt 0))
+ (save-restriction
+ (narrow-to-region (point-at-bol) end-of-cmd)
+ (condition-case nil
+ (progn
+ (down-list 1)
+ (while (re-search-forward ", ?" end-of-cmd t)
+ (setq cnt (1+ cnt)))
+ (cond ((> cnt 1)
+ ;; If the # is > 1, then there is one fewer , than args.
+ (1+ cnt))
+ ((not (looking-at "\\s-*)"))
+ ;; If there are 0 args, then we have to see if there is one arg.
+ (1+ cnt))
+ (t
+ ;; Else, just return the 0.
+ cnt)))
+ (error 0))))))
+
(defun autoconf-delete-parameter (index)
"Delete the INDEXth parameter from the macro starting on the current line.
Leaves the cursor where a new parameter can be inserted.
"Set the version used with automake to VERSION."
(if (not (stringp version))
(signal 'wrong-type-argument '(stringp version)))
- (if (not (autoconf-find-last-macro "AM_INIT_AUTOMAKE"))
- (error "Cannot update version")
- ;; Move to correct position.
+ (if (and (autoconf-find-last-macro "AM_INIT_AUTOMAKE")
+ (>= (autoconf-parameter-count) 2))
+ ;; We can edit right here.
+ nil
+ ;; Else, look for AC init instead.
+ (if (not (and (autoconf-find-last-macro "AC_INIT")
+ (>= (autoconf-parameter-count) 2)))
+ (error "Cannot update version")))
+
+ ;; Perform the edit.
(autoconf-edit-cycle
(autoconf-delete-parameter 2)
- (autoconf-insert version))))
+ (autoconf-insert (concat "[" version "]"))))
(defun autoconf-set-output (outputlist)
"Set the files created in AC_OUTPUT to OUTPUTLIST.
:documentation "Sub projects controlled by this project.
For Automake based projects, each directory is treated as a project.")
(targets :initarg :targets
- :type list
+ :type ede-target-list
:custom (repeat (object :objectcreatefcn ede-new-target-custom))
:label "Local Targets"
:group (targets)
"For the project in which OBJ resides, execute FORMS."
`(save-window-excursion
(let* ((pf (if (obj-of-class-p ,obj ede-target)
- ;; @todo -I think I can change
- ;; this to not need ede-load-project-file
- ;; but I'm not sure how to test well.
- (ede-load-project-file (oref ,obj path))
+ (ede-target-parent ,obj)
,obj))
(dbka (get-file-buffer (oref pf file))))
(if (not dbka) (find-file (oref pf file))
;; file name for a header in your project where most of your CPP
;; macros reside. Doing this can be easier than listing everything in
;; the :spp-table option. The files listed in :spp-files should not
-;; start with a /, and are relative to something in :include-path.;;
+;; start with a /, and are relative to something in :include-path.
;;
;; If you want to override the file-finding tool with your own
;; function you can do this:
;; :proj-file 'MY-FILE-FOR-DIR
;; :proj-root 'MY-ROOT-FCN
;; :load-type 'MY-LOAD
-;; :class-sym 'ede-cpp-root)
+;; :class-sym 'ede-cpp-root-project
+;; :safe-p t)
;; t)
;;
;;; TODO
(ede-cpp-root-file-existing dir))
;;;###autoload
-(add-to-list 'ede-project-class-files
- (ede-project-autoload "cpp-root"
- :name "CPP ROOT"
- :file 'ede/cpp-root
- :proj-file 'ede-cpp-root-project-file-for-dir
- :proj-root 'ede-cpp-root-project-root
- :load-type 'ede-cpp-root-load
- :class-sym 'ede-cpp-root
- :new-p nil)
- t)
+(ede-add-project-autoload
+ (ede-project-autoload "cpp-root"
+ :name "CPP ROOT"
+ :file 'ede-cpp-root
+ :proj-file 'ede-cpp-root-project-file-for-dir
+ :proj-root 'ede-cpp-root-project-root
+ :load-type 'ede-cpp-root-load
+ :class-sym 'ede-cpp-root
+ :new-p nil
+ :safe-p t)
+ ;; When a user creates one of these, it should override any other project
+ ;; type that might happen to be in this directory, so force this to the
+ ;; very front.
+ 'unique)
;;; CLASSES
;;
;; Else, do the usual.
(setq ans (call-next-method)))
)))
+ ;; TODO - does this call-next-method happen twice. Is that bad?? Why is it here?
(or ans (call-next-method))))
(defmethod ede-project-root ((this ede-cpp-root-project))
(table (when expfile
(semanticdb-file-table-object expfile)))
)
- (when (not table)
- (message "Cannot find file %s in project." F))
- (when (and table (semanticdb-needs-refresh-p table))
- (semanticdb-refresh-table table)
+ (if (not table)
+ (message "Cannot find file %s in project." F)
+ (when (semanticdb-needs-refresh-p table)
+ (semanticdb-refresh-table table))
(setq spp (append spp (oref table lexical-table))))))
(oref this spp-files))
spp))
(defmethod ede-system-include-path ((this ede-cpp-root-target))
- "Get the system include path used by project THIS."
+ "Get the system include path used by target THIS."
(ede-system-include-path (ede-target-parent this)))
(defmethod ede-preprocessor-map ((this ede-cpp-root-target))
(setq ede-dired-minor-mode nil)
(error "Not in DIRED mode"))
(unless (or (ede-directory-project-p default-directory)
- (interactive-p))
+ (called-interactively-p 'any))
(setq ede-dired-minor-mode nil)))
(defun ede-dired-add-to-target (target)
(match-string 2) "."
(match-string 3)))
)
+ ((file-exists-p "sxemacs.pc.in")
+ (setq emacs "SXEmacs")
+ (insert-file-contents "sxemacs_version.m4")
+ (goto-char (point-min))
+ (re-search-forward "m4_define(\\[SXEM4CS_MAJOR_VERSION\\], \\[\\([0-9]+\\)\\])
+m4_define(\\[SXEM4CS_MINOR_VERSION\\], \\[\\([0-9]+\\)\\])
+m4_define(\\[SXEM4CS_BETA_VERSION\\], \\[\\([0-9]+\\)\\])")
+ (setq ver (concat (match-string 1) "."
+ (match-string 2) "."
+ (match-string 3)))
+ )
;; Insert other Emacs here...
;; Vaguely recent version of GNU Emacs?
ROOTPROJ is nil, since there is only one project."
(or (ede-emacs-file-existing dir)
;; Doesn't already exist, so let's make one.
- (let* ((vertuple (ede-emacs-version dir)))
- (ede-emacs-project (car vertuple)
- :name (car vertuple)
- :version (cdr vertuple)
- :directory (file-name-as-directory dir)
- :file (expand-file-name "src/emacs.c"
- dir)))
- (ede-add-project-to-global-list this)
- )
- )
+ (let* ((vertuple (ede-emacs-version dir))
+ (proj (ede-emacs-project
+ (car vertuple)
+ :name (car vertuple)
+ :version (cdr vertuple)
+ :directory (file-name-as-directory dir)
+ :file (expand-file-name "src/emacs.c"
+ dir))))
+ (ede-add-project-to-global-list proj))))
;;;###autoload
-(add-to-list 'ede-project-class-files
- (ede-project-autoload "emacs"
- :name "EMACS ROOT"
- :file 'ede/emacs
- :proj-file "src/emacs.c"
- :proj-root 'ede-emacs-project-root
- :load-type 'ede-emacs-load
- :class-sym 'ede-emacs-project
- :new-p nil)
- t)
+(ede-add-project-autoload
+ (ede-project-autoload "emacs"
+ :name "EMACS ROOT"
+ :file 'ede/emacs
+ :proj-file "src/emacs.c"
+ :proj-root-dirmatch "emacs[^/]*"
+ :proj-root 'ede-emacs-project-root
+ :load-type 'ede-emacs-load
+ :class-sym 'ede-emacs-project
+ :new-p nil
+ :safe-p t)
+ 'unique)
(defclass ede-emacs-target-c (ede-target)
()
(interactive)
(require 'ede/locate)
(let* ((loc (ede-get-locator-object (ede-current-project))))
- (ede-locate-flush-hash loc)))
+ (when loc
+ (ede-locate-flush-hash loc))))
;;; Placeholders for ROOT directory scanning on base objects
;;
(when (not ans)
(if (equal (ede--project-inode SP) inode)
(setq ans SP)
- (ede-find-subproject-for-directory SP dir)))))
+ (setq ans (ede-find-subproject-for-directory SP dir))))))
ans)))
;;; DIRECTORY IN OPEN PROJECT
:test 'equal)
"A hash of directory names and associated EDE objects.")
+(defun ede-flush-directory-hash ()
+ "Flush the project directory hash.
+Do this only when developing new projects that are incorrectly putting
+'nomatch tokens into the hash."
+ (interactive)
+ (setq ede-project-directory-hash (make-hash-table :test 'equal))
+ ;; Also slush the current project's locator hash.
+ (let ((loc (ede-get-locator-object ede-object)))
+ (when loc
+ (ede-locate-flush-hash loc)))
+ )
+
(defun ede-project-directory-remove-hash (dir)
"Reset the directory hash for DIR.
Do this whenever a new project is created, as opposed to loaded."
;; Make sure we have a location object available for
;; caching values, and for locating things more robustly.
(let ((top (ede-toplevel proj)))
- (when (not (slot-boundp top 'locate-obj))
- (ede-enable-locate-on-project top))
- (oref top locate-obj)
- ))
+ (when top
+ (when (not (slot-boundp top 'locate-obj))
+ (ede-enable-locate-on-project top))
+ (oref top locate-obj)
+ )))
(defmethod ede-expand-filename ((this ede-project) filename &optional force)
"Return a fully qualified file name based on project THIS.
(require 'eieio-opt)
(require 'ede)
+(require 'ede/shell)
(require 'semantic/db)
;;; Code:
:group (default build)
:documentation
"Command used for debugging this project.")
+ (run-command :initarg :run-command
+ :initform nil
+ :type (or null string)
+ :custom string
+ :group (default build)
+ :documentation
+ "Command used to run something related to this project.")
;; C target customizations
(c-include-path :initarg :c-include-path
:initform nil
(oref proj :directory))))
(if (file-exists-p fname)
;; Load in the configuration
- (setq config (eieio-persistent-read fname))
+ (setq config (eieio-persistent-read fname 'ede-generic-config))
;; Create a new one.
(setq config (ede-generic-config
"Configuration"
(config (ede-generic-get-configuration proj)))
(oref config c-include-path)))
+;;; Commands
+;;
+(defmethod project-compile-project ((proj ede-generic-project) &optional command)
+ "Compile the entire current project PROJ.
+Argument COMMAND is the command to use when compiling."
+ (let* ((config (ede-generic-get-configuration proj))
+ (comp (oref config :build-command)))
+ (compile comp)))
+
+(defmethod project-compile-target ((obj ede-generic-target) &optional command)
+ "Compile the current target OBJ.
+Argument COMMAND is the command to use for compiling the target."
+ (project-compile-project (ede-current-project) command))
+
+(defmethod project-debug-target ((target ede-generic-target))
+ "Run the current project derived from TARGET in a debugger."
+ (let* ((proj (ede-target-parent target))
+ (config (ede-generic-get-configuration proj))
+ (debug (oref config :debug-command))
+ (cmd (read-from-minibuffer
+ "Debug Command: "
+ debug))
+ (cmdsplit (split-string cmd " " t))
+ ;; @TODO - this depends on the user always typing in something good
+ ;; like "gdb" or "dbx" which also exists as a useful Emacs command.
+ ;; Is there a better way?
+ (cmdsym (intern-soft (car cmdsplit))))
+ (call-interactively cmdsym t)))
+
+(defmethod project-run-target ((target ede-generic-target))
+ "Run the current project derived from TARGET."
+ (require 'ede-shell)
+ (let* ((proj (ede-target-parent target))
+ (config (ede-generic-get-configuration proj))
+ (run (concat "./" (oref config :run-command)))
+ (cmd (read-from-minibuffer "Run (like this): " run)))
+ (ede-shell-run-something target cmd)))
+
;;; Customization
;;
(defmethod ede-customize ((proj ede-generic-project))
a Makefile, or SConstruct file.
CLASS is the EIEIO class that is used to track this project. It should subclass
the class `ede-generic-project' project."
- (add-to-list 'ede-project-class-files
- (ede-project-autoload internal-name
- :name external-name
- :file 'ede/generic
- :proj-file projectfile
- :load-type 'ede-generic-load
- :class-sym class
- :new-p nil)
- ;; Generics must go at the end, since more specific types
- ;; can create Makefiles also.
- t))
+ (ede-add-project-autoload
+ (ede-project-autoload internal-name
+ :name external-name
+ :file 'ede/generic
+ :proj-file projectfile
+ :load-type 'ede-generic-load
+ :class-sym class
+ :new-p nil
+ :safe-p nil) ; @todo - could be
+ ; safe if we do something
+ ; about the loading of the
+ ; generic config file.
+ ;; Generics must go at the end, since more specific types
+ ;; can create Makefiles also.
+ 'generic))
;;;###autoload
(defun ede-enable-generic-projects ()
"Enable generic project loaders."
(interactive)
- (ede-generic-new-autoloader "edeproject-makefile" "Make"
+ (ede-generic-new-autoloader "generic-makefile" "Make"
"Makefile" 'ede-generic-makefile-project)
- (ede-generic-new-autoloader "edeproject-scons" "SCons"
+ (ede-generic-new-autoloader "generic-scons" "SCons"
"SConstruct" 'ede-generic-scons-project)
- (ede-generic-new-autoloader "edeproject-cmake" "CMake"
+ (ede-generic-new-autoloader "generic-cmake" "CMake"
"CMakeLists" 'ede-generic-cmake-project)
)
;; * Add website
(require 'ede)
+(require 'ede/make)
+
(declare-function semanticdb-file-table-object "semantic/db")
(declare-function semanticdb-needs-refresh-p "semantic/db")
(declare-function semanticdb-refresh-table "semantic/db")
;;; Code:
+(defgroup project-linux nil
+ "File and tag browser frame."
+ :group 'tools
+ :group 'ede
+ )
+
+(defcustom project-linux-compile-target-command (concat ede-make-command " -k -C %s SUBDIRS=%s")
+ "*Default command used to compile a target."
+ :group 'project-linux
+ :type 'string)
+
+(defcustom project-linux-compile-project-command (concat ede-make-command " -k -C %s")
+ "*Default command used to compile a project."
+ :group 'project-linux
+ :type 'string)
+
(defvar ede-linux-project-list nil
"List of projects created by option `ede-linux-project'.")
"Project Type for the Linux source code."
:method-invocation-order :depth-first)
+;;;###autoload
(defun ede-linux-load (dir &optional rootproj)
"Return an Linux Project object if there is a match.
Return nil if there isn't one.
ROOTPROJ is nil, since there is only one project."
(or (ede-linux-file-existing dir)
;; Doesn't already exist, so let's make one.
- (ede-linux-project "Linux"
- :name "Linux"
- :version (ede-linux-version dir)
- :directory (file-name-as-directory dir)
- :file (expand-file-name "scripts/ver_linux"
- dir))
- (ede-add-project-to-global-list this)
- )
- )
+ (let ((proj (ede-linux-project
+ "Linux"
+ :name "Linux"
+ :version (ede-linux-version dir)
+ :directory (file-name-as-directory dir)
+ :file (expand-file-name "scripts/ver_linux"
+ dir))))
+ (ede-add-project-to-global-list proj))
+ ))
;;;###autoload
-(add-to-list 'ede-project-class-files
- (ede-project-autoload "linux"
- :name "LINUX ROOT"
- :file 'ede/linux
- :proj-file "scripts/ver_linux"
- :proj-root 'ede-linux-project-root
- :load-type 'ede-linux-load
- :class-sym 'ede-linux-project
- :new-p nil)
- t)
+(ede-add-project-autoload
+ (ede-project-autoload "linux"
+ :name "LINUX ROOT"
+ :file 'ede/linux
+ :proj-file "scripts/ver_linux"
+ :proj-root-dirmatch "linux[^/]*"
+ :proj-root 'ede-linux-project-root
+ :load-type 'ede-linux-load
+ :class-sym 'ede-linux-project
+ :new-p nil
+ :safe-p t)
+ 'unique)
(defclass ede-linux-target-c (ede-target)
()
)
(or F (call-next-method))))
+(defmethod project-compile-project ((proj ede-linux-project)
+ &optional command)
+ "Compile the entire current project.
+Argument COMMAND is the command to use when compiling."
+ (let* ((dir (ede-project-root-directory proj)))
+
+ (require 'compile)
+ (if (not project-linux-compile-project-command)
+ (setq project-linux-compile-project-command compile-command))
+ (if (not command)
+ (setq command
+ (format
+ project-linux-compile-project-command
+ dir)))
+
+ (compile command)))
+
+(defmethod project-compile-target ((obj ede-linux-target-c) &optional command)
+ "Compile the current target.
+Argument COMMAND is the command to use for compiling the target."
+ (let* ((proj (ede-target-parent obj))
+ (root (ede-project-root proj))
+ (dir (ede-project-root-directory root))
+ (subdir (oref obj path)))
+
+ (require 'compile)
+ (if (not project-linux-compile-project-command)
+ (setq project-linux-compile-project-command compile-command))
+ (if (not command)
+ (setq command
+ (format
+ project-linux-compile-target-command
+ dir subdir)))
+
+ (compile command)))
+
(provide 'ede/linux)
;; Local variables:
"Return a list of all files in MACRO."
(save-excursion
(goto-char (point-min))
- (let ((lst nil))
+ (let ((lst nil)
+ (case-fold-search nil))
(while (makefile-move-to-macro macro t)
(let ((e (save-excursion
(makefile-end-of-command)
"Add VARNAME into the current Makefile if it doesn't exist.
Execute BODY in a location where a value can be placed."
`(let ((addcr t) (v ,varname))
- (unless (re-search-backward (concat "^" v "\\s-*=") nil t)
- (insert v "=")
- ,@body
- (if addcr (insert "\n"))
- (goto-char (point-max)))
- ))
+ (unless
+ (save-excursion
+ (re-search-backward (concat "^" v "\\s-*=") nil t))
+ (insert v "=")
+ ,@body
+ (when addcr (insert "\n"))
+ (goto-char (point-max)))))
(put 'ede-pmake-insert-variable-once 'lisp-indent-function 1)
;;; SOURCE VARIABLE NAME CONSTRUCTION
(defmethod ede-proj-makefile-insert-rules ((this ede-makefile-rule))
"Insert rules needed for THIS rule object."
- (if (oref this phony) (insert ".PHONY: (oref this target)\n"))
+ (if (oref this phony) (insert ".PHONY: " (oref this target) "\n"))
(insert (oref this target) ": " (oref this dependencies) "\n\t"
(mapconcat (lambda (c) c) (oref this rules) "\n\t")
"\n\n"))
(when (slot-boundp this 'commands)
(with-slots (commands) this
(mapc
- (lambda (obj) (insert "\t"
- (cond ((stringp obj)
- obj)
- ((and (listp obj)
- (eq (car obj) 'lambda))
- (funcall obj))
- (t
- (format "%S" obj)))
- "\n"))
+ (lambda (obj) (insert
+ (if (bolp) "\t" " ")
+ (cond ((stringp obj)
+ obj)
+ ((and (listp obj)
+ (eq (car obj) 'lambda))
+ (funcall obj))
+ (t
+ (format "%S" obj)))
+ "\n"))
commands))
(insert "\n")))
There should only be one toplevel package per auxiliary tool needed.
These packages location is found, and added to the compile time
load path."
- ))
+ )
+ (pre-load-packages :initarg :pre-load-packages
+ :initform nil
+ :type list
+ :custom (repeat string)
+ :documentation "Additional packages to pre-load.
+Each package name will be loaded with `require'.
+Each package's directory should also appear in :aux-packages via a package name.")
+ )
"This target consists of a group of lisp files.
A lisp target may be one general program with many separate lisp files in it.")
+(defmethod ede-proj-makefile-insert-rules :after ((this ede-proj-target-elisp))
+ "Insert rules needed by THIS target.
+This inserts the PRELOADS target-local variable."
+ (let ((preloads (oref this pre-load-packages)))
+ (when preloads
+ (insert (format "%s: PRELOADS=%s\n"
+ (oref this name)
+ (mapconcat 'identity preloads " ")))))
+ (insert "\n"))
+
+(defmethod ede-proj-makefile-dependencies ((this ede-proj-target-elisp))
+ "Return a string representing the dependencies for THIS.
+Some compilers only use the first element in the dependencies, others
+have a list of intermediates (object files), and others don't care.
+This allows customization of how these elements appear.
+For Emacs Lisp, return addsuffix command on source files."
+ (format "$(addsuffix c, $(%s))"
+ (ede-proj-makefile-sourcevar this)))
+
(defvar ede-source-emacs
(ede-sourcecode "ede-emacs-source"
:name "Emacs Lisp"
"ede-emacs-compiler"
:name "emacs"
:variables '(("EMACS" . "emacs")
- ("EMACSFLAGS" . "-batch --no-site-file"))
- :commands
- '("@echo \"(add-to-list 'load-path nil)\" > $@-compile-script"
- "for loadpath in . ${LOADPATH}; do \\"
- " echo \"(add-to-list 'load-path \\\"$$loadpath\\\")\" >> $@-compile-script; \\"
- "done;"
- "@echo \"(setq debug-on-error t)\" >> $@-compile-script"
- "\"$(EMACS)\" $(EMACSFLAGS) -l $@-compile-script -f batch-byte-compile $^"
- )
+ ("EMACSFLAGS" . "-batch --no-site-file --eval '(setq debug-on-error t)'")
+ ("require" . "$(foreach r,$(1),(require (quote $(r))))"))
+ :rules (list (ede-makefile-rule
+ "elisp-inference-rule"
+ :target "%.elc"
+ :dependencies "%.el"
+ :rules '("$(EMACS) $(EMACSFLAGS) $(addprefix -L ,$(LOADPATH)) \
+--eval '(progn $(call require, $(PRELOADS)))' -f batch-byte-compile $^")))
:autoconf '("AM_PATH_LISPDIR")
:sourcetype '(ede-source-emacs)
-; :objectextention ".elc"
+ :objectextention ".elc"
)
"Compile Emacs Lisp programs.")
(full nil)
)
;; Make sure the relative name isn't to far off
- (when (string-match "^\\.\\./\\.\\./\\.\\./\\.\\." rel)
+ (when (string-match "^\\.\\./\\.\\./\\.\\./\\.\\./\\.\\." rel)
(setq full fnd))
;; Do the setup.
(setq paths (cons (or full rel) paths)
(mapc (lambda (src)
(let* ((fsrc (expand-file-name src dir))
(elc (concat (file-name-sans-extension fsrc) ".elc")))
- (if (eq (byte-recompile-file fsrc nil 0) t)
- (setq comp (1+ comp))
- (setq utd (1+ utd)))))
+ (with-no-warnings
+ (if (< emacs-major-version 24)
+ ;; Does not have `byte-recompile-file'
+ (if (or (not (file-exists-p elc))
+ (file-newer-than-file-p fsrc elc))
+ (progn
+ (setq comp (1+ comp))
+ (byte-compile-file fsrc))
+ (setq utd (1+ utd)))
+
+ (if (eq (byte-recompile-file fsrc nil 0) t)
+ (setq comp (1+ comp))
+ (setq utd (1+ utd)))))))
+
(oref obj source))
(message "All Emacs Lisp sources are up to date in %s" (object-name obj))
(cons comp utd)))
"Insert variables needed by target THIS."
(let ((newitems (if (oref this aux-packages)
(ede-proj-elisp-packages-to-loadpath
- (oref this aux-packages))))
- )
+ (oref this aux-packages)))))
(ede-proj-makefile-insert-loadpath-items newitems)))
(defun ede-proj-elisp-add-path (path)
"Tweak the configure file (current buffer) to accommodate THIS."
(call-next-method)
;; Ok, now we have to tweak the autoconf provided `elisp-comp' program.
- (let ((ec (ede-expand-filename this "elisp-comp" 'newfile)))
+ (let ((ec (ede-expand-filename this "elisp-comp" 'newfile))
+ (enable-local-variables nil))
(if (or (not ec) (not (file-exists-p ec)))
(message "No elisp-comp file. There may be compile errors? Rerun a second time.")
(save-excursion
"Flush the configure file (current buffer) to accommodate THIS."
;; Remove crufty old paths from elisp-compile
(let ((ec (ede-expand-filename this "elisp-comp" 'newfile))
- )
+ (enable-local-variables nil))
(if (and ec (file-exists-p ec))
(with-current-buffer (find-file-noselect ec t)
(goto-char (point-min))
;;
(defclass ede-proj-target-elisp-autoloads (ede-proj-target-elisp)
((availablecompilers :initform '(ede-emacs-cedet-autogen-compiler))
- (aux-packages :initform ("cedet-autogen"))
(phony :initform t)
+ (rules :initform nil)
(autoload-file :initarg :autoload-file
:initform "loaddefs.el"
:type string
(ede-compiler
"ede-emacs-autogen-compiler"
:name "emacs"
- :variables '(("EMACS" . "emacs"))
+ :variables '(("EMACS" . "emacs")
+ ("EMACSFLAGS" . "-batch --no-site-file --eval '(setq debug-on-error t)'")
+ ("require" . "$(foreach r,$(1),(require (quote $(r))))"))
:commands
- '("@echo \"(add-to-list 'load-path nil)\" > $@-compile-script"
- "for loadpath in . ${LOADPATH}; do \\"
- " echo \"(add-to-list 'load-path \\\"$$loadpath\\\")\" >> $@-compile-script; \\"
- "done;"
- "@echo \"(require 'cedet-autogen)\" >> $@-compile-script"
- "\"$(EMACS)\" -batch --no-site-file -l $@-compile-script -f cedet-batch-update-autoloads $(LOADDEFS) $(LOADDIRS)"
- )
+ '("$(EMACS) $(EMACSFLAGS) $(addprefix -L ,$(LOADPATH)) \
+--eval '(setq generated-autoload-file \"$(abspath $(LOADDEFS))\")' \
+-f batch-update-autoloads $(abspath $(LOADDIRS))")
+ :rules (list (ede-makefile-rule "clean-autoloads" :target "clean-autoloads" :phony t :rules '("rm -f $(LOADDEFS)")))
:sourcetype '(ede-source-emacs)
)
"Build an autoloads file.")
(autoload 'ede-proj-target-makefile-info "ede/proj-info"
"Target class for info files." nil nil)
+(eieio-defclass-autoload 'ede-proj-target-aux '(ede-proj-target)
+ "ede/proj-aux"
+ "Target class for a group of lisp files.")
+(eieio-defclass-autoload 'ede-proj-target-elisp '(ede-proj-target-makefile)
+ "ede/proj-elisp"
+ "Target class for a group of lisp files.")
+(eieio-defclass-autoload 'ede-proj-target-elisp-autoloads '(ede-proj-target-elisp)
+ "ede/proj-elisp"
+ "Target class for generating autoload files.")
+(eieio-defclass-autoload 'ede-proj-target-scheme '(ede-proj-target)
+ "ede/proj-scheme"
+ "Target class for a group of lisp files.")
+(eieio-defclass-autoload 'ede-proj-target-makefile-miscelaneous '(ede-proj-target-makefile)
+ "ede/proj-misc"
+ "Target class for a group of miscellaneous w/ a special makefile.")
+(eieio-defclass-autoload 'ede-proj-target-makefile-program '(ede-proj-target-makefile-objectcode)
+ "ede/proj-prog"
+ "Target class for building a program.")
+(eieio-defclass-autoload 'ede-proj-target-makefile-archive '(ede-proj-target-makefile-objectcode)
+ "ede/proj-archive"
+ "Target class for building an archive of object code.")
+(eieio-defclass-autoload 'ede-proj-target-makefile-shared-object '(ede-proj-target-makefile-program)
+ "ede/proj-shared"
+ "Target class for building a shared object.")
+(eieio-defclass-autoload 'ede-proj-target-makefile-info '(ede-proj-target-makefile)
+ "ede/proj-info"
+ "Target class for info files.")
+
+;; Not in ede/ , but part of semantic.
+(eieio-defclass-autoload 'semantic-ede-proj-target-grammar '(ede-proj-target-elisp)
+ "semantic/ede-grammar"
+ "Target classfor Semantic grammar files.")
+
;;; Class Definitions:
(defclass ede-proj-target (ede-target)
((auxsource :initarg :auxsource
(setq ede-proj-target-alist
(cons (cons name class) ede-proj-target-alist)))))
-(defclass ede-proj-project (ede-project)
- ((makefile-type :initarg :makefile-type
+(defclass ede-proj-project (eieio-persistent ede-project)
+ ((extension :initform ".ede")
+ (file-header-line :initform ";; EDE Project Files are auto generated: Do Not Edit")
+ (makefile-type :initarg :makefile-type
:initform Makefile
:type symbol
:custom (choice (const Makefile)
for the tree being read in. If ROOTPROJ is nil, then assume that
the PROJECT being read in is the root project."
(save-excursion
- (let ((ret nil)
+ (let ((ret (eieio-persistent-read (concat project "Project.ede")
+ ede-proj-project))
(subdirs (directory-files project nil "[^.].*" nil)))
- (set-buffer (get-buffer-create " *tmp proj read*"))
- (unwind-protect
- (progn
- (insert-file-contents (concat project "Project.ede")
- nil nil nil t)
- (goto-char (point-min))
- (setq ret (read (current-buffer)))
- (if (not (eq (car ret) 'ede-proj-project))
- (error "Corrupt project file"))
- (setq ret (eval ret))
- (oset ret file (concat project "Project.ede"))
- (oset ret directory project)
- (oset ret rootproject rootproj)
- )
- (kill-buffer " *tmp proj read*"))
+ (if (not (object-of-class-p ret 'ede-proj-project))
+ (error "Corrupt project file"))
+ (oset ret directory project)
+ (oset ret rootproject rootproj)
+
+ ;; Load the project file of each subdirectory containing a
+ ;; loadable Project.ede.
(while subdirs
(let ((sd (file-name-as-directory
(expand-file-name (car subdirs) project))))
"Write out object PROJECT into its file."
(save-excursion
(if (not project) (setq project (ede-current-project)))
- (let ((b (set-buffer (get-buffer-create " *tmp proj write*")))
- (cfn (oref project file))
- (cdir (oref project directory)))
+ (let ((cdir (oref project directory)))
(unwind-protect
- (save-excursion
- (erase-buffer)
- (let ((standard-output (current-buffer)))
- (oset project file (file-name-nondirectory cfn))
- (slot-makeunbound project :directory)
- (object-write project ";; EDE project file."))
- (write-file cfn nil)
- )
- ;; Restore the :file on exit.
- (oset project file cfn)
- (oset project directory cdir)
- (kill-buffer b)))))
+ (progn
+ (slot-makeunbound project :directory)
+ (eieio-persistent-save project))
+ ;; Restore the directory slot
+ (oset project directory cdir))) ))
(defmethod ede-commit-local-variables ((proj ede-proj-project))
"Commit change to local variables in PROJ."
(let ((root (or (ede-project-root this) this))
)
(setq ede-projects (delq root ede-projects))
+ ;; NOTE : parent function double-checks that this dir was
+ ;; already in memory once.
(ede-load-project-file (ede-project-root-directory root))
))
(oref amf targets))
nil t))))
;; The input target might be new. See if we can find it.
- (amf (ede-load-project-file (oref ot path)))
+ (amf (ede-target-parent ot))
(ot (object-assoc target 'name (oref amf targets)))
(ofn (file-name-nondirectory (buffer-file-name))))
(if (not ot)
If BUFFER isn't specified, use the current buffer."
(save-excursion
(if buffer (set-buffer buffer))
- (toggle-read-only -1)))
+ (setq buffer-read-only nil)))
(provide 'ede/util)
(defconst inversion-decoders
'(
- (alpha "^\\([0-9]+\\)\\.\\([0-9]+\\)\\s-*\\.?alpha\\([0-9]+\\)?$" 3)
- (beta "^\\([0-9]+\\)\\.\\([0-9]+\\)\\s-*\\.?beta\\([0-9]+\\)?$" 3)
- (beta "^\\([0-9]+\\)\\.\\([0-9]+\\)\\s-*(beta\\([0-9]+\\)?)" 3)
+ (alpha "^\\([0-9]+\\)\\.\\([0-9]+\\)\\.?\\([0-9]*\\)?\\s-*\\.?alpha\\([0-9]+\\)?$" 4)
+ (beta "^\\([0-9]+\\)\\.\\([0-9]+\\)\\.?\\([0-9]*\\)?\\s-*\\.?beta\\([0-9]+\\)?$" 4)
+ (beta "^\\([0-9]+\\)\\.\\([0-9]+\\)\\.?\\([0-9]*\\)?\\s-*\\.?(beta\\([0-9]+\\)?)$" 4)
+ (beta "^[^/]+/\\w+--\\w+--\\([0-9]+\\)\\.\\([0-9]+\\)\\.\\([0-9]+\\)--patch-\\([0-9]+\\)" 4)
+ (beta "^\\w+: v\\([0-9]+\\)\\.\\([0-9]+\\)\\.\\([0-9]+\\)-\\([0-9]+\\)-\\(.*\\)" 5)
(prerelease "^\\([0-9]+\\)\\.\\([0-9]+\\)\\s-*\\.?pre\\([0-9]+\\)?$" 3)
- (full "^\\([0-9]+\\)\\.\\([0-9]+\\)$" 2)
+ (full "^\\([0-9]+\\)\\.\\([0-9]+\\)\\.?\\([0-9]+\\)?$" 3)
(fullsingle "^\\([0-9]+\\)$" 1)
- (patch "^\\([0-9]+\\)\\.\\([0-9]+\\) (patch \\([0-9]+\\))" 3)
+ (patch "^\\([0-9]+\\)\\.\\([0-9]+\\)\\.?\\([0-9]+\\)?\\s-*(patch \\([0-9]+\\))" 4)
(point "^\\([0-9]+\\)\\.\\([0-9]+\\)\\.\\([0-9]+\\)$" 3)
+ (point "^\\w+: v\\([0-9]+\\)\\.\\([0-9]+\\)\\.\\([0-9]+\\)-\\(0\\)-\\(.*\\)" 5)
(build "^\\([0-9]+\\)\\.\\([0-9]+\\)\\.\\([0-9]+\\).\\([0-9]+\\)$" 4)
+ (full "^[^/]+/\\w+--\\w+--\\([0-9]+\\)\\.\\([0-9]+\\)\\.\\([0-9]+\\)--version-\\([0-9]+\\)" 4)
+ (full "^\\w+: v\\([0-9]+\\)\\.\\([0-9]+\\)\\.\\([0-9]+\\)" 5)
)
"List of decoders for version strings.
Each decoder is of the form:
;; Decode the code
(setq code (inversion-decode-version ver))
(unless code
- (error "%S-version value cannot be decoded" package))
+ (error "%S-version value (%s) cannot be decoded" package ver))
code))
(defun inversion-package-incompatibility-version (package)
(v2-3 (nth 3 ver2))
(v2-4 (nth 4 ver2))
)
- (or (and (= v1-0 v2-0)
- (= v1-1 v2-1)
- (= v1-2 v2-2)
- (= v1-3 v2-3)
- v1-4 v2-4 ; all or nothing if elt - is =
+
+ (cond ((and (equal (list v1-1 v1-2 v1-3 v1-4)
+ (list v2-1 v2-2 v2-3 v2-4))
+ v1-0 v2-0)
+ (< v1-0 v2-0))
+ ((and (equal v1-1 v2-1)
+ (equal v1-2 v2-2)
+ (equal v1-3 v2-3)
+ v1-4 v2-4) ; all or nothing if elt - is =
(< v1-4 v2-4))
- (and (= v1-0 v2-0)
- (= v1-1 v2-1)
- (= v1-2 v2-2)
- v1-3 v2-3 ; all or nothing if elt - is =
+ ((and (equal v1-1 v2-1)
+ (equal v1-2 v2-2)
+ v1-3 v2-3) ; all or nothing if elt - is =
(< v1-3 v2-3))
- (and (= v1-1 v2-1)
+ ((and (equal v1-1 v2-1)
+ v1-2 v2-2)
(< v1-2 v2-2))
- (and (< v1-1 v2-1))
- (and (< v1-0 v2-0)
- (= v1-1 v2-1)
- (= v1-2 v2-2)
- )
+ ((and v1-1 v2-1)
+ (< v1-1 v2-1))
)))
(defun inversion-check-version (version incompatible-version
;; Return the package symbol that was required.
package))
-(defun inversion-require-emacs (emacs-ver xemacs-ver)
- "Declare that you need either EMACS-VER, or XEMACS-VER.
+;;;###autoload
+(defun inversion-require-emacs (emacs-ver xemacs-ver sxemacs-ver)
+ "Declare that you need either EMACS-VER, XEMACS-VER or SXEMACE-ver.
Only checks one based on which kind of Emacs is being run."
(let ((err (inversion-test 'emacs
- (if (featurep 'xemacs)
- xemacs-ver
- emacs-ver))))
+ (cond ((featurep 'sxemacs)
+ sxemacs-ver)
+ ((featurep 'xemacs)
+ xemacs-ver)
+ (t
+ emacs-ver)))))
(if err (error err)
;; Something nice...
t)))
(require 'semantic/tag)
(require 'semantic/lex)
-(defvar semantic-version "2.0"
+(defvar semantic-version "2.1beta"
"Current version of Semantic.")
(declare-function inversion-test "inversion")
(js-mode . wisent-javascript-setup-parser)
(python-mode . wisent-python-default-setup)
(scheme-mode . semantic-default-scheme-setup)
+ (f90-mode . semantic-default-f90-setup)
(srecode-template-mode . srecode-template-setup-parser)
+ (texinfo-mode . semantic-default-texi-setup)
(makefile-automake-mode . semantic-default-make-setup)
(makefile-gmake-mode . semantic-default-make-setup)
(makefile-makepp-mode . semantic-default-make-setup)
;;;; Parse the whole system.
((semantic-parse-tree-needs-rebuild-p)
- ;; Use Emacs's built-in progress-reporter
- (let ((semantic--progress-reporter
- (and (>= (point-max) semantic-minimum-working-buffer-size)
- (eq semantic-working-type 'percent)
- (make-progress-reporter
- (semantic-parser-working-message (buffer-name))
- 0 100))))
- (setq res (semantic-parse-region (point-min) (point-max)))
- (if semantic--progress-reporter
- (progress-reporter-done semantic--progress-reporter)))
+ ;; Use Emacs's built-in progress-reporter (only interactive).
+ (if noninteractive
+ (setq res (semantic-parse-region (point-min) (point-max)))
+ (let ((semantic--progress-reporter
+ (and (>= (point-max) semantic-minimum-working-buffer-size)
+ (eq semantic-working-type 'percent)
+ (make-progress-reporter
+ (semantic-parser-working-message (buffer-name))
+ 0 100))))
+ (setq res (semantic-parse-region (point-min) (point-max)))
+ (if semantic--progress-reporter
+ (progress-reporter-done semantic--progress-reporter))))
;; Clear the caches when we see there were no errors.
;; But preserve the unmatched syntax cache and warnings!
:help "Highlight the tag at point"
:visible semantic-mode
:button (:toggle . global-semantic-highlight-func-mode)))
+ (define-key cedet-menu-map [global-semantic-stickyfunc-mode]
+ '(menu-item "Stick Top Tag to Headerline" global-semantic-stickyfunc-mode
+ :help "Stick the tag scrolled off the top of the buffer into the header line"
+ :visible semantic-mode
+ :button (:toggle . (bound-and-true-p
+ global-semantic-stickyfunc-mode))))
(define-key cedet-menu-map [global-semantic-decoration-mode]
'(menu-item "Decorate Tags" global-semantic-decoration-mode
:help "Decorate tags based on tag attributes"
global-semantic-idle-scheduler-mode
global-semanticdb-minor-mode
global-semantic-idle-summary-mode
- global-semantic-mru-bookmark-mode)
+ global-semantic-mru-bookmark-mode
+ global-cedet-m3-minor-mode
+ global-semantic-idle-local-symbol-highlight-mode
+ global-semantic-highlight-edits-mode
+ global-semantic-show-unmatched-syntax-mode
+ global-semantic-show-parser-state-mode)
"List of auxiliary minor modes in the Semantic package.")
;;;###autoload
`global-semantic-highlight-func-mode' - Highlight the current tag.
`global-semantic-stickyfunc-mode' - Show current fun in header line.
`global-semantic-mru-bookmark-mode' - Provide `switch-to-buffer'-like
- keybinding for tag names."
+ keybinding for tag names.
+ `global-cedet-m3-minor-mode' - A mouse 3 context menu.
+ `global-semantic-idle-local-symbol-highlight-mode' - Highlight references
+ of the symbol under point.
+The following modes are more targeted at people who want to see
+ some internal information of the semantic parser in action:
+ `global-semantic-highlight-edits-mode' - Visualize incremental parser by
+ highlighting not-yet parsed changes.
+ `global-semantic-show-unmatched-syntax-mode' - Highlight unmatched lexical
+ syntax tokens.
+ `global-semantic-show-parser-state-mode' - Display the parser cache state."
:group 'semantic
:type `(set ,@(mapcar (lambda (c) (list 'const c))
semantic-submode-list)))
(dolist (b (buffer-list))
(with-current-buffer b
(semantic-new-buffer-fcn))))
- ;; Disable all Semantic features.
+ ;; Disable Semantic features. Removing everything Semantic has
+ ;; introduced in the buffer is pretty much futile, but we have to
+ ;; clean the hooks and delete Semantic-related overlays, so that
+ ;; Semantic can be re-activated cleanly.
(remove-hook 'mode-local-init-hook 'semantic-new-buffer-fcn)
(remove-hook 'completion-at-point-functions
'semantic-completion-at-point-function)
+ (remove-hook 'after-change-functions
+ 'semantic-change-function)
(define-key cedet-menu-map [cedet-menu-separator] nil)
(define-key cedet-menu-map [semantic-options-separator] nil)
;; FIXME: handle semanticdb-load-ebrowse-caches
(dolist (mode semantic-submode-list)
(if (and (boundp mode) (eval mode))
- (funcall mode -1)))))
+ (funcall mode -1)))
+ ;; Unlink buffer and clear cache
+ (semantic--tag-unlink-cache-from-buffer)
+ (setq semantic--buffer-cache nil)
+ ;; Make sure we run the setup function if Semantic gets
+ ;; re-activated.
+ (setq semantic-new-buffer-fcn-was-run nil)))
(defun semantic-completion-at-point-function ()
'semantic-ia-complete-symbol)
the current buffer was set up for parsing. Return non-nil if the
minor mode is enabled." t nil)
+(autoload 'global-semantic-idle-local-symbol-highlight-mode "semantic/idle"
+ "Highlight the tag and symbol references of the symbol under point.
+Call `semantic-analyze-current-context' to find the reference tag.
+Call `semantic-symref-hits-in-region' to identify local references." t nil)
+
(autoload 'srecode-template-setup-parser "srecode/srecode-template"
"Set up buffer for parsing SRecode template files." t nil)
(semanticdb-file-table-object fileinner t))))
(cond ((not fileinner)
(setq unknown (1+ unknown)))
- ((number-or-marker-p (oref tableinner pointmax))
+ ((and tableinner (number-or-marker-p (oref tableinner pointmax)))
(setq ok (1+ ok)))
(t
(setq unparsed (1+ unparsed))))))
;;
;; These queries allow a major mode to help the analyzer make decisions.
;;
-(define-overloadable-function semantic-analyze-tag-prototype-p (tag)
- "Non-nil if TAG is a prototype."
- )
-
-(defun semantic-analyze-tag-prototype-p-default (tag)
- "Non-nil if TAG is a prototype."
- (let ((p (semantic-tag-get-attribute tag :prototype-flag)))
- (cond
- ;; Trust the parser author.
- (p p)
- ;; Empty types might be a prototype.
- ((eq (semantic-tag-class tag) 'type)
- (not (semantic-tag-type-members tag)))
- ;; No other heuristics.
- (t nil))
- ))
-
-;;------------------------------------------------------------
(define-overloadable-function semantic-analyze-split-name (name)
"Split a tag NAME into a sequence.
(if (and type-declaration
(semantic-tag-p type-declaration)
(semantic-tag-of-class-p type-declaration 'type)
- (not (semantic-analyze-tag-prototype-p type-declaration))
+ (not (semantic-tag-prototype-p type-declaration))
)
;; We have an anonymous type for TAG with children.
;; Use this type directly.
(when (and (semantic-tag-p ans)
(eq (semantic-tag-class ans) 'type))
;; We have a tag.
- (if (semantic-analyze-tag-prototype-p ans)
+ (if (semantic-tag-prototype-p ans)
;; It is a prototype.. find the real one.
(or (and scope
(car-safe
(semantic-go-to-tag tag db)
(setq scope (semantic-calculate-scope))
- (setq allhits (semantic--analyze-refs-full-lookup tag scope))
+ (setq allhits (semantic--analyze-refs-full-lookup tag scope t))
(semantic-analyze-references (semantic-tag-name tag)
:tag tag
(aDB (car ans))
)
(when (and (not (semantic-tag-prototype-p aT))
- (semantic-tag-similar-p tag aT :prototype-flag :parent))
+ (semantic-tag-similar-p tag aT
+ :prototype-flag
+ :parent
+ :typemodifiers))
(when in-buffer (save-excursion (semantic-go-to-tag aT aDB)))
(push aT impl))))
allhits)
(aDB (car ans))
)
(when (and (semantic-tag-prototype-p aT)
- (semantic-tag-similar-p tag aT :prototype-flag :parent))
+ (semantic-tag-similar-p tag aT
+ :prototype-flag
+ :parent
+ :typemodifiers))
(when in-buffer (save-excursion (semantic-go-to-tag aT aDB)))
(push aT proto))))
allhits)
;;; LOOKUP
;;
-(defun semantic--analyze-refs-full-lookup (tag scope)
+(defun semantic--analyze-refs-full-lookup (tag scope &optional noerror)
"Perform a full lookup for all occurrences of TAG in the current project.
TAG should be the tag currently under point.
SCOPE is the scope the cursor is in. From this a list of parents is
-derived. If SCOPE does not have parents, then only a simple lookup is done."
+derived. If SCOPE does not have parents, then only a simple lookup is done.
+Optional argument NOERROR means don't error if the lookup fails."
(if (not (oref scope parents))
;; If this tag has some named parent, but is not
- (semantic--analyze-refs-full-lookup-simple tag)
+ (semantic--analyze-refs-full-lookup-simple tag noerror)
;; We have some sort of lineage we need to consider when we do
;; our side lookup of tags.
;;; Commentary:
;;
-;; This file was generated from etc/grammars/c.by.
+;; This file was generated from admin/grammars/c.by.
;;; Code:
(require 'semantic/lex)
(eval-when-compile (require 'semantic/bovine))
-
+\f
+;;; Prologue
+;;
(declare-function semantic-c-reconstitute-token "semantic/bovine/c")
(declare-function semantic-c-reconstitute-template "semantic/bovine/c")
(declare-function semantic-expand-c-tag "semantic/bovine/c")
-
+\f
+;;; Declarations
+;;
(defconst semantic-c-by--keyword-table
(semantic-lex-make-keyword-table
'(("extern" . EXTERN)
("inline" . INLINE)
("virtual" . VIRTUAL)
("mutable" . MUTABLE)
+ ("explicit" . EXPLICIT)
("struct" . STRUCT)
("union" . UNION)
("enum" . ENUM)
("enum" summary "Enumeration Type Declaration: enum [name] { ... };")
("union" summary "Union Type Declaration: union [name] { ... };")
("struct" summary "Structure Type Declaration: struct [name] { ... };")
+ ("explicit" summary "Forbids implicit type conversion: explicit <constructor>")
("mutable" summary "Member Declaration Modifier: mutable <type> <name> ...")
("virtual" summary "Method Modifier: virtual <type> <name>(...) ...")
("inline" summary "Function Modifier: inline <return type> <name>(...) {...};")
)
(template)
(using)
+ (spp-include
+ ,(semantic-lambda
+ (semantic-tag
+ (nth 0 vals)
+ 'include :inside-ns t))
+ )
( ;;EMPTY
)
) ;; end namespacesubparts
"*"
(nth 2 vals))))
)
+ (open-paren
+ "("
+ symbol
+ close-paren
+ ")"
+ ,(semantic-lambda
+ (list
+ (nth 1 vals)))
+ )
) ;; end function-pointer
(fun-or-proto-end
semantic-flex-keywords-obarray semantic-c-by--keyword-table
semantic-equivalent-major-modes '(c-mode c++-mode)
))
+
+\f
+;;; Analyzers
+;;
\f
;;; Epilogue
;;
(require 'semantic)
(require 'semantic/analyze)
+(require 'semantic/bovine)
(require 'semantic/bovine/gcc)
(require 'semantic/idle)
(require 'semantic/lex-spp)
(require 'semantic/bovine/c-by)
+(require 'semantic/db-find)
+(require 'hideif)
(eval-when-compile
(require 'semantic/find))
'( ("__THROW" . "")
("__const" . "const")
("__restrict" . "")
+ ("__attribute_pure__" . "")
+ ("__attribute_malloc__" . "")
+ ("__nonnull" . "")
+ ("__wur" . "")
("__declspec" . ((spp-arg-list ("foo") 1 . 2)))
("__attribute__" . ((spp-arg-list ("foo") 1 . 2)))
+ ("__asm" . ((spp-arg-list ("foo") 1 . 2)))
)
"List of symbols to include by default.")
(defun semantic-c-reset-preprocessor-symbol-map ()
"Reset the C preprocessor symbol map based on all input variables."
- (when (featurep 'semantic/bovine/c)
+ (when (and semantic-mode
+ (featurep 'semantic/bovine/c))
+ (remove-hook 'mode-local-init-hook 'semantic-c-reset-preprocessor-symbol-map)
+ ;; Initialize semantic-lex-spp-macro-symbol-obarray with symbols.
+ (setq-mode-local c-mode
+ semantic-lex-spp-macro-symbol-obarray
+ (semantic-lex-make-spp-table
+ (append semantic-lex-c-preprocessor-symbol-map-builtin
+ semantic-lex-c-preprocessor-symbol-map)))
(let ((filemap nil)
)
(when (and (not semantic-c-in-reset-preprocessor-table)
(error (message "Error updating tables for %S"
(object-name table)))))
(setq filemap (append filemap (oref table lexical-table)))
- )
- ))))
-
- (setq-mode-local c-mode
- semantic-lex-spp-macro-symbol-obarray
- (semantic-lex-make-spp-table
- (append semantic-lex-c-preprocessor-symbol-map-builtin
- semantic-lex-c-preprocessor-symbol-map
- filemap))
- )
- )))
+ ;; Update symbol obarray
+ (setq-mode-local c-mode
+ semantic-lex-spp-macro-symbol-obarray
+ (semantic-lex-make-spp-table
+ (append semantic-lex-c-preprocessor-symbol-map-builtin
+ semantic-lex-c-preprocessor-symbol-map
+ filemap)))))))))))
+
+;; Make sure the preprocessor symbols are set up when mode-local kicks
+;; in.
+(add-hook 'mode-local-init-hook 'semantic-c-reset-preprocessor-symbol-map)
(defcustom semantic-lex-c-preprocessor-symbol-map nil
"Table of C Preprocessor keywords used by the Semantic C lexer.
nil
(let* ((name (buffer-substring-no-properties
(match-beginning 1) (match-end 1)))
+ (beginning-of-define (match-end 1))
(with-args (save-excursion
(goto-char (match-end 0))
(looking-at "(")))
(raw-stream
(semantic-lex-spp-stream-for-macro (save-excursion
(semantic-c-end-of-macro)
- (point))))
+ ;; HACK - If there's a C comment after
+ ;; the macro, do not parse it.
+ (if (looking-back "/\\*.*" beginning-of-define)
+ (progn
+ (goto-char (match-beginning 0))
+ (1- (point)))
+ (point)))))
)
;; Only do argument checking if the paren was immediately after
(cond
((looking-at "^\\s-*#\\s-*if")
;; We found a nested if. Skip it.
- ;; @TODO - can we use the new c-scan-conditionals
- (c-forward-conditional 1))
+ (if (fboundp 'c-scan-conditionals)
+ (goto-char (c-scan-conditionals 1))
+ ;; For older Emacsen, but this will set the mark.
+ (c-forward-conditional 1)))
((looking-at "^\\s-*#\\s-*elif")
;; We need to let the preprocessor analyze this one.
(beginning-of-line)
;; We found an elif. Stop here.
(setq done t))))))
+;;; HIDEIF USAGE:
+;; NOTE: All hideif using code was contributed by Brian Carlson as
+;; copies from hideif plus modifications and additions.
+;; Eric then converted things to use hideif functions directly,
+;; deleting most of that code, and added the advice.
+
+;;; SPP SYM EVAL
+;;
+;; Convert SPP symbols into values usable by hideif.
+;;
+;; @TODO - can these conversion fcns be a part of semantic-lex-spp.el?
+;; -- TRY semantic-lex-spp-one-token-to-txt
+(defun semantic-c-convert-spp-value-to-hideif-value (symbol macrovalue)
+ "Convert an spp macro SYMBOL MACROVALUE, to something that hideif can use.
+Take the first interesting thing and convert it."
+ ;; Just warn for complex macros.
+ (when (> (length macrovalue) 1)
+ (semantic-push-parser-warning
+ (format "Complex macro value (%s) may be improperly evaluated. "
+ symbol) 0 0))
+
+ (let* ((lextoken (car macrovalue))
+ (key (semantic-lex-token-class lextoken))
+ (value (semantic-lex-token-text lextoken)))
+ (cond
+ ((eq key 'number) (string-to-number value))
+ ((eq key 'symbol) (semantic-c-evaluate-symbol-for-hideif value))
+ ((eq key 'string)
+ (if (string-match "^[0-9]+L?$" value)
+ ;; If it matches a number expression, then
+ ;; convert to a number.
+ (string-to-number value)
+ value))
+ (t (semantic-push-parser-warning
+ (format "Unknown macro value. Token class = %s value = %s. " key value)
+ 0 0)
+ nil)
+ )))
+
+(defun semantic-c-evaluate-symbol-for-hideif (spp-symbol)
+ "Lookup the symbol SPP-SYMBOL (a string) to something hideif can use.
+Pulls out the symbol list, and call `semantic-c-convert-spp-value-to-hideif-value'."
+ (interactive "sSymbol name: ")
+ (when (symbolp spp-symbol) (setq spp-symbol (symbol-name spp-symbol)))
+
+ (if (semantic-lex-spp-symbol-p spp-symbol )
+ ;; Convert the symbol into a stream of tokens from the macro which we
+ ;; can then interpret.
+ (let ((stream (semantic-lex-spp-symbol-stream spp-symbol)))
+ (cond
+ ;; Empyt string means defined, so t.
+ ((null stream) t)
+ ;; A list means a parsed macro stream.
+ ((listp stream)
+ ;; Convert the macro to something we can return.
+ (semantic-c-convert-spp-value-to-hideif-value spp-symbol stream))
+
+ ;; Strings might need to be turned into numbers
+ ((stringp stream)
+ (if (string-match "^[0-9]+L?$" stream)
+ ;; If it matches a number expression, then convert to a
+ ;; number.
+ (string-to-number stream)
+ stream))
+
+ ;; Just return the stream. A user might have just stuck some
+ ;; value in it directly.
+ (t stream)
+ ))
+ ;; Else, store an error, return nil.
+ (progn
+ (semantic-push-parser-warning
+ (format "SPP Symbol %s not available" spp-symbol)
+ (point) (point))
+ nil)))
+
+;;; HIDEIF HACK support fcns
+;;
+;; These fcns can replace the impl of some hideif features.
+;;
+;; @TODO - Should hideif and semantic-c merge?
+;; I picture a grammar just for CPP that expands into
+;; a second token stream for the parser.
+(defun semantic-c-hideif-lookup (var)
+ "Replacement for `hif-lookup'.
+I think it just gets the value for some CPP variable VAR."
+ (let ((val (semantic-c-evaluate-symbol-for-hideif
+ (cond
+ ((stringp var) var)
+ ((symbolp var) (symbol-name var))
+ (t "Unable to determine var")))))
+ (if val
+ val
+ ;; Real hideif will return the right undefined symbol.
+ nil)))
+
+(defun semantic-c-hideif-defined (var)
+ "Replacement for `hif-defined'.
+I think it just returns t/nil dependent on if VAR has been defined."
+ (let ((var-symbol-name
+ (cond
+ ((symbolp var) (symbol-name var))
+ ((stringp var) var)
+ (t "Not A Symbol"))))
+ (if (not (semantic-lex-spp-symbol-p var-symbol-name))
+ (progn
+ (semantic-push-parser-warning
+ (format "Skip %s" (buffer-substring-no-properties
+ (point-at-bol) (point-at-eol)))
+ (point-at-bol) (point-at-eol))
+ nil)
+ t)))
+
+;;; HIDEIF ADVICE
+;;
+;; Advise hideif functions to use our lexical tables instead.
+(defvar semantic-c-takeover-hideif nil
+ "Non-nil when Semantic is taking over hideif features.")
+
+;; (defadvice hif-defined (around semantic-c activate)
+;; "Is the variable defined?"
+;; (if semantic-c-takeover-hideif
+;; (setq ad-return-value
+;; (semantic-c-hideif-defined (ad-get-arg 0)))
+;; ad-do-it))
+
+;; (defadvice hif-lookup (around semantic-c activate)
+;; "Is the argument defined? Return true or false."
+;; (let ((ans nil))
+;; (when semantic-c-takeover-hideif
+;; (setq ans (semantic-c-hideif-lookup (ad-get-arg 0))))
+;; (if (null ans)
+;; ad-do-it
+;; (setq ad-return-value ans))))
+
+;;; #if macros
+;;
+;; Support #if macros by evaluating the values via use of hideif
+;; logic. See above for hacks to make this work.
(define-lex-regex-analyzer semantic-lex-c-if
"Code blocks wrapped up in #if, or #ifdef.
Uses known macro tables in SPP to determine what block to skip."
- "^\\s-*#\\s-*\\(if\\|ifndef\\|ifdef\\|elif\\)\\s-+\\(!?defined(\\|\\)\\s-*\\(\\(\\sw\\|\\s_\\)+\\)\\(\\s-*)\\)?\\s-*$"
+ "^\\s-*#\\s-*\\(if\\|elif\\).*$"
(semantic-c-do-lex-if))
(defun semantic-c-do-lex-if ()
+ "Handle lexical CPP if statements.
+Enables a takeover of some hideif functions, then uses hideif to
+evaluate the #if expression and enables us to make decisions on which
+code to parse."
+ ;; Enable our advice, and use hideif to parse.
+ (let* ((semantic-c-takeover-hideif t)
+ (hif-ifx-regexp (concat hif-cpp-prefix "\\(elif\\|if\\(n?def\\)?\\)[ \t]+"))
+ (parsedtokelist
+ (condition-case nil
+ ;; This is imperfect, so always assume on error.
+ (hif-canonicalize)
+ (error nil))))
+
+ (let ((eval-form (eval parsedtokelist)))
+ (if (or (not eval-form)
+ (and (numberp eval-form)
+ (equal eval-form 0)));; ifdefline resulted in false
+
+ ;; The if indicates to skip this preprocessor section
+ (let ((pt nil))
+ (semantic-push-parser-warning (format "Skip %s" (buffer-substring-no-properties (point-at-bol) (point-at-eol)))
+ (point-at-bol) (point-at-eol))
+ (beginning-of-line)
+ (setq pt (point))
+ ;; This skips only a section of a conditional. Once that section
+ ;; is opened, encountering any new #else or related conditional
+ ;; should be skipped.
+ (semantic-c-skip-conditional-section)
+ (setq semantic-lex-end-point (point))
+
+ ;; @TODO -somewhere around here, we also need to skip
+ ;; other sections of the conditional.
+
+ nil)
+ ;; Else, don't ignore it, but do handle the internals.
+ (end-of-line)
+ (setq semantic-lex-end-point (point))
+ nil))))
+
+(define-lex-regex-analyzer semantic-lex-c-ifdef
+ "Code blocks wrapped up in #ifdef.
+Uses known macro tables in SPP to determine what block to skip."
+ "^\\s-*#\\s-*\\(ifndef\\|ifdef\\)\\s-+\\(\\(\\sw\\|\\s_\\)+\\)$"
+ (semantic-c-do-lex-ifdef))
+
+(defun semantic-c-do-lex-ifdef ()
"Handle lexical CPP if statements."
(let* ((sym (buffer-substring-no-properties
- (match-beginning 3) (match-end 3)))
- (defstr (buffer-substring-no-properties
- (match-beginning 2) (match-end 2)))
- (defined (string= defstr "defined("))
- (notdefined (string= defstr "!defined("))
+ (match-beginning 2) (match-end 2)))
(ift (buffer-substring-no-properties
(match-beginning 1) (match-end 1)))
- (ifdef (or (string= ift "ifdef")
- (and (string= ift "if") defined)
- (and (string= ift "elif") defined)
- ))
- (ifndef (or (string= ift "ifndef")
- (and (string= ift "if") notdefined)
- (and (string= ift "elif") notdefined)
- ))
+ (ifdef (string= ift "ifdef"))
+ (ifndef (string= ift "ifndef"))
)
- (if (or (and (or (string= ift "if") (string= ift "elif"))
- (string= sym "0"))
- (and ifdef (not (semantic-lex-spp-symbol-p sym)))
+ (if (or (and ifdef (not (semantic-lex-spp-symbol-p sym)))
(and ifndef (semantic-lex-spp-symbol-p sym)))
;; The if indicates to skip this preprocessor section.
(let ((pt nil))
;; C preprocessor features
semantic-lex-cpp-define
semantic-lex-cpp-undef
+ semantic-lex-c-ifdef
semantic-lex-c-if
semantic-lex-c-macro-else
semantic-lex-c-macrobits
;; Hack in mode-local
(activate-mode-local-bindings)
+ ;; Setup C parser
+ (semantic-default-c-setup)
;; CHEATER! The following 3 lines are from
;; `semantic-new-buffer-fcn', but we don't want to turn
;; on all the other annoying modes for this little task.
)
;; Expand an EXTERN C first.
(when (eq (semantic-tag-class tag) 'extern)
- (let* ((mb (semantic-tag-get-attribute tag :members))
- (ret mb))
- (while mb
- (let ((mods (semantic-tag-get-attribute (car mb) :typemodifiers)))
- (setq mods (cons "extern" (cons "\"C\"" mods)))
- (semantic-tag-put-attribute (car mb) :typemodifiers mods))
- (setq mb (cdr mb)))
- (setq return-list ret)))
+ (setq return-list (semantic-expand-c-extern-C tag))
+ ;; The members will be expanded in the next iteration. The
+ ;; 'extern' tag itself isn't needed anymore.
+ (setq tag nil))
- ;; Function or variables that have a :type that is some complex
- ;; thing, extract it, and replace it with a reference.
- ;;
- ;; Thus, struct A { int a; } B;
- ;;
- ;; will create 2 toplevel tags, one is type A, and the other variable B
- ;; where the :type of B is just a type tag A that is a prototype, and
- ;; the actual struct info of A is its own toplevel tag.
+ ;; Check if we have a complex type
(when (or (semantic-tag-of-class-p tag 'function)
(semantic-tag-of-class-p tag 'variable))
- (let* ((basetype (semantic-tag-type tag))
- (typeref nil)
- (tname (when (consp basetype)
- (semantic-tag-name basetype))))
- ;; Make tname be a string.
- (when (consp tname) (setq tname (car (car tname))))
- ;; Is the basetype a full type with a name of its own?
- (when (and basetype (semantic-tag-p basetype)
- (not (semantic-tag-prototype-p basetype))
- tname
- (not (string= tname "")))
- ;; a type tag referencing the type we are extracting.
- (setq typeref (semantic-tag-new-type
- (semantic-tag-name basetype)
- (semantic-tag-type basetype)
- nil nil
- :prototype t))
- ;; Convert original tag to only have a reference.
- (setq tag (semantic-tag-copy tag))
- (semantic-tag-put-attribute tag :type typeref)
- ;; Convert basetype to have the location information.
- (semantic--tag-copy-properties tag basetype)
- (semantic--tag-set-overlay basetype
- (semantic-tag-overlay tag))
- ;; Store the base tag as part of the return list.
- (setq return-list (cons basetype return-list)))))
+ (setq tag (semantic-expand-c-complex-type tag))
+ ;; Extract new basetag
+ (setq return-list (car tag))
+ (setq tag (cdr tag)))
;; Name of the tag is a list, so expand it. Tag lists occur
;; for variables like this: int var1, var2, var3;
;; If we didn't have a list, but the return-list is non-empty,
;; that means we still need to take our existing tag, and glom
;; it onto our extracted type.
- (if (consp return-list)
+ (if (and tag (consp return-list))
(setq return-list (cons tag return-list)))
)
;; Default, don't change the tag means returning nil.
return-list))
+(defun semantic-expand-c-extern-C (tag)
+ "Expand TAG containing an 'extern \"C\"' statement.
+This will return all members of TAG with 'extern \"C\"' added to
+the typemodifiers attribute."
+ (when (eq (semantic-tag-class tag) 'extern)
+ (let* ((mb (semantic-tag-get-attribute tag :members))
+ (ret mb))
+ (while mb
+ (let ((mods (semantic-tag-get-attribute (car mb) :typemodifiers)))
+ (setq mods (cons "extern" (cons "\"C\"" mods)))
+ (semantic-tag-put-attribute (car mb) :typemodifiers mods))
+ (setq mb (cdr mb)))
+ (nreverse ret))))
+
+(defun semantic-expand-c-complex-type (tag)
+ "Check if TAG has a full :type with a name on its own.
+If so, extract it, and replace it with a reference to that type.
+Thus, 'struct A { int a; } B;' will create 2 toplevel tags, one
+is type A, and the other variable B where the :type of B is just
+a type tag A that is a prototype, and the actual struct info of A
+is its own toplevel tag. This function will return (cons A B)."
+ (let* ((basetype (semantic-tag-type tag))
+ (typeref nil)
+ (ret nil)
+ (tname (when (consp basetype)
+ (semantic-tag-name basetype))))
+ ;; Make tname be a string.
+ (when (consp tname) (setq tname (car (car tname))))
+ ;; Is the basetype a full type with a name of its own?
+ (when (and basetype (semantic-tag-p basetype)
+ (not (semantic-tag-prototype-p basetype))
+ tname
+ (not (string= tname "")))
+ ;; a type tag referencing the type we are extracting.
+ (setq typeref (semantic-tag-new-type
+ (semantic-tag-name basetype)
+ (semantic-tag-type basetype)
+ nil nil
+ :prototype t))
+ ;; Convert original tag to only have a reference.
+ (setq tag (semantic-tag-copy tag))
+ (semantic-tag-put-attribute tag :type typeref)
+ ;; Convert basetype to have the location information.
+ (semantic--tag-copy-properties tag basetype)
+ (semantic--tag-set-overlay basetype
+ (semantic-tag-overlay tag))
+ ;; Store the base tag as part of the return list.
+ (setq ret (cons basetype ret)))
+ (cons ret tag)))
+
(defun semantic-expand-c-tag-namelist (tag)
"Expand TAG whose name is a list into a list of tags, or nil."
(cond ((semantic-tag-of-class-p tag 'variable)
'public
nil))))
+(define-mode-local-override semantic-find-tags-included c-mode
+ (&optional table)
+ "Find all tags in TABLE that are of the 'include class.
+TABLE is a tag table. See `semantic-something-to-tag-table'.
+For C++, we also have to search namespaces for include tags."
+ (let ((tags (semantic-find-tags-by-class 'include table))
+ (namespaces (semantic-find-tags-by-type "namespace" table)))
+ (dolist (cur namespaces)
+ (setq tags
+ (append tags
+ (semantic-find-tags-by-class
+ 'include
+ (semantic-tag-get-attribute cur :members)))))
+ tags))
+
+
(define-mode-local-override semantic-tag-components c-mode (tag)
"Return components for TAG."
(if (and (eq (semantic-tag-class tag) 'type)
(string= (semantic-tag-type type) "typedef"))
(let ((dt (semantic-tag-get-attribute type :typedef)))
(cond ((and (semantic-tag-p dt)
- (not (semantic-analyze-tag-prototype-p dt)))
+ (not (semantic-tag-prototype-p dt)))
;; In this case, DT was declared directly. We need
;; to clone DT and apply a filename to it.
(let* ((fname (semantic-tag-file-name type))
;; Else, return tag unmodified.
tag)))
+(define-mode-local-override semanticdb-find-table-for-include c-mode
+ (includetag &optional table)
+ "For a single INCLUDETAG found in TABLE, find a `semanticdb-table' object
+INCLUDETAG is a semantic TAG of class 'include.
+TABLE is a semanticdb table that identifies where INCLUDETAG came from.
+TABLE is optional if INCLUDETAG has an overlay of :filename attribute.
+
+For C++, we also have to check if the include is inside a
+namespace, since this means all tags inside this include will
+have to be wrapped in that namespace."
+ (let ((inctable (semanticdb-find-table-for-include-default includetag table))
+ (inside-ns (semantic-tag-get-attribute includetag :inside-ns))
+ tags newtags namespaces prefix parenttable newtable)
+ (if (or (null inside-ns)
+ (not inctable)
+ (not (slot-boundp inctable 'tags)))
+ inctable
+ (when (and (eq inside-ns t)
+ ;; Get the table which has this include.
+ (setq parenttable
+ (semanticdb-find-table-for-include-default
+ (semantic-tag-new-include
+ (semantic--tag-get-property includetag :filename) nil)))
+ table)
+ ;; Find the namespace where this include is located.
+ (setq namespaces
+ (semantic-find-tags-by-type "namespace" parenttable))
+ (when (and namespaces
+ (slot-boundp inctable 'tags))
+ (dolist (cur namespaces)
+ (when (semantic-find-tags-by-name
+ (semantic-tag-name includetag)
+ (semantic-tag-get-attribute cur :members))
+ (setq inside-ns (semantic-tag-name cur))
+ ;; Cache the namespace value.
+ (semantic-tag-put-attribute includetag :inside-ns inside-ns)))))
+ (unless (semantic-find-tags-by-name
+ inside-ns
+ (semantic-find-tags-by-type "namespace" inctable))
+ (setq tags (oref inctable tags))
+ ;; Wrap tags inside namespace tag
+ (setq newtags
+ (list (semantic-tag-new-type inside-ns "namespace" tags nil)))
+ ;; Create new semantic-table for the wrapped tags, since we don't want
+ ;; the namespace to actually be a part of the header file.
+ (setq newtable (semanticdb-table "include with context"))
+ (oset newtable tags newtags)
+ (oset newtable parent-db (oref inctable parent-db))
+ (oset newtable file (oref inctable file)))
+ newtable)))
+
+
(define-mode-local-override semantic-get-local-variables c++-mode ()
"Do what `semantic-get-local-variables' does, plus add `this' if needed."
(let* ((origvar (semantic-get-local-variables-default))
txt)
(semantic-idle-summary-current-symbol-info-default))))
+(define-mode-local-override semantic--tag-similar-names-p c-mode (tag1 tag2 blankok)
+ "Compare the names of TAG1 and TAG2.
+If BLANKOK is false, then the names must exactly match.
+If BLANKOK is true, then always return t, as for C, the names don't matter
+for arguments compared."
+ (if blankok t (semantic--tag-similar-names-p-default tag1 tag2 nil)))
+
+(define-mode-local-override semantic--tag-similar-types-p c-mode (tag1 tag2)
+ "For c-mode, deal with TAG1 and TAG2 being used in different namespaces.
+In this case, one type will be shorter than the other. Instead
+of fully resolving all namespaces currently in scope for both
+types, we simply compare as many elements as the shorter type
+provides."
+ ;; First, we see if the default method fails
+ (if (semantic--tag-similar-types-p-default tag1 tag2)
+ t
+ (let* ((names
+ (mapcar
+ (lambda (tag)
+ (let ((type (semantic-tag-type tag)))
+ (unless (stringp type)
+ (setq type (semantic-tag-name type)))
+ (setq type (semantic-analyze-split-name type))
+ (when (stringp type)
+ (setq type (list type)))
+ type))
+ (list tag1 tag2)))
+ (len1 (length (car names)))
+ (len2 (length (cadr names))))
+ (cond
+ ((<= len1 len2)
+ (equal (nthcdr len1 (cadr names)) (car names)))
+ ((< len2 len1)
+ (equal (nthcdr len2 (car names)) (cadr names)))))))
+
+
+(define-mode-local-override semantic--tag-attribute-similar-p c-mode
+ (attr value1 value2 ignorable-attributes)
+ "For c-mode, allow function :arguments to ignore the :name attributes."
+ (cond ((eq attr :arguments)
+ (semantic--tag-attribute-similar-p-default attr value1 value2
+ (cons :name ignorable-attributes)))
+ (t
+ (semantic--tag-attribute-similar-p-default attr value1 value2
+ ignorable-attributes))))
+
(defvar-mode-local c-mode semantic-orphaned-member-metaparent-type "struct"
"When lost members are found in the class hierarchy generator, use a struct.")
(defvar-mode-local c-mode senator-step-at-tag-classes '(function variable)
"Tag classes where senator will stop at the end.")
+(defvar-mode-local c-mode semantic-tag-similar-ignorable-attributes
+ '(:prototype-flag :parent :typemodifiers)
+ "Tag attributes to ignore during similarity tests.
+:parent is here because some tags might specify a parent, while others are
+actually in their parent which is not accessible.")
+
;;;###autoload
(defun semantic-default-c-setup ()
"Set up a buffer for semantic parsing of the C language."
(setq semantic-lex-analyzer #'semantic-c-lexer)
(add-hook 'semantic-lex-reset-hooks 'semantic-lex-spp-reset-hook nil t)
+ (when (eq major-mode 'c++-mode)
+ (add-to-list 'semantic-lex-c-preprocessor-symbol-map '("__cplusplus" . "")))
)
;;;###autoload
(defun semantic-c-describe-environment ()
"Describe the Semantic features of the current C environment."
(interactive)
- (if (not (or (eq major-mode 'c-mode) (eq major-mode 'c++-mode)))
+ (if (not (member 'c-mode (mode-local-equivalent-mode-p major-mode)))
(error "Not useful to query C mode in %s mode" major-mode))
(let ((gcc (when (boundp 'semantic-gcc-setup-data)
semantic-gcc-setup-data))
(princ "\n\nInclude Path Summary:\n")
(when (and (boundp 'ede-object) ede-object)
(princ "\n This file's project include is handled by:\n")
- (princ " ")
- (princ (object-print ede-object))
- (princ "\n with the system path:\n")
- (dolist (dir (ede-system-include-path ede-object))
- (princ " ")
- (princ dir)
- (princ "\n"))
+ (let ((objs (if (listp ede-object)
+ ede-object
+ (list ede-object))))
+ (dolist (O objs)
+ (princ " EDE : ")
+ (princ (object-print O))
+ (let ((ipath (ede-system-include-path O)))
+ (if (not ipath)
+ (princ "\n with NO specified system include path.\n")
+ (princ "\n with the system path:\n")
+ (dolist (dir ipath)
+ (princ " ")
+ (princ dir)
+ (princ "\n"))))))
)
(when semantic-dependency-include-path
"Setup hook function for Emacs Lisp files and Semantic."
)
-(add-hook 'emacs-lisp-mode-hook 'semantic-default-elisp-setup)
-
;;; LISP MODE
;;
;; @TODO: Lisp supports syntaxes that Emacs Lisp does not.
;;
(add-hook 'lisp-mode-hook 'semantic-default-elisp-setup)
-(eval-after-load "semanticdb"
+(eval-after-load "semantic/db"
'(require 'semantic/db-el)
)
;;; Code:
(defun semantic-gcc-query (gcc-cmd &rest gcc-options)
- "Return program output to both standard output and standard error.
+ "Return program output or error code in case error happens.
GCC-CMD is the program to execute and GCC-OPTIONS are the options
to give to the program."
;; $ gcc -v
;;
- (let ((buff (get-buffer-create " *gcc-query*"))
- (old-lc-messages (getenv "LC_ALL")))
+ (let* ((buff (get-buffer-create " *gcc-query*"))
+ (old-lc-messages (getenv "LC_ALL"))
+ (options `(,nil ,(cons buff t) ,nil ,@gcc-options))
+ (err 0))
(with-current-buffer buff
(erase-buffer)
(setenv "LC_ALL" "C")
(condition-case nil
- (apply 'call-process gcc-cmd nil (cons buff t) nil gcc-options)
+ (setq err (apply 'call-process gcc-cmd options))
(error ;; Some bogus directory for the first time perhaps?
(let ((default-directory (expand-file-name "~/")))
(condition-case nil
- (apply 'call-process gcc-cmd nil (cons buff t) nil gcc-options)
+ (setq err (apply 'call-process gcc-cmd options))
(error ;; gcc doesn't exist???
nil)))))
(setenv "LC_ALL" old-lc-messages)
(prog1
- (buffer-string)
- (kill-buffer buff)
- )
- )))
+ (if (zerop err)
+ (buffer-string)
+ err)
+ (kill-buffer buff)))))
;;(semantic-gcc-get-include-paths "c")
;;(semantic-gcc-get-include-paths "c++")
(interactive)
(let* ((fields (or semantic-gcc-setup-data
(semantic-gcc-fields (semantic-gcc-query "gcc" "-v"))))
- (defines (semantic-cpp-defs (semantic-gcc-query "cpp" "-E" "-dM" "-x" "c++" null-device)))
+ (cpp-options `("-E" "-dM" "-x" "c++" ,null-device))
+ (query (let ((q (apply 'semantic-gcc-query "cpp" cpp-options)))
+ (if (stringp q)
+ q
+ ;; `cpp' command in `semantic-gcc-setup' doesn't work on
+ ;; Mac, try `gcc'.
+ (apply 'semantic-gcc-query "gcc" cpp-options))))
+ (defines (semantic-cpp-defs query))
(ver (cdr (assoc 'version fields)))
(host (or (cdr (assoc 'target fields))
(cdr (assoc '--target fields))
(prefix (cdr (assoc '--prefix fields)))
;; gcc output supplied paths
(c-include-path (semantic-gcc-get-include-paths "c"))
- (c++-include-path (semantic-gcc-get-include-paths "c++")))
+ (c++-include-path (semantic-gcc-get-include-paths "c++"))
+ (gcc-exe (locate-file "gcc" exec-path exec-suffixes 'executable))
+ )
;; Remember so we don't have to call GCC twice.
(setq semantic-gcc-setup-data fields)
- (unless c-include-path
+ (when (and (not c-include-path) gcc-exe)
;; Fallback to guesses
(let* ( ;; gcc include dirs
- (gcc-exe (locate-file "gcc" exec-path exec-suffixes 'executable))
(gcc-root (expand-file-name ".." (file-name-directory gcc-exe)))
(gcc-include (expand-file-name "include" gcc-root))
(gcc-include-c++ (expand-file-name "c++" gcc-include))
(semantic-add-system-include D 'c-mode))
(dolist (D (semantic-gcc-get-include-paths "c++"))
(semantic-add-system-include D 'c++-mode)
- (let ((cppconfig (concat D "/bits/c++config.h")))
- ;; Presumably there will be only one of these files in the try-paths list...
- (when (file-readable-p cppconfig)
+ (let ((cppconfig (list (concat D "/bits/c++config.h") (concat D "/sys/cdefs.h"))))
+ (dolist (cur cppconfig)
+ ;; Presumably there will be only one of these files in the try-paths list...
+ (when (file-readable-p cur)
;; Add it to the symbol file
(if (boundp 'semantic-lex-c-preprocessor-symbol-file)
;; Add to the core macro header list
- (add-to-list 'semantic-lex-c-preprocessor-symbol-file cppconfig)
+ (add-to-list 'semantic-lex-c-preprocessor-symbol-file cur)
;; Setup the core macro header
- (setq semantic-lex-c-preprocessor-symbol-file (list cppconfig)))
- )))
+ (setq semantic-lex-c-preprocessor-symbol-file (list cur)))
+ ))))
(if (not (boundp 'semantic-lex-c-preprocessor-symbol-map))
(setq semantic-lex-c-preprocessor-symbol-map nil))
(dolist (D defines)
(add-to-list 'semantic-lex-c-preprocessor-symbol-map D))
+ ;; Needed for parsing OS X libc
+ (when (eq system-type 'darwin)
+ (add-to-list 'semantic-lex-c-preprocessor-symbol-map '("__i386__" . "")))
(when (featurep 'semantic/bovine/c)
(semantic-c-reset-preprocessor-symbol-map))
nil))
;;; Commentary:
;;
-;; This file was generated from etc/grammars/make.by.
+;; This file was generated from admin/grammars/make.by.
;;; Code:
(require 'semantic/lex)
(eval-when-compile (require 'semantic/bovine))
-
\f
;;; Prologue
;;
semantic-flex-keywords-obarray semantic-make-by--keyword-table
))
+\f
+;;; Analyzers
+;;
+\f
+;;; Epilogue
+;;
+
(provide 'semantic/bovine/make-by)
;;; semantic/bovine/make-by.el ends here
(require 'make-mode)
(require 'semantic)
+(require 'semantic/bovine)
(require 'semantic/bovine/make-by)
(require 'semantic/analyze)
(require 'semantic/dep)
-;;; semantic-scm-by.el --- Generated parser support file
+;;; semantic/bovine/scm-by.el --- Generated parser support file
;; Copyright (C) 2001, 2003, 2009-2012 Free Software Foundation, Inc.
;;; Commentary:
;;
-;; This file was generated from etc/grammars/scm.by.
+;; This file was generated from admin/grammars/scm.by.
;;; Code:
(require 'semantic/lex)
-
(eval-when-compile (require 'semantic/bovine))
\f
;;; Prologue
semantic-flex-keywords-obarray semantic-scm-by--keyword-table
))
+\f
+;;; Analyzers
+;;
+\f
+;;; Epilogue
+;;
+
(provide 'semantic/bovine/scm-by)
;;; semantic/bovine/scm-by.el ends here
;; Use the Semantic Bovinator for Scheme (guile)
(require 'semantic)
+(require 'semantic/bovine)
(require 'semantic/bovine/scm-by)
(require 'semantic/format)
(require 'semantic/dep)
This should probably do some sort of search to see what is
actually on the local machine.")
-(define-mode-local-override semantic-format-tag-prototype scheme-mode (tag)
+(define-mode-local-override semantic-format-tag-prototype scheme-mode (tag &optional parent color)
"Return a prototype for the Emacs Lisp nonterminal TAG."
(let* ((tok (semantic-tag-class tag))
(args (semantic-tag-components tag))
(concat (semantic-tag-name tag) " ("
(mapconcat (lambda (a) a) args " ")
")")
- (semantic-format-tag-prototype-default tag))))
+ (semantic-format-tag-prototype-default tag parent color))))
(define-mode-local-override semantic-documentation-for-tag scheme-mode (tag &optional nosnarf)
"Return the documentation string for TAG.
(require 'semantic/ctxt)
(require 'semantic/decorate)
(require 'semantic/format)
+(require 'semantic/idle)
(eval-when-compile
;; For the semantic-find-tags-for-completion macro.
(cond
;; EXIT when we are no longer in a good place.
((or (not (eq b (current-buffer)))
- (< (point) s)
+ (<= (point) s)
(> (point) e))
;;(message "Exit: %S %S %S" s e (point))
(semantic-complete-inline-exit)
of a completion."
:abstract t)
+;;; Smart completion collector
+(defclass semantic-collector-analyze-completions (semantic-collector-abstract)
+ ((context :initarg :context
+ :type semantic-analyze-context
+ :documentation "An analysis context.
+Specifies some context location from whence completion lists will be drawn."
+ )
+ (first-pass-completions :type list
+ :documentation "List of valid completion tags.
+This list of tags is generated when completion starts. All searches
+derive from this list.")
+ )
+ "Completion engine that uses the context analyzer to provide options.
+The only options available for completion are those which can be logically
+inserted into the current context.")
+
+(defmethod semantic-collector-calculate-completions-raw
+ ((obj semantic-collector-analyze-completions) prefix completionlist)
+ "calculate the completions for prefix from completionlist."
+ ;; if there are no completions yet, calculate them.
+ (if (not (slot-boundp obj 'first-pass-completions))
+ (oset obj first-pass-completions
+ (semantic-analyze-possible-completions (oref obj context))))
+ ;; search our cached completion list. make it look like a semanticdb
+ ;; results type.
+ (list (cons (with-current-buffer (oref (oref obj context) buffer)
+ semanticdb-current-table)
+ (semantic-find-tags-for-completion
+ prefix
+ (oref obj first-pass-completions)))))
+
(defmethod semantic-collector-cleanup ((obj semantic-collector-abstract))
"Clean up any mess this collector may have."
nil)
(defmethod semantic-collector-next-action
((obj semantic-collector-abstract) partial)
- "What should we do next? OBJ can predict a next good action.
+ "What should we do next? OBJ can be used to determine the next action.
PARTIAL indicates if we are doing a partial completion."
(if (and (slot-boundp obj 'last-completion)
(string= (semantic-completion-text) (oref obj last-completion)))
"Calculate completions for prefix as setup for other queries."
(let* ((case-fold-search semantic-case-fold)
(same-prefix-p (semantic-collector-last-prefix= obj prefix))
+ (last-prefix (and (slot-boundp obj 'last-prefix)
+ (oref obj last-prefix)))
(completionlist
- (if (or same-prefix-p
- (and (slot-boundp obj 'last-prefix)
- (eq (compare-strings (oref obj last-prefix) 0 nil
- prefix 0 (length prefix))
- t)))
- ;; New prefix is subset of old prefix
- (oref obj last-all-completions)
- (semantic-collector-get-cache obj)))
+ (cond ((or same-prefix-p
+ (and last-prefix (eq (compare-strings
+ last-prefix 0 nil
+ prefix 0 (length last-prefix)) t)))
+ ;; We have the same prefix, or last-prefix is a
+ ;; substring of the of new prefix, in which case we are
+ ;; refining our symbol so just re-use cache.
+ (oref obj last-all-completions))
+ ((and last-prefix
+ (> (length prefix) 1)
+ (eq (compare-strings
+ prefix 0 nil
+ last-prefix 0 (length prefix)) t))
+ ;; The new prefix is a substring of the old
+ ;; prefix, and it's longer than one character.
+ ;; Perform a full search to pull in additional
+ ;; matches.
+ (let ((context (semantic-analyze-current-context (point))))
+ ;; Set new context and make first-pass-completions
+ ;; unbound so that they are newly calculated.
+ (oset obj context context)
+ (when (slot-boundp obj 'first-pass-completions)
+ (slot-makeunbound obj 'first-pass-completions)))
+ nil)))
;; Get the result
(answer (if same-prefix-p
completionlist
(semantic-collector-calculate-completions-raw
- obj prefix completionlist))
- )
+ obj prefix completionlist)))
(completion nil)
(complete-not-uniq nil)
)
(semantic-collector-buffer-abstract)
()
"Completion engine for tags in the current buffer.
-When searching for a tag, uses semantic deep searche functions.
+When searching for a tag, uses semantic deep search functions.
Basics search only in the current buffer.")
(defmethod semantic-collector-calculate-cache
(semantic-find-tags-for-completion prefix localstuff)))))
;(semanticdb-brute-deep-find-tags-for-completion prefix (oref obj path))))
-;;; Smart completion collector
-(defclass semantic-collector-analyze-completions (semantic-collector-abstract)
- ((context :initarg :context
- :type semantic-analyze-context
- :documentation "An analysis context.
-Specifies some context location from whence completion lists will be drawn."
- )
- (first-pass-completions :type list
- :documentation "List of valid completion tags.
-This list of tags is generated when completion starts. All searches
-derive from this list.")
- )
- "Completion engine that uses the context analyzer to provide options.
-The only options available for completion are those which can be logically
-inserted into the current context.")
-
-(defmethod semantic-collector-calculate-completions-raw
- ((obj semantic-collector-analyze-completions) prefix completionlist)
- "calculate the completions for prefix from completionlist."
- ;; if there are no completions yet, calculate them.
- (if (not (slot-boundp obj 'first-pass-completions))
- (oset obj first-pass-completions
- (semantic-analyze-possible-completions (oref obj context))))
- ;; search our cached completion list. make it look like a semanticdb
- ;; results type.
- (list (cons (with-current-buffer (oref (oref obj context) buffer)
- semanticdb-current-table)
- (semantic-find-tags-for-completion
- prefix
- (oref obj first-pass-completions)))))
-
\f
;;; ------------------------------------------------------------
;;; Tag List Display Engines
(defmethod semantic-displayor-next-action ((obj semantic-displayor-abstract))
"The next action to take on the minibuffer related to display."
(if (and (slot-boundp obj 'last-prefix)
- (string= (oref obj last-prefix) (semantic-completion-text))
- (eq last-command this-command))
+ (or (eq this-command 'semantic-complete-inline-TAB)
+ (and (string= (oref obj last-prefix) (semantic-completion-text))
+ (eq last-command this-command))))
'scroll
'display))
(nt (semanticdb-normalize-one-tag rtable rtag))
(tag (cdr nt))
(table (car nt))
- )
+ (curwin (selected-window)))
;; If we fail to normalize, reset.
(when (not tag) (setq table rtable tag rtag))
;; Do the focus.
(switch-to-buffer-other-window buf t)
(select-window (get-buffer-window buf)))
;; Now do some positioning
- (unwind-protect
- (if (semantic-tag-with-position-p tag)
- ;; Full tag positional information available
- (progn
- (goto-char (semantic-tag-start tag))
- ;; This avoids a dangerous problem if we just loaded a tag
- ;; from a file, but the original position was not updated
- ;; in the TAG variable we are currently using.
- (semantic-momentary-highlight-tag (semantic-current-tag))
- ))
- (select-window (minibuffer-window)))
+ (when (semantic-tag-with-position-p tag)
+ ;; Full tag positional information available
+ (goto-char (semantic-tag-start tag))
+ ;; This avoids a dangerous problem if we just loaded a tag
+ ;; from a file, but the original position was not updated
+ ;; in the TAG variable we are currently using.
+ (semantic-momentary-highlight-tag (semantic-current-tag)))
+ (select-window curwin)
;; Calculate text difference between contents and the focus item.
(let* ((mbc (semantic-completion-text))
(ftn (semantic-tag-name tag))
;; * Safe compatibility for tooltip free systems.
;; * Don't use 'avoid package for tooltip positioning.
+;;;###autoload
+(defcustom semantic-displayor-tooltip-mode 'standard
+ "Mode for the tooltip inline completion.
+
+Standard: Show only `semantic-displayor-tooltip-initial-max-tags'
+number of completions initially. Pressing TAB will show the
+extended set.
+
+Quiet: Only show completions when we have narrowed all
+posibilities down to a maximum of
+`semantic-displayor-tooltip-initial-max-tags' tags. Pressing TAB
+multiple times will also show completions.
+
+Verbose: Always show all completions available.
+
+The absolute maximum number of completions for all mode is
+determined through `semantic-displayor-tooltip-max-tags'."
+ :group 'semantic
+ :type '(choice (const :tag "Standard" standard)
+ (const :tag "Quiet" quiet)
+ (const :tag "Verbose" verbose)))
+
+;;;###autoload
+(defcustom semantic-displayor-tooltip-initial-max-tags 5
+ "Maximum number of tags to be displayed initially.
+See doc-string of `semantic-displayor-tooltip-mode' for details."
+ :group 'semantic
+ :type 'integer)
+
+(defcustom semantic-displayor-tooltip-max-tags 25
+ "The maximum number of tags to be displayed.
+Maximum number of completions where we have activated the
+extended completion list through typing TAB or SPACE multiple
+times. This limit needs to fit on your screen!
+
+Note: If available, customizing this variable increases
+'x-max-tooltip-size' to force over-sized tooltips when necessary.
+This will not happen if you directly set this variable via
+`setq'."
+ :group 'semantic
+ :type 'integer
+ :set '(lambda (sym var)
+ (set-default sym var)
+ (when (boundp 'x-max-tooltip-size)
+ (setcdr x-max-tooltip-size (max (1+ var) (cdr x-max-tooltip-size))))))
+
+
(defclass semantic-displayor-tooltip (semantic-displayor-traditional)
- ((max-tags :type integer
- :initarg :max-tags
- :initform 5
- :custom integer
- :documentation
- "Max number of tags displayed on tooltip at once.
-If `force-show' is 1, this value is ignored with typing tab or space twice continuously.
-if `force-show' is 0, this value is always ignored.")
- (force-show :type integer
- :initarg :force-show
- :initform 1
- :custom (choice (const
- :tag "Show when double typing"
- 1)
- (const
- :tag "Show always"
- 0)
- (const
- :tag "Show if the number of tags is less than `max-tags'."
- -1))
- :documentation
- "Control the behavior of the number of tags is greater than `max-tags'.
--1 means tags are never shown.
-0 means the tags are always shown.
-1 means tags are shown if space or tab is typed twice continuously.")
+ ((mode :initarg :mode
+ :initform
+ (symbol-value 'semantic-displayor-tooltip-mode)
+ :documentation
+ "See `semantic-displayor-tooltip-mode'.")
+ (max-tags-initial :initarg max-tags-initial
+ :initform
+ (symbol-value 'semantic-displayor-tooltip-initial-max-tags)
+ :documentation
+ "See `semantic-displayor-tooltip-initial-max-tags'.")
(typing-count :type integer
:initform 0
:documentation
(shown :type boolean
:initform nil
:documentation
- "Flag representing whether tags is shown once or not.")
+ "Flag representing whether tooltip has been shown yet.")
)
"Display completions options in a tooltip.
Display mechanism using tooltip for a list of possible completions.")
(call-next-method)
(let* ((tablelong (semanticdb-strip-find-results (oref obj table)))
(table (semantic-unique-tag-table-by-name tablelong))
- (l (mapcar semantic-completion-displayor-format-tag-function table))
- (ll (length l))
+ (completions (mapcar semantic-completion-displayor-format-tag-function table))
+ (numcompl (length completions))
(typing-count (oref obj typing-count))
- (force-show (oref obj force-show))
+ (mode (oref obj mode))
+ (max-tags (oref obj max-tags-initial))
(matchtxt (semantic-completion-text))
- msg)
- (if (or (oref obj shown)
- (< ll (oref obj max-tags))
- (and (<= 0 force-show)
- (< (1- force-show) typing-count)))
- (progn
- (oset obj typing-count 0)
- (oset obj shown t)
- (if (eq 1 ll)
- ;; We Have only one possible match. There could be two cases.
- ;; 1) input text != single match.
- ;; --> Show it!
- ;; 2) input text == single match.
- ;; --> Complain about it, but still show the match.
- (if (string= matchtxt (semantic-tag-name (car table)))
- (setq msg (concat "[COMPLETE]\n" (car l)))
- (setq msg (car l)))
- ;; Create the long message.
- (setq msg (mapconcat 'identity l "\n"))
- ;; If there is nothing, say so!
- (if (eq 0 (length msg))
- (setq msg "[NO MATCH]")))
- (semantic-displayor-tooltip-show msg))
- ;; The typing count determines if the user REALLY REALLY
- ;; wanted to show that much stuff. Only increment
- ;; if the current command is a completion command.
- (if (and (stringp (this-command-keys))
- (string= (this-command-keys) "\C-i"))
- (oset obj typing-count (1+ typing-count)))
- ;; At this point, we know we have too many items.
- ;; Let's be brave, and truncate l
- (setcdr (nthcdr (oref obj max-tags) l) nil)
- (setq msg (mapconcat 'identity l "\n"))
+ msg msg-tail)
+ ;; Keep a count of the consecutive completion commands entered by the user.
+ (if (and (stringp (this-command-keys))
+ (string= (this-command-keys) "\C-i"))
+ (oset obj typing-count (1+ (oref obj typing-count)))
+ (oset obj typing-count 0))
+ (cond
+ ((eq mode 'quiet)
+ ;; Switch back to standard mode if user presses key more than 5 times.
+ (when (>= (oref obj typing-count) 5)
+ (oset obj mode 'standard)
+ (setq mode 'standard)
+ (message "Resetting inline-mode to 'standard'."))
+ (when (and (> numcompl max-tags)
+ (< (oref obj typing-count) 2))
+ ;; Discretely hint at completion availability.
+ (setq msg "...")))
+ ((eq mode 'verbose)
+ ;; Always show extended match set.
+ (oset obj max-tags semantic-displayor-tooltip-max-tags)
+ (setq max-tags semantic-displayor-tooltip-max-tags)))
+ (unless msg
+ (oset obj shown t)
(cond
- ((= force-show -1)
- (semantic-displayor-tooltip-show (concat msg "\n...")))
- ((= force-show 1)
- (semantic-displayor-tooltip-show (concat msg "\n(TAB for more)")))
- )))))
+ ((> numcompl max-tags)
+ ;; We have too many items, be brave and truncate 'completions'.
+ (setcdr (nthcdr (1- max-tags) completions) nil)
+ (if (= max-tags semantic-displayor-tooltip-initial-max-tags)
+ (setq msg-tail (concat "\n[<TAB> " (number-to-string (- numcompl max-tags)) " more]"))
+ (setq msg-tail (concat "\n[<n/a> " (number-to-string (- numcompl max-tags)) " more]"))
+ (when (>= (oref obj typing-count) 2)
+ (message "Refine search to display results beyond the '%s' limit"
+ (symbol-name 'semantic-complete-inline-max-tags-extended)))))
+ ((= numcompl 1)
+ ;; two possible cases
+ ;; 1. input text != single match - we found a unique completion!
+ ;; 2. input text == single match - we found no additional matches, it's just the input text!
+ (when (string= matchtxt (semantic-tag-name (car table)))
+ (setq msg "[COMPLETE]\n")))
+ ((zerop numcompl)
+ (oset obj shown nil)
+ ;; No matches, say so if in verbose mode!
+ (when semantic-idle-scheduler-verbose-flag
+ (setq msg "[NO MATCH]"))))
+ ;; Create the tooltip text.
+ (setq msg (concat msg (mapconcat 'identity completions "\n"))))
+ ;; Add any tail info.
+ (setq msg (concat msg msg-tail))
+ ;; Display tooltip.
+ (when (not (eq msg ""))
+ (semantic-displayor-tooltip-show msg)))))
;;; Compatibility
;;
"Return the location of POINT as positioned on the selected frame.
Return a cons cell (X . Y)"
(let* ((frame (selected-frame))
- (left (frame-parameter frame 'left))
- (top (frame-parameter frame 'top))
+ (left (or (car-safe (cdr-safe (frame-parameter frame 'left)))
+ (frame-parameter frame 'left)))
+ (top (or (car-safe (cdr-safe (frame-parameter frame 'top)))
+ (frame-parameter frame 'top)))
(point-pix-pos (posn-x-y (posn-at-point)))
(edges (window-inside-pixel-edges (selected-window))))
(cons (+ (car point-pix-pos) (car edges) left)
(defmethod semantic-displayor-scroll-request ((obj semantic-displayor-tooltip))
"A request to for the displayor to scroll the completion list (if needed)."
;; Do scrolling in the tooltip.
- (oset obj max-tags 30)
+ (oset obj max-tags-initial 30)
(semantic-displayor-show-request obj)
)
(error nil))
))
+;;;;###autoload
+(defun semantic-complete-inline-project ()
+ "Perform inline completion for any symbol in the current project.
+`semantic-analyze-possible-completions' is used to determine the
+possible values.
+The function returns immediately, leaving the buffer in a mode that
+will perform the completion."
+ (interactive)
+ ;; Only do this if we are not already completing something.
+ (if (not (semantic-completion-inline-active-p))
+ (semantic-complete-inline-tag-project))
+ ;; Report a message if things didn't startup.
+ (if (and (called-interactively-p 'interactive)
+ (not (semantic-completion-inline-active-p)))
+ (message "Inline completion not needed."))
+ )
+
(provide 'semantic/complete)
;; Local variables:
;; End:
;;; semantic/complete.el ends here
+
(require 'eieio-base))
(declare-function semantic-elisp-desymbolify "semantic/bovine/el")
+(declare-function semantic-tag-similar-p "semantic/tag-ls")
;;; Code:
"Return nil, we never need a refresh."
nil)
+(defmethod object-print ((obj semanticdb-table-emacs-lisp) &rest strings)
+ "Pretty printer extension for `semanticdb-table-emacs-lisp'.
+Adds the number of tags in this file to the object print name."
+ (apply 'call-next-method obj (cons " (proxy)" strings)))
+
(defclass semanticdb-project-database-emacs-lisp
(semanticdb-project-database eieio-singleton)
((new-table-class :initform semanticdb-table-emacs-lisp
)
"Database representing Emacs core.")
+(defmethod object-print ((obj semanticdb-project-database-emacs-lisp) &rest strings)
+ "Pretty printer extension for `semanticdb-table-emacs-lisp'.
+Adds the number of tags in this file to the object print name."
+ (let ((count 0))
+ (mapatoms (lambda (sym) (setq count (1+ count))))
+ (apply 'call-next-method obj (cons
+ (format " (%d known syms)" count)
+ strings))))
+
;; Create the database, and add it to searchable databases for Emacs Lisp mode.
(defvar-mode-local emacs-lisp-mode semanticdb-project-system-databases
(list
(setq file (concat file ".gz"))))
(let* ((tab (semanticdb-file-table-object file))
- (alltags (semanticdb-get-tags tab))
- (newtags (semanticdb-find-tags-by-name-method
- tab (semantic-tag-name tag)))
+ (alltags (when tab (semanticdb-get-tags tab)))
+ (newtags (when tab (semanticdb-find-tags-by-name-method
+ tab (semantic-tag-name tag))))
(match nil))
;; Find the best match.
(dolist (T newtags)
(when (not match)
(setq match (car newtags)))
;; Return it.
- (cons tab match)))))
-
-(defun semanticdb-elisp-sym-function-arglist (sym)
- "Get the argument list for SYM.
-Deal with all different forms of function.
-This was snarfed out of eldoc."
- (let* ((prelim-def
- (let ((sd (and (fboundp sym)
- (symbol-function sym))))
- (and (symbolp sd)
- (condition-case err
- (setq sd (indirect-function sym))
- (error (setq sd nil))))
- sd))
- (def (if (eq (car-safe prelim-def) 'macro)
- (cdr prelim-def)
- prelim-def))
- (arglist (cond ((null def) nil)
- ((byte-code-function-p def)
- ;; This is an eieio compatibility function.
- ;; We depend on EIEIO, so use this.
- (eieio-compiled-function-arglist def))
- ((eq (car-safe def) 'lambda)
- (nth 1 def))
- (t nil))))
- arglist))
+ (when tab (cons tab match))))))
+
+(autoload 'help-function-arglist "help-fns")
+(defalias 'semanticdb-elisp-sym-function-arglist 'help-function-arglist)
+(make-obsolete 'semanticdb-elisp-sym-function-arglist
+ 'help-function-arglist "CEDET 1.1")
(defun semanticdb-elisp-sym->tag (sym &optional toktype)
"Convert SYM into a semantic tag.
(symbol-name sym)
nil ;; return type
(semantic-elisp-desymbolify
- (semanticdb-elisp-sym-function-arglist sym)) ;; arg-list
+ (help-function-arglist sym)) ;; arg-list
:user-visible-flag (condition-case nil
(interactive-form sym)
(error nil))
(require 'semantic/db)
(require 'cedet-files)
+(eval-when-compile
+ (require 'data-debug))
+
(defvar semanticdb-file-version semantic-version
"Version of semanticdb we are writing files to disk with.")
(defvar semanticdb-file-incompatible-version "1.4"
directory))
"/")
:file fn :tables nil
- :semantic-tag-version semantic-version
+ :semantic-tag-version semantic-tag-version
:semanticdb-version semanticdb-file-version)))
;; Set this up here. We can't put it in the constructor because it
;; would be saved, and we want DB files to be portable.
(defun semanticdb-load-database (filename)
"Load the database FILENAME."
(condition-case foo
- (let* ((r (eieio-persistent-read filename))
+ (let* ((r (eieio-persistent-read filename semanticdb-project-database-file))
(c (semanticdb-get-database-tables r))
(tv (oref r semantic-tag-version))
(fv (oref r semanticdb-version))
(defvar data-debug-thing-alist)
(declare-function data-debug-insert-stuff-list "data-debug")
+(declare-function data-debug-new-buffer "data-debug")
;;;(declare-function data-debug-insert-tag-list "adebug")
(declare-function semantic-scope-reset-cache "semantic/scope")
(declare-function semanticdb-typecache-notify-reset "semantic/db-typecache")
:group 'semanticdb
:type semanticdb-find-throttle-custom-list)
+(make-variable-buffer-local 'semanticdb-find-default-throttle)
+
(defun semanticdb-find-throttle-active-p (access-type)
"Non-nil if ACCESS-TYPE is an active throttle type."
(or (memq access-type semanticdb-find-default-throttle)
;; Find-file-match allows a tool to make sure the tag is
;; 'live', somewhere in a buffer.
(cond ((eq find-file-match 'name)
- (let ((f (semanticdb-full-filename nametable)))
- (semantic--tag-put-property ntag :filename f)))
+ (or (semantic--tag-get-property ntag :filename)
+ (let ((f (semanticdb-full-filename nametable)))
+ (semantic--tag-put-property ntag :filename f))))
((and find-file-match ntab)
(semanticdb-get-buffer ntab))
)
"In TABLE, find all occurrences of tags of CLASS.
Optional argument TAGS is a list of tags to search.
Returns a table of all matching tags."
- (semantic-find-tags-by-class class (or tags (semanticdb-get-tags table))))
+ ;; Delegate 'include' to the overridable
+ ;; `semantic-find-tags-included', which by default will just call
+ ;; `semantic-find-tags-by-class'.
+ (if (eq class 'include)
+ (semantic-find-tags-included (or tags (semanticdb-get-tags table)))
+ (semantic-find-tags-by-class class (or tags (semanticdb-get-tags table)))))
(defmethod semanticdb-find-tags-external-children-of-type-method ((table semanticdb-abstract-table) parent &optional tags)
"In TABLE, find all occurrences of tags whose parent is the PARENT type.
;;; Code:
;;;###autoload
-(defun semanticdb-enable-gnu-global-databases (mode)
+(defun semanticdb-enable-gnu-global-databases (mode &optional noerror)
"Enable the use of the GNU Global SemanticDB back end for all files of MODE.
This will add an instance of a GNU Global database to each buffer
-in a GNU Global supported hierarchy."
+in a GNU Global supported hierarchy.
+
+Two sanity checks are performed to assure (a) that GNU global program exists
+and (b) that the GNU global program version is compatibility with the database
+version. If optional NOERROR is nil, then an error may be signalled on version
+mismatch. If NOERROR is not nil, then no error will be signlled. Instead
+return value will indicate success or failure with non-nil or nil respective
+values."
(interactive
(list (completing-read
"Enable in Mode: " obarray
t (symbol-name major-mode))))
;; First, make sure the version is ok.
- (cedet-gnu-global-version-check)
-
- ;; Make sure mode is a symbol.
- (when (stringp mode)
- (setq mode (intern mode)))
-
- (let ((ih (mode-local-value mode 'semantic-init-mode-hook)))
- (eval `(setq-mode-local
- ,mode semantic-init-mode-hook
- (cons 'semanticdb-enable-gnu-global-hook ih))))
-
+ (if (not (cedet-gnu-global-version-check noerror))
+ nil
+ ;; Make sure mode is a symbol.
+ (when (stringp mode)
+ (setq mode (intern mode)))
+
+ (let ((ih (mode-local-value mode 'semantic-init-mode-hook)))
+ (eval `(setq-mode-local
+ ,mode semantic-init-mode-hook
+ (cons 'semanticdb-enable-gnu-global-hook ih))))
+ t
+ )
)
(defun semanticdb-enable-gnu-global-hook ()
(defclass semanticdb-project-database-global
;; @todo - convert to one DB per directory.
(semanticdb-project-database eieio-instance-tracker)
+
+ ;; @todo - use instance tracker symbol.
()
"Database representing a GNU Global tags file.")
)
"A table for returning search results from GNU Global.")
+(defmethod object-print ((obj semanticdb-table-global) &rest strings)
+ "Pretty printer extension for `semanticdb-table-global'.
+Adds the number of tags in this file to the object print name."
+ (apply 'call-next-method obj (cons " (proxy)" strings)))
+
(defmethod semanticdb-equivalent-mode ((table semanticdb-table-global) &optional buffer)
"Return t, pretend that this table's mode is equivalent to BUFFER.
Equivalent modes are specified by the `semantic-equivalent-major-modes'
(setq ans nil)))
)
+ ;; The typecache holds all the known types and elements. Some databases
+ ;; may provide tags that are simplified by name, and are proxies. These
+ ;; proxies must be resolved in order to extract type members.
+ (setq ans (semantic-tag-resolve-proxy ans))
+
(push ans calculated-scope)
;; Track most recent file.
(interactive)
(let* ((path (semanticdb-find-translate-path nil nil)))
(dolist (P path)
- (oset P pointmax nil)
+ (condition-case nil
+ (oset P pointmax nil)
+ ;; Pointmax may not exist for all tables disovered in the
+ ;; path.
+ (error nil))
(semantic-reset (semanticdb-get-typecache P)))))
(defun semanticdb-typecache-dump ()
(require 'eieio-base)
(require 'semantic)
+(eval-when-compile
+ (require 'semantic/find))
+
(declare-function semantic-lex-spp-save-table "semantic/lex-spp")
+;; Use autoload to avoid recursive require of semantic/db-ref
+(autoload 'semanticdb-refresh-references "semantic/db-ref"
+ "Refresh references to DBT in other files.")
+
;;; Variables:
(defgroup semanticdb nil
"Parser Generator Persistent Database interface."
:accessor semanticdb-get-tags
:printer semantic-tag-write-list-slot-value
:documentation "The tags belonging to this table.")
+ (db-refs :initform nil
+ :documentation
+ "List of `semanticdb-table' objects refering to this one.
+These aren't saved, but are instead recalculated after load.
+See the file semanticdb-ref.el for how this slot is used.")
(index :type semanticdb-abstract-search-index
:documentation "The search index.
Used by semanticdb-find to store additional information about
(cons obj tag))
(defmethod object-print ((obj semanticdb-abstract-table) &rest strings)
- "Pretty printer extension for `semanticdb-table'.
+ "Pretty printer extension for `semanticdb-abstract-table'.
Adds the number of tags in this file to the object print name."
- (apply 'call-next-method obj
- (cons (format " (%d tags)"
- (length (semanticdb-get-tags obj))
- )
- strings)))
+ (if (or (not strings)
+ (and (= (length strings) 1) (stringp (car strings))
+ (string= (car strings) "")))
+ ;; Else, add a tags quantifier.
+ (call-next-method obj (format " (%d tags)" (length (semanticdb-get-tags obj))))
+ ;; Pass through.
+ (apply 'call-next-method obj strings)
+ ))
;;; Index Cache
;;
;; a semanticdb-table associated with a file.
;;
(defclass semanticdb-search-results-table (semanticdb-abstract-table)
- (
- )
+ ()
"Table used for search results when there is no file or table association.
Examples include search results from external sources such as from
Emacs's own symbol table, or from external libraries.")
"Pretty printer extension for `semanticdb-table'.
Adds the number of tags in this file to the object print name."
(apply 'call-next-method obj
- (cons (if (oref obj dirty) ", DIRTY" "") strings)))
+ (cons (format " (%d tags)" (length (semanticdb-get-tags obj)))
+ (cons (if (oref obj dirty) ", DIRTY" "") strings))))
;;; DATABASE BASE CLASS
;;
Note: This index will not be saved in a persistent file.")
(tables :initarg :tables
- :type list
+ :type semanticdb-abstract-table-list
;; Need this protection so apps don't try to access
;; the tables without using the accessor.
:accessor semanticdb-get-database-tables
If there is no database for the table to live in, create one."
(let ((cdb nil)
(tbl nil)
- (dd (file-name-directory filename))
+ (dd (file-name-directory (file-truename filename)))
)
;; Allow a database override function
(setq cdb (semanticdb-create-database semanticdb-new-database-class
;; semanticdb-create-table-for-file-not-in-buffer
(save-excursion
(let ((buff (semantic-find-file-noselect
- (semanticdb-full-filename obj))))
+ (semanticdb-full-filename obj) t)))
(set-buffer buff)
(semantic-fetch-tags)
;; Kill off the buffer if it didn't exist when we were called.
)
;; Update cross references
- ;; (semanticdb-refresh-references table)
+ (semanticdb-refresh-references table)
)
(defmethod semanticdb-partial-synchronize ((table semanticdb-abstract-table)
)
;; Update cross references
- ;;(when (semantic-find-tags-by-class 'include new-tags)
- ;; (semanticdb-refresh-references table))
+ (when (semantic-find-tags-by-class 'include new-tags)
+ (semanticdb-refresh-references table))
)
;;; SAVE/LOAD
(defun semanticdb-save-current-db ()
"Save the current tag database."
(interactive)
- (message "Saving current tag summaries...")
+ (unless noninteractive
+ (message "Saving current tag summaries..."))
(semanticdb-save-db semanticdb-current-database)
- (message "Saving current tag summaries...done"))
+ (unless noninteractive
+ (message "Saving current tag summaries...done")))
;; This prevents Semanticdb from querying multiple times if the users
;; answers "no" to creating the Semanticdb directory.
(defun semanticdb-save-all-db ()
"Save all semantic tag databases."
(interactive)
- (message "Saving tag summaries...")
+ (unless noninteractive
+ (message "Saving tag summaries..."))
(let ((semanticdb--inhibit-make-directory nil))
(mapc 'semanticdb-save-db semanticdb-database-list))
- (message "Saving tag summaries...done"))
+ (unless noninteractive
+ (message "Saving tag summaries...done")))
(defun semanticdb-save-all-db-idle ()
"Save all semantic tag databases from idle time.
;; Install our map onto this buffer
(use-local-map semantic-debug-mode-map)
;; Make the buffer read only
- (toggle-read-only 1)
+ (setq buffer-read-only t)
(set-buffer (oref iface source-buffer))
;; Use our map in the source buffer also
(use-local-map semantic-debug-mode-map)
;; Make the buffer read only
- (toggle-read-only 1)
+ (setq buffer-read-only t)
;; Hooks
(run-hooks 'semantic-debug-mode-hook)
)
:help "Add an include path for this session." ])
))
+;;; Includes with no file, but a table
+;;
+(defface semantic-decoration-on-fileless-includes
+ '((((class color) (background dark))
+ (:background "#009000"))
+ (((class color) (background light))
+ (:background "#f0fdf0")))
+ "*Face used to show includes that have no file, but do have a DB table.
+Used by the decoration style: `semantic-decoration-on-fileless-includes'."
+ :group 'semantic-faces)
+
+(defvar semantic-decoration-on-fileless-include-map
+ (let ((km (make-sparse-keymap)))
+ ;(define-key km [ mouse-2 ] 'semantic-decoration-fileless-include-describe)
+ (define-key km semantic-decoratiton-mouse-3 'semantic-decoration-fileless-include-menu)
+ km)
+ "Keymap used on unparsed includes.")
+
+(defvar semantic-decoration-on-fileless-include-menu nil
+ "Menu used for unparsed include headers.")
+
+(easy-menu-define
+ semantic-decoration-on-fileless-include-menu
+ semantic-decoration-on-fileless-include-map
+ "Fileless Include Menu"
+ (list
+ "Fileless Include"
+ (semantic-menu-item
+ ["What Is This?" semantic-decoration-fileless-include-describe
+ :active t
+ :help "Describe why this include has been marked this way." ])
+ (semantic-menu-item
+ ["List all unknown includes" semanticdb-find-adebug-lost-includes
+ :active t
+ :help "Show a list of all includes semantic cannot find for this file." ])
+ "---"
+ (semantic-menu-item
+ ["Summarize includes current buffer" semantic-decoration-all-include-summary
+ :active t
+ :help "Show a summary for the current buffer containing this include." ])
+ (semantic-menu-item
+ ["List found includes (load unparsed)" semanticdb-find-test-translate-path
+ :active t
+ :help "List all includes found for this file, and parse unparsed files." ])
+ (semantic-menu-item
+ ["List found includes (no loading)" semanticdb-find-test-translate-path-no-loading
+ :active t
+ :help "List all includes found for this file, do not parse unparsed files." ])
+ "---"
+ (semantic-menu-item
+ ["Customize System Include Path" semantic-customize-system-include-path
+ :active (get 'semantic-dependency-system-include-path major-mode)
+ :help "Run customize for the system include path for this major mode." ])
+ (semantic-menu-item
+ ["Add a System Include Path" semantic-add-system-include
+ :active t
+ :help "Add an include path for this session." ])
+ (semantic-menu-item
+ ["Remove a System Include Path" semantic-remove-system-include
+ :active t
+ :help "Add an include path for this session." ])
+ ))
+
;;; Includes that need to be parsed.
;;
(defface semantic-decoration-on-unparsed-includes
(defun semantic-decoration-on-includes-highlight-default (tag)
"Highlight the include TAG to show that semantic can't find it."
(let* ((file (semantic-dependency-tag-file tag))
- (table (when file
- (semanticdb-file-table-object file t)))
+ (table (semanticdb-find-table-for-include tag (current-buffer)))
(face nil)
(map nil)
)
(cond
- ((not file)
+ ((and (not file) (not table))
;; Cannot find this header.
(setq face 'semantic-decoration-on-unknown-includes
map semantic-decoration-on-unknown-include-map)
)
+ ((and (not file) table)
+ ;; There is no file, but the language supports a table for this
+ ;; include. Import perhaps? System include with no file?
+ (setq face 'semantic-decoration-on-fileless-includes
+ map semantic-decoration-on-fileless-include-map)
+ )
((and table (number-or-marker-p (oref table pointmax)))
;; A found and parsed file.
(setq face 'semantic-decoration-on-includes
;;; Regular Include Functions
;;
(defun semantic-decoration-include-describe ()
- "Describe what unparsed includes are in the current buffer.
+ "Describe the current include tag.
Argument EVENT is the mouse clicked event."
(interactive)
(let* ((tag (or (semantic-current-tag)
;;; Unknown Include functions
;;
(defun semantic-decoration-unknown-include-describe ()
- "Describe what unknown includes are in the current buffer.
+ "Describe the current unknown include.
Argument EVENT is the mouse clicked event."
(interactive)
(let ((tag (semantic-current-tag))
)))
(defun semantic-decoration-unknown-include-menu (event)
- "Popup a menu that can help a user understand unparsed includes.
+ "Popup a menu that can help a user understand unknown includes.
Argument EVENT describes the event that caused this function to be called."
(interactive "e")
(let* ((startwin (selected-window))
)
(select-window startwin)))
+\f
+;;; Fileless Include functions
+;;
+(defun semantic-decoration-fileless-include-describe ()
+ "Describe the current fileless include.
+Argument EVENT is the mouse clicked event."
+ (interactive)
+ (let* ((tag (semantic-current-tag))
+ (table (semanticdb-find-table-for-include tag (current-buffer)))
+ (mm major-mode))
+ (with-output-to-temp-buffer (help-buffer) ; "*Help*"
+ (help-setup-xref (list #'semantic-decoration-fileless-include-describe)
+ (called-interactively-p 'interactive))
+ (princ "Include Tag: ")
+ (princ (semantic-format-tag-name tag nil t))
+ (princ "\n\n")
+ (princ "This header tag has been marked \"Fileless\".
+This means that Semantic cannot find a file associated with this tag
+on disk, but a database table of tags has been associated with it.
+
+This means that the include will still be used to find tags for
+searches, but you connot visit this include.\n\n")
+ (princ "This Header is now represented by the following database table:\n\n ")
+ (princ (object-print table))
+ )))
+
+(defun semantic-decoration-fileless-include-menu (event)
+ "Popup a menu that can help a user understand fileless includes.
+Argument EVENT describes the event that caused this function to be called."
+ (interactive "e")
+ (let* ((startwin (selected-window))
+ ;; This line has an issue in XEmacs.
+ (win (semantic-event-window event))
+ )
+ (select-window win t)
+ (save-excursion
+ ;(goto-char (window-start win))
+ (mouse-set-point event)
+ (sit-for 0)
+ (semantic-popup-menu semantic-decoration-on-fileless-include-menu)
+ )
+ (select-window startwin)))
+
\f
;;; Interactive parts of unparsed includes
;;
(dolist (tag unk)
(princ " ")
(princ (semantic-tag-name tag))
+ (when (not (eq (semantic-tag-name tag) (semantic-tag-include-filename tag)))
+ (princ " -> ")
+ (princ (semantic-tag-include-filename tag)))
(princ "\n"))
))
(semantic-make-local-hook 'semantic-after-toplevel-cache-change-hook)
(add-hook 'semantic-after-toplevel-cache-change-hook
'semantic-decorate-tags-after-full-reparse nil t)
+ ;; Decorate includes by default
+ (require 'semantic/decorate/include)
;; Add decorations to available tags. The above hooks ensure
;; that new tags will be decorated when they become available.
(semantic-decorate-add-decorations (semantic-fetch-available-tags)))
;; In case it's a real string, STRIPIT.
(while (string-match "\\s-*\\s\"+\\s-*" ct)
(setq ct (concat (substring ct 0 (match-beginning 0))
- (substring ct (match-end 0))))))
+ (substring ct (match-end 0)))))
+ ;; Remove comment delimiter at the end of the string.
+ (when (string-match (concat (regexp-quote comment-end) "$") ct)
+ (setq ct (substring ct 0 (match-beginning 0)))))
;; Now return the text.
ct))))
(require 'semantic/grammar)
;;; Code:
-(defclass semantic-ede-proj-target-grammar (ede-proj-target-makefile)
+(defclass semantic-ede-proj-target-grammar (ede-proj-target-elisp)
((menu :initform nil)
(keybindings :initform nil)
(phony :initform t)
(semantic-ede-grammar-compiler-wisent
semantic-ede-grammar-compiler-bovine
))
+ (aux-packages :initform '("semantic" "cedet-compat"))
+ (pre-load-packages :initform '("cedet-compat" "semantic/grammar" "semantic/bovine/grammar" "semantic/wisent/grammar"))
)
"This target consists of a group of grammar files.
A grammar target consists of grammar files that build Emacs Lisp programs for
parsing different languages.")
+(defmethod ede-proj-makefile-dependencies ((this semantic-ede-proj-target-grammar))
+ "Return a string representing the dependencies for THIS.
+Some compilers only use the first element in the dependencies, others
+have a list of intermediates (object files), and others don't care.
+This allows customization of how these elements appear.
+For Emacs Lisp, return addsuffix command on source files."
+ (let ((source (car (oref this source))))
+ (cond
+ ((string-match "\\.wy$" source)
+ (format "$(addsuffix -wy.elc, $(basename $(%s)))"
+ (ede-proj-makefile-sourcevar this)))
+ ((string-match "\\.by$" source)
+ (format "$(addsuffix -by.elc, $(basename $(%s)))"
+ (ede-proj-makefile-sourcevar this))))))
+
(defvar semantic-ede-source-grammar-wisent
(ede-sourcecode "semantic-ede-grammar-source-wisent"
:name "Wisent Grammar"
:sourcepattern "\\.wy$"
+ :garbagepattern '("*-wy.el")
)
"Semantic Grammar source code definition for wisent.")
(semantic-ede-grammar-compiler-class
"ede-emacs-wisent-compiler"
:name "emacs"
- :variables '(("EMACS" . "emacs"))
- :commands
- '(
- "@echo \"(add-to-list 'load-path nil)\" > grammar-make-script"
- "@for loadpath in . ${LOADPATH}; do \\"
- " echo \"(add-to-list 'load-path \\\"$$loadpath\\\")\" >> grammar-make-script; \\"
- "done;"
- "@echo \"(require 'semantic/load)\" >> grammar-make-script"
- "@echo \"(require 'semantic/grammar)\" >> grammar-make-script"
- ;; "@echo \"(setq debug-on-error t)\" >> grammar-make-script"
- "\"$(EMACS)\" -batch --no-site-file -l grammar-make-script -f semantic-grammar-batch-build-packages $^"
- )
- ;; :autoconf '("AM_PATH_LISPDIR")
+ :variables '(("EMACS" . "emacs")
+ ("EMACSFLAGS" . "-batch --no-site-file --eval '(setq debug-on-error t)'")
+ ("require" . "$(foreach r,$(1),(require (quote $(r))))"))
+ :rules (list (ede-makefile-rule
+ "elisp-inference-rule"
+ :target "%-wy.el"
+ :dependencies "%.wy"
+ :rules '("$(EMACS) $(EMACSFLAGS) $(addprefix -L ,$(LOADPATH)) \
+--eval '(progn $(call require,$(PRELOADS)))' -f semantic-grammar-batch-build-packages $^")))
:sourcetype '(semantic-ede-source-grammar-wisent)
- :objectextention "-wy.elc"
+ :objectextention "-wy.el"
)
"Compile Emacs Lisp programs.")
(ede-sourcecode "semantic-ede-grammar-source-bovine"
:name "Bovine Grammar"
:sourcepattern "\\.by$"
+ :garbagepattern '("*-by.el")
)
"Semantic Grammar source code definition for the bovinator.")
(semantic-ede-grammar-compiler-class
"ede-emacs-wisent-compiler"
:name "emacs"
- :variables '(("EMACS" . "emacs"))
- :commands
- '(
- "@echo \"(add-to-list 'load-path nil)\" > grammar-make-script"
- "@for loadpath in . ${LOADPATH}; do \\"
- " echo \"(add-to-list 'load-path \\\"$$loadpath\\\")\" >> grammar-make-script; \\"
- "done;"
- "@echo \"(require 'semantic/load)\" >> grammar-make-script"
- "@echo \"(require 'semantic/grammar)\" >> grammar-make-script"
- ;; "@echo \"(setq debug-on-error t)\" >> grammar-make-script"
- "\"$(EMACS)\" -batch --no-site-file -l grammar-make-script -f semantic-grammar-batch-build-packages $^"
- )
- ;; :autoconf '("AM_PATH_LISPDIR")
+ :variables '(("EMACS" . "emacs")
+ ("EMACSFLAGS" . "-batch --no-site-file --eval '(setq debug-on-error t)'")
+ ("require" . "$(foreach r,$(1),(require (quote $(r))))"))
+ :rules (list (ede-makefile-rule
+ "elisp-inference-rule"
+ :target "%-by.el"
+ :dependencies "%.by"
+ :rules '("$(EMACS) $(EMACSFLAGS) $(addprefix -L ,$(LOADPATH)) \
+--eval '(progn $(call require,$(PRELOADS)))' -f semantic-grammar-batch-build-packages $^")))
:sourcetype '(semantic-ede-source-grammar-bovine)
- :objectextention "-by.elc"
+ :objectextention "-by.el"
)
"Compile Emacs Lisp programs.")
"Compile all sources in a Lisp target OBJ."
(let* ((cb (current-buffer))
(proj (ede-target-parent obj))
- (default-directory (oref proj directory)))
+ (default-directory (oref proj directory))
+ (comp 0)
+ (utd 0))
(mapc (lambda (src)
(with-current-buffer (find-file-noselect src)
(save-excursion
(semantic-grammar-create-package))
+ ;; After compile, the current buffer is the compiled grammar.
+ ;; Save and compile it.
(save-buffer)
- (byte-recompile-file (concat (semantic-grammar-package) ".el") nil 0)))
- (oref obj source)))
- (message "All Semantic Grammar sources are up to date in %s" (object-name obj)))
+ (let* ((src (buffer-file-name))
+ (csrc (concat (file-name-sans-extension src) ".elc")))
+ (if (< emacs-major-version 24)
+ ;; Does not have `byte-recompile-file'
+ (if (or (not (file-exists-p csrc))
+ (file-newer-than-file-p src csrc))
+ (progn
+ (setq comp (1+ comp))
+ (byte-compile-file src))
+ (setq utd (1+ utd)))
+ ;; Emacs 24 and newer
+ (with-no-warnings
+ (if (eq (byte-recompile-file src nil 0) t)
+ (setq comp (1+ comp))
+ (setq utd (1+ utd))))))))
+ (oref obj source))
+ (message "All Semantic Grammar sources are up to date in %s" (object-name obj))
+ (cons comp utd)))
;;; Makefile generation functions
;;
" ")))
)
-(defmethod ede-proj-makefile-insert-rules ((this semantic-ede-proj-target-grammar))
- "Insert rules needed by THIS target."
- ;; Add in some dependencies.
-;; (mapc (lambda (src)
-;; (let ((nm (file-name-sans-extension src)))
-;; (insert nm "-wy.el: " src "\n"
-;; nm "-wy.elc: " nm "-wy.el\n\n")
-;; ))
-;; (oref this source))
- ;; Call the normal insertion of rules.
- (call-next-method)
- )
+(defmethod ede-proj-makefile-insert-rules :after ((this semantic-ede-proj-target-grammar))
+ "Insert rules needed by THIS target.
+This raises `max-specpdl-size' and `max-lisp-eval-depth', which can be
+needed for the compilation of the resulting parsers."
+ (insert (format "%s: EMACSFLAGS+= --eval '(setq max-specpdl-size 1500 \
+max-lisp-eval-depth 700)'\n"
+ (oref this name))))
(defmethod ede-proj-makefile-insert-dist-dependencies ((this semantic-ede-proj-target-grammar))
"Insert dist dependencies, or intermediate targets.
(require 'semantic/tag)
(declare-function semantic-tag-protected-p "semantic/tag-ls")
+(declare-function semantic-tag-package-protected-p "semantic/tag-ls")
;;; Overlay Search Routines
;;
table
(require 'semantic/tag-ls)
(semantic--find-tags-by-macro
- (not (semantic-tag-protected-p (car tags) scopeprotection parent))
+ (not (and (semantic-tag-protected-p (car tags) scopeprotection parent)
+ (semantic-tag-package-protected-p (car tags) parent)))
table)))
-(defsubst semantic-find-tags-included (&optional table)
+;;;###autoload
+(define-overloadable-function semantic-find-tags-included (&optional table)
"Find all tags in TABLE that are of the 'include class.
-TABLE is a tag table. See `semantic-something-to-tag-table'."
+TABLE is a tag table. See `semantic-something-to-tag-table'.")
+
+(defun semantic-find-tags-included-default (&optional table)
+ "Find all tags in TABLE that are of the 'include class.
+TABLE is a tag table. See `semantic-something-to-tag-table'.
+By default, just call `semantic-find-tags-by-class'."
(semantic-find-tags-by-class 'include table))
;;; Deep Searches
(load "semantic/loaddefs" nil 'nomessage)
;;; Compatibility
-
-(defalias 'semantic-buffer-local-value 'buffer-local-value)
-(defalias 'semantic-overlay-live-p 'overlay-buffer)
-(defalias 'semantic-make-overlay 'make-overlay)
-(defalias 'semantic-overlay-put 'overlay-put)
-(defalias 'semantic-overlay-get 'overlay-get)
-(defalias 'semantic-overlay-properties 'overlay-properties)
-(defalias 'semantic-overlay-move 'move-overlay)
-(defalias 'semantic-overlay-delete 'delete-overlay)
-(defalias 'semantic-overlays-at 'overlays-at)
-(defalias 'semantic-overlays-in 'overlays-in)
-(defalias 'semantic-overlay-buffer 'overlay-buffer)
-(defalias 'semantic-overlay-start 'overlay-start)
-(defalias 'semantic-overlay-end 'overlay-end)
-(defalias 'semantic-overlay-size 'overlay-size)
-(defalias 'semantic-overlay-next-change 'next-overlay-change)
-(defalias 'semantic-overlay-previous-change 'previous-overlay-change)
-(defalias 'semantic-overlay-lists 'overlay-lists)
-(defalias 'semantic-overlay-p 'overlayp)
-(defalias 'semantic-read-event 'read-event)
-(defalias 'semantic-popup-menu 'popup-menu)
-(defalias 'semantic-make-local-hook 'identity)
-(defalias 'semantic-mode-line-update 'force-mode-line-update)
-(defalias 'semantic-run-mode-hooks 'run-mode-hooks)
-(defalias 'semantic-compile-warn 'byte-compile-warn)
-(defalias 'semantic-menu-item 'identity)
-
-(defun semantic-event-window (event)
- "Extract the window from EVENT."
- (car (car (cdr event))))
+;;
+(eval-and-compile
+ (if (featurep 'xemacs)
+ (progn
+ (defalias 'semantic-buffer-local-value 'symbol-value-in-buffer)
+ (defalias 'semantic-overlay-live-p
+ (lambda (o)
+ (and (extent-live-p o)
+ (not (extent-detached-p o))
+ (bufferp (extent-buffer o)))))
+ (defalias 'semantic-make-overlay
+ (lambda (beg end &optional buffer &rest rest)
+ "Xemacs `make-extent', supporting the front/rear advance options."
+ (let ((ol (make-extent beg end buffer)))
+ (when rest
+ (set-extent-property ol 'start-open (car rest))
+ (setq rest (cdr rest)))
+ (when rest
+ (set-extent-property ol 'end-open (car rest)))
+ ol)))
+ (defalias 'semantic-overlay-put 'set-extent-property)
+ (defalias 'semantic-overlay-get 'extent-property)
+ (defalias 'semantic-overlay-properties 'extent-properties)
+ (defalias 'semantic-overlay-move 'set-extent-endpoints)
+ (defalias 'semantic-overlay-delete 'delete-extent)
+ (defalias 'semantic-overlays-at
+ (lambda (pos)
+ (condition-case nil
+ (extent-list nil pos pos)
+ (error nil))
+ ))
+ (defalias 'semantic-overlays-in
+ (lambda (beg end) (extent-list nil beg end)))
+ (defalias 'semantic-overlay-buffer 'extent-buffer)
+ (defalias 'semantic-overlay-start 'extent-start-position)
+ (defalias 'semantic-overlay-end 'extent-end-position)
+ (defalias 'semantic-overlay-size 'extent-length)
+ (defalias 'semantic-overlay-next-change 'next-extent-change)
+ (defalias 'semantic-overlay-previous-change 'previous-extent-change)
+ (defalias 'semantic-overlay-lists
+ (lambda () (list (extent-list))))
+ (defalias 'semantic-overlay-p 'extentp)
+ (defalias 'semantic-event-window 'event-window)
+ (defun semantic-read-event ()
+ (let ((event (next-command-event)))
+ (if (key-press-event-p event)
+ (let ((c (event-to-character event)))
+ (if (char-equal c (quit-char))
+ (keyboard-quit)
+ c)))
+ event))
+ (defun semantic-popup-menu (menu)
+ "Blockinig version of `popup-menu'"
+ (popup-menu menu)
+ ;; Wait...
+ (while (popup-up-p) (dispatch-event (next-event))))
+ )
+ ;; Emacs Bindings
+ (defalias 'semantic-overlay-live-p 'overlay-buffer)
+ (defalias 'semantic-make-overlay 'make-overlay)
+ (defalias 'semantic-overlay-put 'overlay-put)
+ (defalias 'semantic-overlay-get 'overlay-get)
+ (defalias 'semantic-overlay-properties 'overlay-properties)
+ (defalias 'semantic-overlay-move 'move-overlay)
+ (defalias 'semantic-overlay-delete 'delete-overlay)
+ (defalias 'semantic-overlays-at 'overlays-at)
+ (defalias 'semantic-overlays-in 'overlays-in)
+ (defalias 'semantic-overlay-buffer 'overlay-buffer)
+ (defalias 'semantic-overlay-start 'overlay-start)
+ (defalias 'semantic-overlay-end 'overlay-end)
+ (defalias 'semantic-overlay-next-change 'next-overlay-change)
+ (defalias 'semantic-overlay-previous-change 'previous-overlay-change)
+ (defalias 'semantic-overlay-lists 'overlay-lists)
+ (defalias 'semantic-overlay-p 'overlayp)
+ (defalias 'semantic-read-event 'read-event)
+ (defalias 'semantic-popup-menu 'popup-menu)
+ (defun semantic-event-window (event)
+ "Extract the window from EVENT."
+ (car (car (cdr event))))
+
+ (if (> emacs-major-version 21)
+ (defalias 'semantic-buffer-local-value 'buffer-local-value)
+
+ (defun semantic-buffer-local-value (sym &optional buf)
+ "Get the value of SYM from buffer local variable in BUF."
+ (cdr (assoc sym (buffer-local-variables buf)))))
+ )
+
+
+ (if (and (not (featurep 'xemacs))
+ (>= emacs-major-version 21))
+ (defalias 'semantic-make-local-hook 'identity)
+ (defalias 'semantic-make-local-hook 'make-local-hook)
+ )
+
+ (if (featurep 'xemacs)
+ (defalias 'semantic-mode-line-update 'redraw-modeline)
+ (defalias 'semantic-mode-line-update 'force-mode-line-update))
+
+ ;; Since Emacs 22 major mode functions should use `run-mode-hooks' to
+ ;; run major mode hooks.
+ (defalias 'semantic-run-mode-hooks
+ (if (fboundp 'run-mode-hooks)
+ 'run-mode-hooks
+ 'run-hooks))
+
+ ;; Fancy compat useage now handled in cedet-compat
+ (defalias 'semantic-subst-char-in-string 'subst-char-in-string)
+ )
(defun semantic-delete-overlay-maybe (overlay)
"Delete OVERLAY if it is a semantic token overlay."
(if (semantic-overlay-get overlay 'semantic)
(semantic-overlay-delete overlay)))
+;;; Menu Item compatibility
+;;
+(defun semantic-menu-item (item)
+ "Build an XEmacs compatible menu item from vector ITEM.
+That is remove the unsupported :help stuff."
+ (if (featurep 'xemacs)
+ (let ((n (length item))
+ (i 0)
+ slot l)
+ (while (< i n)
+ (setq slot (aref item i))
+ (if (and (keywordp slot)
+ (eq slot :help))
+ (setq i (1+ i))
+ (setq l (cons slot l)))
+ (setq i (1+ i)))
+ (apply #'vector (nreverse l)))
+ item))
+
;;; Positional Data Cache
;;
(defvar semantic-cache-data-overlays nil
(when ans
(semantic-overlay-get ans 'cached-value)))))
+(defun semantic-test-data-cache ()
+ "Test the data cache."
+ (interactive)
+ (let ((data '(a b c)))
+ (save-current-buffer
+ (set-buffer (get-buffer-create " *semantic-test-data-cache*"))
+ (save-excursion
+ (erase-buffer)
+ (insert "The Moose is Loose")
+ (goto-char (point-min))
+ (semantic-cache-data-to-buffer (current-buffer) (point) (+ (point) 5)
+ data 'moose 'exit-cache-zone)
+ (if (equal (semantic-get-cache-data 'moose) data)
+ (message "Successfully retrieved cached data.")
+ (error "Failed to retrieve cached data"))
+ ))))
+
;;; Obsoleting various functions & variables
;;
(defun semantic-overload-symbol-from-function (name)
(not (string-match "cedet" byte-compile-current-file))
)
(make-obsolete-overload oldfnalias newfn when)
- (semantic-compile-warn
+ (byte-compile-warn
"%s: `%s' obsoletes overload `%s'"
byte-compile-current-file
newfn
;; Only throw this warning when byte compiling things.
(when (and (boundp 'byte-compile-current-file)
byte-compile-current-file)
- (semantic-compile-warn
+ (byte-compile-warn
"variable `%s' obsoletes, but isn't alias of `%s'"
newvar oldvaralias)
))))
"Call `find-file-noselect' with various features turned off.
Use this when referencing a file that will be soon deleted.
FILE, NOWARN, RAWFILE, and WILDCARDS are passed into `find-file-noselect'"
+ ;; Hack -
+ ;; Check if we are in set-auto-mode, and if so, warn about this.
+ (when (or (and (featurep 'emacs) (boundp 'keep-mode-if-same))
+ (and (featurep 'xemacs) (boundp 'just-from-file-name)))
+ (let ((filename (or (and (boundp 'filename) filename)
+ "(unknown)")))
+ (message "WARNING: semantic-find-file-noselect called for \
+%s while in set-auto-mode for %s. You should call the responsible function \
+into `mode-local-init-hook'." file filename)
+ (sit-for 1)))
+
(let* ((recentf-exclude '( (lambda (f) t) ))
;; This is a brave statement. Don't waste time loading in
;; lots of modes. Especially decoration mode can waste a lot
(ede-auto-add-method 'never)
;; Ask font-lock to not colorize these buffers, nor to
;; whine about it either.
- (font-lock-maximum-size 0)
+ (global-font-lock-mode nil)
(font-lock-verbose nil)
+ ;; This forces flymake to ignore this buffer on find-file, and
+ ;; prevents flymake processes from being started.
+ (flymake-start-syntax-check-on-find-file nil)
;; Disable revision control
(vc-handled-backends nil)
;; Don't prompt to insert a template if we visit an empty file
;; Copyright (C) 2002-2004, 2009-2012 Free Software Foundation, Inc.
-;; Author: David Ponce <david@dponce.com>
-;; Keywords: syntax
-
;; This file is part of GNU Emacs.
;; GNU Emacs is free software: you can redistribute it and/or modify
;;; Code:
(require 'semantic/lex)
+(eval-when-compile (require 'semantic/bovine))
+\f
+;;; Prologue
+;;
(defvar semantic-grammar-lex-c-char-re)
;; Current parsed nonterminal name.
("%left" . LEFT)
("%nonassoc" . NONASSOC)
("%package" . PACKAGE)
+ ("%provide" . PROVIDE)
("%prec" . PREC)
("%put" . PUT)
("%quotemode" . QUOTEMODE)
(eval-when-compile
(require 'semantic/wisent/comp))
(wisent-compile-grammar
- '((DEFAULT-PREC NO-DEFAULT-PREC KEYWORD LANGUAGEMODE LEFT NONASSOC PACKAGE PREC PUT QUOTEMODE RIGHT SCOPESTART START TOKEN TYPE USE-MACROS STRING SYMBOL PERCENT_PERCENT CHARACTER PREFIXED_LIST SEXP PROLOGUE EPILOGUE PAREN_BLOCK BRACE_BLOCK LPAREN RPAREN LBRACE RBRACE COLON SEMI OR LT GT)
+ '((DEFAULT-PREC NO-DEFAULT-PREC KEYWORD LANGUAGEMODE LEFT NONASSOC PACKAGE PROVIDE PREC PUT QUOTEMODE RIGHT SCOPESTART START TOKEN TYPE USE-MACROS STRING SYMBOL PERCENT_PERCENT CHARACTER PREFIXED_LIST SEXP PROLOGUE EPILOGUE PAREN_BLOCK BRACE_BLOCK LPAREN RPAREN LBRACE RBRACE COLON SEMI OR LT GT)
nil
(grammar
((prologue))
((no_default_prec_decl))
((languagemode_decl))
((package_decl))
+ ((provide_decl))
((precedence_decl))
((put_decl))
((quotemode_decl))
((PACKAGE SYMBOL)
`(wisent-raw-tag
(semantic-tag-new-package ',$2 nil))))
+ (provide_decl
+ ((PROVIDE SYMBOL)
+ `(wisent-raw-tag
+ (semantic-tag ',$2 'provide))))
(precedence_decl
((associativity token_type_opt items)
`(wisent-raw-tag
'((parse-stream . wisent-parse-stream)))
(setq semantic-parser-name "LALR"
semantic--parse-table semantic-grammar-wy--parse-table
- semantic-debug-parser-source "semantic-grammar.wy"
+ semantic-debug-parser-source "grammar.wy"
semantic-flex-keywords-obarray semantic-grammar-wy--keyword-table
semantic-lex-types-obarray semantic-grammar-wy--token-table)
;; Collect unmatched syntax lexical tokens
(semantic-make-local-hook 'wisent-discarding-token-functions)
(add-hook 'wisent-discarding-token-functions
- 'wisent-collect-unmatched-syntax nil t))
+ 'wisent-collect-unmatched-syntax nil t))
\f
;;; Analyzers
-
-(define-lex-sexp-type-analyzer semantic-grammar-wy--<sexp>-sexp-analyzer
- "sexp analyzer for <sexp> tokens."
- "\\="
- 'SEXP)
-
-(define-lex-sexp-type-analyzer semantic-grammar-wy--<qlist>-sexp-analyzer
- "sexp analyzer for <qlist> tokens."
- "\\s'\\s-*("
- 'PREFIXED_LIST)
-
-(define-lex-keyword-type-analyzer semantic-grammar-wy--<keyword>-keyword-analyzer
- "keyword analyzer for <keyword> tokens."
- "\\(\\sw\\|\\s_\\)+")
-
+;;
(define-lex-block-type-analyzer semantic-grammar-wy--<block>-block-analyzer
"block analyzer for <block> tokens."
"\\s(\\|\\s)"
nil
'CHARACTER)
-(define-lex-sexp-type-analyzer semantic-grammar-wy--<string>-sexp-analyzer
- "sexp analyzer for <string> tokens."
- "\\s\""
- 'STRING)
-
(define-lex-regex-type-analyzer semantic-grammar-wy--<symbol>-regexp-analyzer
"regexp analyzer for <symbol> tokens."
":?\\(\\sw\\|\\s_\\)+"
'((PERCENT_PERCENT . "\\`%%\\'"))
'SYMBOL)
+(define-lex-sexp-type-analyzer semantic-grammar-wy--<qlist>-sexp-analyzer
+ "sexp analyzer for <qlist> tokens."
+ "\\s'\\s-*("
+ 'PREFIXED_LIST)
+
+(define-lex-sexp-type-analyzer semantic-grammar-wy--<string>-sexp-analyzer
+ "sexp analyzer for <string> tokens."
+ "\\s\""
+ 'STRING)
+
(define-lex-string-type-analyzer semantic-grammar-wy--<punctuation>-string-analyzer
"string analyzer for <punctuation> tokens."
"\\(\\s.\\|\\s$\\|\\s'\\)+"
(COLON . ":"))
'punctuation)
+(define-lex-keyword-type-analyzer semantic-grammar-wy--<keyword>-keyword-analyzer
+ "keyword analyzer for <keyword> tokens."
+ "\\(\\sw\\|\\s_\\)+")
+
+(define-lex-sexp-type-analyzer semantic-grammar-wy--<sexp>-sexp-analyzer
+ "sexp analyzer for <sexp> tokens."
+ "\\="
+ 'SEXP)
+
+\f
+;;; Epilogue
+;;
+
+
+
+
(provide 'semantic/grammar-wy)
;;; semantic/grammar-wy.el ends here
;;; Code:
(require 'semantic)
+(require 'semantic/wisent)
(require 'semantic/ctxt)
(require 'semantic/format)
(require 'semantic/grammar-wy)
(require 'semantic/idle)
+
(declare-function semantic-momentary-highlight-tag "semantic/decorate")
(declare-function semantic-analyze-context "semantic/analyze")
(declare-function semantic-analyze-tags-of-class-list
(eval-when-compile
(require 'eldoc)
(require 'semantic/edit)
- (require 'semantic/find))
+ (require 'semantic/find)
+ (require 'semantic/db))
\f
;;;;
;;;;
(defvar semantic--grammar-input-buffer nil)
(defvar semantic--grammar-output-buffer nil)
+(defvar semantic--grammar-package nil)
+(defvar semantic--grammar-provide nil)
(defsubst semantic-grammar-keywordtable ()
"Return the variable name of the keyword table."
- (concat (file-name-sans-extension
- (semantic-grammar-buffer-file
- semantic--grammar-output-buffer))
+ (concat semantic--grammar-package
"--keyword-table"))
(defsubst semantic-grammar-tokentable ()
"Return the variable name of the token table."
- (concat (file-name-sans-extension
- (semantic-grammar-buffer-file
- semantic--grammar-output-buffer))
+ (concat semantic--grammar-package
"--token-table"))
(defsubst semantic-grammar-parsetable ()
"Return the variable name of the parse table."
- (concat (file-name-sans-extension
- (semantic-grammar-buffer-file
- semantic--grammar-output-buffer))
+ (concat semantic--grammar-package
"--parse-table"))
(defsubst semantic-grammar-setupfunction ()
"Return the name of the parser setup function."
- (concat (file-name-sans-extension
- (semantic-grammar-buffer-file
- semantic--grammar-output-buffer))
+ (concat semantic--grammar-package
"--install-parser"))
(defmacro semantic-grammar-as-string (object)
;;
;;; Code:
+
+(require 'semantic/lex)
+(eval-when-compile (require 'semantic/bovine))
")
"Generated header template.
The symbols in the template are local variables in
"Return text of a generated standard footer."
(let* ((file (semantic-grammar-buffer-file
semantic--grammar-output-buffer))
- (libr (file-name-sans-extension file))
+ (libr (or semantic--grammar-provide
+ semantic--grammar-package))
(out ""))
(dolist (S semantic-grammar-footer-template)
(cond ((stringp S)
;; explicitly declared in a %type statement, and if at least the
;; syntax property has been provided.
(when (and declared syntax)
- (setq prefix (file-name-sans-extension
- (semantic-grammar-buffer-file
- semantic--grammar-output-buffer))
+ (setq prefix semantic--grammar-package
mtype (or (get type 'matchdatatype) 'regexp)
name (intern (format "%s--<%s>-%s-analyzer" prefix type mtype))
doc (format "%s analyzer for <%s> tokens." mtype type))
(with-current-buffer semantic--grammar-input-buffer
(setq tokens (semantic-grammar-tokens)
props (semantic-grammar-token-properties tokens)))
- (insert "(require 'semantic/lex)\n\n")
(let ((semantic-lex-types-obarray
(semantic-lex-make-type-table tokens props))
semantic-grammar--lex-block-specs)
;; Values of the following local variables are obtained from
;; the grammar parsed tree in current buffer, that is before
;; switching to the output file.
- (package (semantic-grammar-package))
- (output (concat package ".el"))
+ (semantic--grammar-package (semantic-grammar-package))
+ (semantic--grammar-provide (semantic-grammar-first-tag-name 'provide))
+ (output (concat (or semantic--grammar-provide
+ semantic--grammar-package) ".el"))
(semantic--grammar-input-buffer (current-buffer))
- (semantic--grammar-output-buffer (find-file-noselect output))
+ (semantic--grammar-output-buffer
+ (find-file-noselect
+ (file-name-nondirectory output)))
(header (semantic-grammar-header))
(prologue (semantic-grammar-prologue))
(epilogue (semantic-grammar-epilogue))
(file-newer-than-file-p
(buffer-file-name semantic--grammar-output-buffer)
(buffer-file-name semantic--grammar-input-buffer)))
- (message "Package `%s' is up to date." package)
+ (message "Package `%s' is up to date." semantic--grammar-package)
;; Create the package
(set-buffer semantic--grammar-output-buffer)
;; Use Unix EOLs, so that the file is portable to all platforms.
(let ((packagename
(condition-case err
(with-current-buffer (find-file-noselect file)
- (semantic-grammar-create-package))
+ (let ((semantic-new-buffer-setup-functions nil)
+ (vc-handled-backends nil))
+ (setq semanticdb-new-database-class 'semanticdb-project-database)
+ (semantic-mode 1)
+ (semantic-grammar-create-package)))
(error
(message "%s" (error-message-string err))
nil))))
;; Remove vc from find-file-hook. It causes bad stuff to
;; happen in Emacs 20.
(find-file-hook (delete 'vc-find-file-hook find-file-hook)))
- (message "Compiling Grammars from: %s" (locate-library "semantic-grammar"))
(dolist (arg command-line-args-left)
(unless (and arg (file-exists-p arg))
(error "Argument %s is not a valid file name" arg))
(require 'semantic/analyze)
(require 'semantic/format)
(require 'pulse)
+(require 'semantic/senator)
+(require 'semantic/analyze/refs)
(eval-when-compile
(require 'semantic/analyze)
- (require 'semantic/analyze/refs)
(require 'semantic/find))
(declare-function imenu--mouse-menu "imenu")
(mapcar semantic-ia-completion-format-tag-function syms)))))))))
(defcustom semantic-ia-completion-menu-format-tag-function
- 'semantic-uml-concise-prototype-nonterminal
+ 'semantic-format-tag-uml-concise-prototype
"*Function used to convert a tag to a string during completion."
:group 'semantic
:type semantic-format-tag-custom-list)
+;;;###autoload
+(defun semantic-ia-complete-symbol-menu (point)
+ "Complete the current symbol via a menu based at POINT.
+Completion options are calculated with `semantic-analyze-possible-completions'."
+ (interactive "d")
+ (require 'imenu)
+ (let* ((a (semantic-analyze-current-context point))
+ (syms (semantic-analyze-possible-completions a))
+ )
+ ;; Complete this symbol.
+ (if (not syms)
+ (progn
+ (message "No smart completions found. Trying Senator.")
+ (when (semantic-analyze-context-p a)
+ ;; This is a quick way of getting a nice completion list
+ ;; in the menu if the regular context mechanism fails.
+ (senator-completion-menu-popup)))
+
+ (let* ((menu
+ (mapcar
+ (lambda (tag)
+ (cons
+ (funcall semantic-ia-completion-menu-format-tag-function tag)
+ (vector tag)))
+ syms))
+ (ans
+ (imenu--mouse-menu
+ ;; XEmacs needs that the menu has at least 2 items. So,
+ ;; include a nil item that will be ignored by imenu.
+ (cons nil menu)
+ (senator-completion-menu-point-as-event)
+ "Completions")))
+ (when ans
+ (if (not (semantic-tag-p ans))
+ (setq ans (aref (cdr ans) 0)))
+ (delete-region (car (oref a bounds)) (cdr (oref a bounds)))
+ (semantic-ia-insert-tag ans))
+ ))))
+
;;; Completions Tip
;;
;; This functions shows how to get the list of completions,
(require 'semantic/format)
(require 'semantic/tag)
(require 'timer)
+;;(require 'working)
;; For the semantic-find-tags-by-name macro.
(eval-when-compile (require 'semantic/find))
"Return non-nil if idle-scheduler is enabled for this buffer.
idle-scheduler is disabled when debugging or if the buffer size
exceeds the `semantic-idle-scheduler-max-buffer-size' threshold."
- (and semantic-idle-scheduler-mode
- (not (and (boundp 'semantic-debug-enabled)
- semantic-debug-enabled))
- (not semantic-lex-debug)
- (or (<= semantic-idle-scheduler-max-buffer-size 0)
- (< (buffer-size) semantic-idle-scheduler-max-buffer-size))))
+ (let* ((remote-file? (when (stringp buffer-file-name) (file-remote-p buffer-file-name))))
+ (and semantic-idle-scheduler-mode
+ (not (and (boundp 'semantic-debug-enabled)
+ semantic-debug-enabled))
+ (not semantic-lex-debug)
+ ;; local file should exist on disk
+ ;; remote file should have active connection
+ (or (and (null remote-file?) (stringp buffer-file-name)
+ (file-exists-p buffer-file-name))
+ (and remote-file? (file-remote-p buffer-file-name nil t)))
+ (or (<= semantic-idle-scheduler-max-buffer-size 0)
+ (< (buffer-size) semantic-idle-scheduler-max-buffer-size)))))
;;;###autoload
(define-minor-mode semantic-idle-scheduler-mode
semantic tag information has been updated.
This routine creates the following functions and variables:"
(let ((global (intern (concat "global-" (symbol-name name) "-mode")))
- (mode (intern (concat (symbol-name name) "-mode")))
- (hook (intern (concat (symbol-name name) "-mode-hook")))
- (map (intern (concat (symbol-name name) "-mode-map")))
- (func (intern (concat (symbol-name name) "-idle-function"))))
+ (mode (intern (concat (symbol-name name) "-mode")))
+ (hook (intern (concat (symbol-name name) "-mode-hook")))
+ (map (intern (concat (symbol-name name) "-mode-map")))
+ (setup (intern (concat (symbol-name name) "-mode-setup")))
+ (func (intern (concat (symbol-name name) "-idle-function"))))
`(eval-and-compile
(define-minor-mode ,global
(symbol-name mode) "'.")
,@forms))))
(put 'define-semantic-idle-service 'lisp-indent-function 1)
-
+(add-hook 'edebug-setup-hook
+ (lambda ()
+ (def-edebug-spec define-semantic-idle-service
+ (&define name stringp def-body))))
\f
;;; SUMMARY MODE
;;
;; We use pulse, but we don't want the flashy version,
;; just the stable version.
(pulse-flag nil))
- (when ctxt
+ (when (and ctxt tag)
;; Highlight the original tag? Protect against problems.
(condition-case nil
(semantic-idle-symbol-maybe-highlight target)
"Calculate and display a list of completions."
(when (and (semantic-idle-summary-useful-context-p)
(semantic-idle-completions-end-of-symbol-p))
- ;; This mode can be fragile. Ignore problems.
- ;; If something doesn't do what you expect, run
- ;; the below command by hand instead.
- (condition-case nil
+ ;; This mode can be fragile, hence don't raise errors, and only
+ ;; report problems if semantic-idle-scheduler-verbose-flag is
+ ;; non-nil. If something doesn't do what you expect, run the
+ ;; below command by hand instead.
+ (condition-case err
(semanticdb-without-unloaded-file-searches
;; Use idle version.
(semantic-complete-analyze-inline-idle)
)
- (error nil))
+ (error
+ (when semantic-idle-scheduler-verbose-flag
+ (message " %s" (error-message-string err)))))
))
(define-semantic-idle-service semantic-idle-completions
;; :active t
;; :style 'toggle
;; :selected '(let ((tag (semantic-current-tag)))
- ;; (and tag (semantic-tag-folded-p tag)))
+ ;; (and tag (semantic-tag-folded-p tag)))
;; :help "Fold the current tag to one line"))
"---"
(semantic-menu-item
;; Format TAG-LIST and put the formatted string into the header
;; line.
(setq header-line-format
- (concat
- semantic-idle-breadcrumbs-header-line-prefix
- (if tag-list
- (semantic-idle-breadcrumbs--format-tag-list
- tag-list
- (- width
- (length semantic-idle-breadcrumbs-header-line-prefix)))
- (propertize
- "<not on tags>"
- 'face
- 'font-lock-comment-face)))))
+ (replace-regexp-in-string ;; Since % is interpreted in the
+ "\\(%\\)" "%\\1" ;; mode/header line format, we
+ (concat ;; have to escape all occurrences.
+ semantic-idle-breadcrumbs-header-line-prefix
+ (if tag-list
+ (semantic-idle-breadcrumbs--format-tag-list
+ tag-list
+ (- width
+ (length semantic-idle-breadcrumbs-header-line-prefix)))
+ (propertize
+ "<not on tags>"
+ 'face
+ 'font-lock-comment-face))))))
;; Update the header line.
(force-mode-line-update))
(let ((width (- (nth 2 (window-edges))
(nth 0 (window-edges)))))
(setq mode-line-format
- (semantic-idle-breadcrumbs--format-tag-list tag-list width)))
+ (replace-regexp-in-string ;; see comment in
+ "\\(%\\)" "%\\1" ;; `semantic-idle-breadcrumbs--display-in-header-line'
+ (semantic-idle-breadcrumbs--format-tag-list tag-list width))))
(force-mode-line-update))
(setq clone (semantic-tag-clone tag (car dim))
xpand (cons clone xpand))
(semantic-tag-put-attribute clone :dereference (cdr dim)))
+
((eq class 'variable)
(or (consp elts) (setq elts (list (list elts))))
(setq dim (semantic-java-dim (semantic-tag-get-attribute tag :type))
(semantic-tag-put-attribute clone :type type)
(semantic-tag-put-attribute clone :dereference (+ dim0 (cdr dim)))
(semantic-tag-set-bounds clone start end)))
- )
+
+ ((and (eq class 'type) (string-match "\\." (semantic-tag-name tag)))
+ ;; javap outputs files where the package name is stuck onto the class or interface
+ ;; name. To make this more regular, we extract the package name into a package statement,
+ ;; then make the class name regular.
+ (let* ((name (semantic-tag-name tag))
+ (rsplit (nreverse (split-string name "\\." t)))
+ (newclassname (car rsplit))
+ (newpkg (mapconcat 'identity (reverse (cdr rsplit)) ".")))
+ (semantic-tag-set-name tag newclassname)
+ (setq xpand
+ (list tag
+ (semantic-tag-new-package newpkg nil))))
+ ))
xpand))
\f
;;; Environment
(semantic-find-tags-by-class
'type (semantic-find-tag-by-overlay point))))
+;; Tag Protection
+;;
+(define-mode-local-override semantic-tag-protection
+ java-mode (tag &optional parent)
+ "Return the protection of TAG in PARENT.
+Override function for `semantic-tag-protection'."
+ (let ((prot (semantic-tag-protection-default tag parent)))
+ (or prot 'package)))
+
;; Prototype handler
;;
(defun semantic-java-prototype-function (tag &optional parent color)
(let ((name (semantic-tag-name tag)))
(concat (mapconcat 'identity (split-string name "\\.") "/") ".java")))
-
;; Documentation handler
;;
(defsubst semantic-java-skip-spaces-backward ()
;; (symbol "name" 569 . 573)
;; (semantic-list "(int in)" 574 . 582))
;;
- ;; In the second case, a macro with an argument list as the a rgs as the
+ ;; In the second case, a macro with an argument list as the args as the
;; first entry.
;;
;; CASE 3: Symbol text merge
(cond
;; CASE 3: Merge symbols together.
((eq (semantic-lex-token-class v) 'spp-symbol-merge)
- ;; We need to merge the tokens in the 'text segment together,
- ;; and produce a single symbol from it.
- (let ((newsym
- (mapconcat (lambda (tok)
- (semantic-lex-spp-one-token-to-txt tok))
- txt
- "")))
+ (let ((newsym (semantic-lex-spp-symbol-merge txt)))
(semantic-lex-push-token
(semantic-lex-token 'symbol beg end newsym))
))
(semantic-lex-spp-symbol-pop A))
))
+(defun semantic-lex-spp-symbol-merge (txt)
+ "Merge the tokens listed in TXT.
+TXT might contain further 'spp-symbol-merge, which will
+be merged recursively."
+ ;; We need to merge the tokens in the 'text segment together,
+ ;; and produce a single symbol from it.
+ (mapconcat (lambda (tok)
+ (cond
+ ((eq (car tok) 'symbol)
+ (semantic-lex-spp-one-token-to-txt tok))
+ ((eq (car tok) 'spp-symbol-merge)
+ ;; Call recursively for multiple merges, like
+ ;; #define FOO(a) foo##a##bar
+ (semantic-lex-spp-symbol-merge (cadr tok)))
+ (t
+ (message "Invalid merge macro ecountered; \
+will return empty string instead.")
+ "")))
+ txt
+ ""))
+
;;; Macro Merging
;;
;; Used when token streams from different macros include each other.
(forward-char 1)
(setq fresh-toks (semantic-lex-spp-stream-for-macro (1- end)))
(dolist (tok fresh-toks)
- (when (memq (semantic-lex-token-class tok) '(symbol semantic-list))
+ ;; march 2011: This is too restrictive! For example "void"
+ ;; can't get through. What elements was I trying to expunge
+ ;; to put this in here in the first place? If I comment it
+ ;; out, does anything new break?
+ ;(when (memq (semantic-lex-token-class tok) '(symbol semantic-list))
+ ;; It appears the commas need to be dumped. perhaps this is better,
+ ;; but will it cause more problems later?
+ (unless (eq (semantic-lex-token-class tok) 'punctuation)
(setq toks (cons tok toks))))
(nreverse toks)))))
(fresh-toks nil)
(toks nil)
(origbuff (current-buffer))
+ (analyzer semantic-lex-analyzer)
(important-vars '(semantic-lex-spp-macro-symbol-obarray
semantic-lex-spp-project-macro-symbol-obarray
semantic-lex-spp-dynamic-macro-symbol-obarray
;; Hack in mode-local
(activate-mode-local-bindings)
+ ;; Call the major mode's setup function
+ (let ((entry (assq major-mode semantic-new-buffer-setup-functions)))
+ (when entry
+ (funcall (cdr entry))))
+
;; CHEATER! The following 3 lines are from
;; `semantic-new-buffer-fcn', but we don't want to turn
;; on all the other annoying modes for this little task.
(semantic-overlay-put o 'face 'highlight)
o))
-(defsubst semantic-lex-debug-break (token)
- "Break during lexical analysis at TOKEN."
- (when semantic-lex-debug
- (let ((o nil))
- (unwind-protect
- (progn
- (when token
- (setq o (semantic-lex-highlight-token token)))
- (semantic-read-event
- (format "%S :: SPC - continue" token))
- )
- (when o
- (semantic-overlay-delete o))))))
-
;;; Lexical analyzer creation
;;
;; Code for creating a lex function from lists of analyzers.
;;(defvar semantic-lex-timeout 5
;; "*Number of sections of lexing before giving up.")
+(defsubst semantic-lex-debug-break (token)
+ "Break during lexical analysis at TOKEN."
+ (when semantic-lex-debug
+ (let ((o nil))
+ (unwind-protect
+ (progn
+ (when token
+ (setq o (semantic-lex-highlight-token token)))
+ (semantic-read-event
+ (format "%S :: Depth: %d :: SPC - continue" token semantic-lex-current-depth))
+ )
+ (when o
+ (semantic-overlay-delete o))))))
+
(defmacro define-lex (name doc &rest analyzers)
"Create a new lexical analyzer with NAME.
DOC is a documentation string describing this analyzer.
))
))
((setq match (assoc text ',clist))
- (setq semantic-lex-current-depth (1- semantic-lex-current-depth))
- (semantic-lex-push-token
- (semantic-lex-token
- (nth 1 match)
- (match-beginning 0) (match-end 0)))))))
+ (if (> semantic-lex-current-depth 0)
+ (progn
+ (setq semantic-lex-current-depth (1- semantic-lex-current-depth))
+ (semantic-lex-push-token
+ (semantic-lex-token
+ (nth 1 match)
+ (match-beginning 0) (match-end 0)))))))))
)))
\f
;;; Analyzers
(declare-function data-debug-new-buffer "data-debug")
(declare-function data-debug-insert-object-slots "eieio-datadebug")
(declare-function semantic-momentary-highlight-tag "semantic/decorate")
+(declare-function semantic-tag-similar-p "semantic/tag-ls")
;;; TRACKING CORE
;;
(declare-function semantic-analyze-princ-sequence "semantic/analyze")
(declare-function semanticdb-typecache-merge-streams "semantic/db-typecache")
(declare-function semanticdb-typecache-add-dependant "semantic/db-typecache")
+(declare-function semantic-tag-similar-p "semantic/tag-ls")
;;; Code:
;; tag can be passed in and a scope derived from it.
(defun semantic-scope-tag-clone-with-scope (tag scopetags)
- "Close TAG, and return it. Add SCOPETAGS as a tag-local scope.
+ "Clone TAG, and return it. Add SCOPETAGS as a tag-local scope.
Stores the SCOPETAGS as a set of tag properties on the cloned tag."
(let ((clone (semantic-tag-clone tag))
)
(semanticdb-typecache-find (car sp)))
;(semantic-analyze-find-tag (car sp) 'type))
((semantic-tag-p (car sp))
- (if (semantic-analyze-tag-prototype-p (car sp))
+ (if (semantic-tag-prototype-p (car sp))
(semanticdb-typecache-find (semantic-tag-name (car sp)))
;;(semantic-analyze-find-tag (semantic-tag-name (car sp)) 'type)
(car sp)))
(setq stack (reverse stack))
;; Add things to STACK until we cease finding tags of class type.
(while (and stack (eq (semantic-tag-class (car stack)) 'type))
- ;; Otherwise, just add this to the returnlist.
- (setq returnlist (cons (car stack) returnlist))
- (setq stack (cdr stack)))
+ ;; Otherwise, just add this to the returnlist, but make
+ ;; sure we didn't already have that tag in scopetypes
+ (unless (member (car stack) scopetypes)
+ (setq returnlist (cons (car stack) returnlist)))
+ (setq stack (cdr stack)))
(setq returnlist (nreverse returnlist))
))
;;;###autoload
(defun semantic-symref-find-tags-by-name (name &optional scope)
- "Find a list of references to NAME in the current project.
+ "Find a list of tags by NAME in the current project.
Optional SCOPE specifies which file set to search. Defaults to 'project.
Refers to `semantic-symref-tool', to determine the reference tool to use
for the current buffer.
(forward-line (1- line))
;; Search forward for the matching text
- (re-search-forward (regexp-quote txt)
- (point-at-eol)
- t)
+ (when (re-search-forward (regexp-quote txt)
+ (point-at-eol)
+ t)
+ (goto-char (match-beginning 0))
+ )
(setq tag (semantic-current-tag))
(funcall hookfcn start end prefix)))))
(point)))))))
+(defun semantic-symref-test-count-hits-in-tag ()
+ "Lookup in the current tag the symbol under point.
+the count all the other references to the same symbol within the
+tag that contains point, and return that."
+ (interactive)
+ (let* ((ctxt (semantic-analyze-current-context))
+ (target (car (reverse (oref ctxt prefix))))
+ (tag (semantic-current-tag))
+ (start (current-time))
+ (Lcount 0))
+ (when (semantic-tag-p target)
+ (semantic-symref-hits-in-region
+ target (lambda (start end prefix) (setq Lcount (1+ Lcount)))
+ (semantic-tag-start tag)
+ (semantic-tag-end tag))
+ (when (called-interactively-p 'interactive)
+ (message "Found %d occurances of %s in %.2f seconds"
+ Lcount (semantic-tag-name target)
+ (semantic-elapsed-time start (current-time))))
+ Lcount)))
+
(defun semantic-symref-rename-local-variable ()
"Fancy way to rename the local variable under point.
Depends on the SRecode Field editing API."
(defvar semantic-symref-results-mode-map
(let ((km (make-sparse-keymap)))
+ (suppress-keymap km)
(define-key km "\C-i" 'forward-button)
(define-key km "\M-C-i" 'backward-button)
(define-key km " " 'push-button)
;; the information.
(require 'semantic)
+(require 'semantic/find)
;;; Code:
+;;; TAG SIMILARITY:
+;;
+;; Two tags that represent the same thing are "similar", but not the "same".
+;; Similar tags might have the same name, but one is a :prototype, while
+;; the other is an implementation.
+;;
+;; Each language will have different things that can be ignored
+;; between two "similar" tags, so similarity checks involve a series
+;; of mode overridable features. Some are "internal" features.
+(defvar semantic-tag-similar-ignorable-attributes '(:prototype-flag)
+ "The tag attributes that can be ignored during a similarity test.")
+
+(define-overloadable-function semantic--tag-similar-names-p (tag1 tag2 blankok)
+ "Compare the names of TAG1 and TAG2.
+If BLANKOK is false, then the names must exactly match.
+If BLANKOK is true, then if either of TAG1 or TAG2 has blank
+names, then that is ok, and this returns true, but if they both
+have values, they must still match.")
+
+(defun semantic--tag-similar-names-p-default (tag1 tag2 blankok)
+ "Compare the names of TAG1 and TAG2.
+If BLANKOK is false, then the names must exactly match.
+If BLANKOK is true, then if either of TAG1 or TAG2 has blank
+names, then that is ok, and this returns true, but if they both
+have values, they must still match."
+ (let ((n1 (semantic-tag-name tag1))
+ (n2 (semantic-tag-name tag2)))
+ (or (and blankok (or (null n1) (null n2) (string= n1 "") (string= n2 "")))
+ (string= n1 n2))))
+
+(define-overloadable-function semantic--tag-similar-types-p (tag1 tag2)
+ "Compare the types of TAG1 and TAG2.
+This functions can be overriden, for example to compare a fully
+qualified with an unqualified type."
+ (cond
+ ((and (null (semantic-tag-type tag1))
+ (null (semantic-tag-type tag2)))
+ t)
+ ((or (null (semantic-tag-type tag1))
+ (null (semantic-tag-type tag2)))
+ nil)
+ (t
+ (:override))))
+
+(defun semantic--tag-similar-types-p-default (tag1 tag2)
+ "Compare the types of TAG1 and TAG2.
+This functions can be overriden, for example to compare a fully
+qualified with an unqualified type."
+ (semantic-tag-of-type-p tag1 (semantic-tag-type tag2)))
+
+(define-overloadable-function semantic--tag-attribute-similar-p (attr value1 value2 ignorable-attributes)
+ "Test to see if attribute ATTR is similar for VALUE1 and VALUE2.
+IGNORABLE-ATTRIBUTES is described in `semantic-tag-similar-p'.
+This function is internal, but allows customization of `semantic-tag-similar-p'
+for a given mode at a more granular level.
+
+Note that :type, :name, and anything in IGNORABLE-ATTRIBUTES will
+not be passed to this function.
+
+Modes that override this function can call `semantic--tag-attribute-similar-p-default'
+to do the default equality tests if ATTR is not special for that mode.")
+
+(defun semantic--tag-attribute-similar-p-default (attr value1 value2 ignorable-attributes)
+ "For ATTR, VALUE1, VALUE2 and IGNORABLE-ATTRIBUTES, test for similarness."
+ (cond
+ ;; Tag sublists require special testing.
+ ((and (listp value1) (semantic-tag-p (car value1))
+ (listp value2) (semantic-tag-p (car value2)))
+ (let ((ans t)
+ (taglist1 value1)
+ (taglist2 value2))
+ (when (not (eq (length taglist1) (length taglist2)))
+ (setq ans nil))
+ (while (and ans taglist1 taglist2)
+ (setq ans (apply 'semantic-tag-similar-p
+ (car taglist1) (car taglist2)
+ ignorable-attributes)
+ taglist1 (cdr taglist1)
+ taglist2 (cdr taglist2)))
+ ans))
+
+ ;; The attributes are not the same?
+ ((not (equal value1 value2))
+ nil)
+
+ (t t))
+ )
+
+(define-overloadable-function semantic-tag-similar-p (tag1 tag2 &rest ignorable-attributes)
+ "Test to see if TAG1 and TAG2 are similar.
+Two tags are similar if their name, datatype, and various attributes
+are the same.
+
+Similar tags that have sub-tags such as arg lists or type members,
+are similar w/out checking the sub-list of tags.
+Optional argument IGNORABLE-ATTRIBUTES are attributes to ignore while comparing similarity.
+By default, `semantic-tag-similar-ignorable-attributes' is referenced for
+attributes, and IGNOREABLE-ATTRIBUTES will augment this list.
+
+Note that even though :name is not an attribute, it can be used to
+to indicate lax comparison of names via `semantic--tag-similar-names-p'")
+
+;; Note: optional thing is because overloadable fcns don't handle this
+;; quite right.
+(defun semantic-tag-similar-p-default (tag1 tag2 &optional ignorable-attributes)
+ "Test to see if TAG1 and TAG2 are similar.
+Two tags are similar if their name, datatype, and various attributes
+are the same.
+
+IGNORABLE-ATTRIBUTES are tag attributes that can be ignored.
+
+See `semantic-tag-similar-p' for details."
+ (let* ((ignore (append ignorable-attributes semantic-tag-similar-ignorable-attributes))
+ (A1 (and (semantic--tag-similar-names-p tag1 tag2 (memq :name ignore))
+ (semantic--tag-similar-types-p tag1 tag2)
+ (semantic-tag-of-class-p tag1 (semantic-tag-class tag2))))
+ (attr1 (semantic-tag-attributes tag1))
+ (attr2 (semantic-tag-attributes tag2))
+ (A2 t)
+ (A3 t)
+ )
+ ;; Test if there are non-ignorable attributes in A2 which are not present in A1
+ (while (and A2 attr2)
+ (let ((a (car attr2)))
+ (unless (or (eq a :type) (memq a ignore))
+ (setq A2 (semantic-tag-get-attribute tag1 a)))
+ (setq attr2 (cdr (cdr attr2)))))
+ (while (and A2 attr1 A3)
+ (let ((a (car attr1)))
+
+ (cond ((or (eq a :type) ;; already tested above.
+ (memq a ignore)) ;; Ignore them...
+ nil)
+
+ (t
+ (setq A3
+ (semantic--tag-attribute-similar-p
+ a (car (cdr attr1)) (semantic-tag-get-attribute tag2 a)
+ ignorable-attributes)))
+ ))
+ (setq attr1 (cdr (cdr attr1))))
+ (and A1 A2 A3)))
+
+;;; FULL NAMES
+;;
+;; For programmer convenience, a full name is not specified in source
+;; code. Instead some abbreviation is made, and the local environment
+;; will contain the info needed to determine the full name.
+(define-overloadable-function semantic-tag-full-package (tag &optional stream-or-buffer)
+ "Return the fully qualified package name of TAG in a package hierarchy.
+STREAM-OR-BUFFER can be anything convertible by `semantic-something-to-stream',
+but must be a toplevel semantic tag stream that contains TAG.
+A Package Hierarchy is defined in UML by the way classes and methods
+are organized on disk. Some languages use this concept such that a
+class can be accessed via it's fully qualified name, (such as Java.)
+Other languages qualify names within a Namespace (such as C++) which
+result in a different package like structure.
+
+Languages which do not override this function will just search the
+stream for a tag of class 'package, and return that."
+ (let ((stream (semantic-something-to-tag-table
+ (or stream-or-buffer tag))))
+ (:override-with-args (tag stream))))
+
+(defun semantic-tag-full-package-default (tag stream)
+ "Default method for `semantic-tag-full-package' for TAG.
+Return the name of the first tag of class `package' in STREAM."
+ (let ((pack (car-safe (semantic-find-tags-by-class 'package stream))))
+ (when (and pack (semantic-tag-p pack))
+ (semantic-tag-name pack))))
+
+(define-overloadable-function semantic-tag-full-name (tag &optional stream-or-buffer)
+ "Return the fully qualified name of TAG in the package hierarchy.
+STREAM-OR-BUFFER can be anything convertable by `semantic-something-to-stream',
+but must be a toplevel semantic tag stream that contains TAG.
+A Package Hierarchy is defined in UML by the way classes and methods
+are organized on disk. Some languages use this concept such that a
+class can be accessed via it's fully qualified name, (such as Java.)
+Other languages qualify names within a Namespace (such as C++) which
+result in a different package like structure.
+
+Languages which do not override this function with
+`tag-full-name' will combine `semantic-tag-full-package' and
+`semantic-tag-name', separated with language separator character.
+Override functions only need to handle STREAM-OR-BUFFER with a
+tag stream value, or nil.
+
+TODO - this function should probably also take a PARENT to TAG to
+resolve issues where a method in a class in a package is present."
+ (let ((stream (semantic-something-to-tag-table
+ (or stream-or-buffer tag))))
+ (:override-with-args (tag stream))))
+
+(make-obsolete-overload 'semantic-nonterminal-full-name
+ 'semantic-tag-full-name "23.2")
+
+(defun semantic-tag-full-name-default (tag stream)
+ "Default method for `semantic-tag-full-name'.
+Return the name of TAG found in the toplevel STREAM."
+ (let ((pack (semantic-tag-full-package tag stream))
+ (name (semantic-tag-name tag)))
+ (if pack
+ (concat pack
+ (car semantic-type-relation-separator-character)
+ name)
+ name)))
+
;;; UML features:
;;
;; UML can represent several types of features of a tag
((string= s "private")
'private)
((string= s "protected")
- 'protected)))))
+ 'protected)
+ ((string= s "package")
+ 'package)
+ ))))
(setq mods (cdr mods)))
prot))
+(defun semantic-tag-package-protected-p (tag &optional parent currentpackage)
+ "Non-nil if TAG is not available via package access control.
+For languages (such as Java) where a method is package protected,
+this method will return nil if TAG, as found in PARENT is available
+for access from a file in CURRENTPACKAGE.
+If TAG is not protected by PACKAGE, also return t. Use
+`semantic-tag-protected-p' instead.
+If PARENT is not provided, it will be derived when passed to
+`semantic-tag-protection'.
+If CURRENTPACKAGE is not provided, it will be derived from the current
+buffer."
+ (let ((tagpro (semantic-tag-protection tag parent)))
+ (if (not (eq tagpro 'package))
+ t ;; protected
+
+ ;; package protection, so check currentpackage.
+ ;; Deriving the package is better from the parent, as TAG is
+ ;; probably a field or method.
+ (if (not currentpackage)
+ (setq currentpackage (semantic-tag-full-package nil (current-buffer))))
+ (let ((tagpack (semantic-tag-full-package (or parent tag))))
+ (if (string= currentpackage tagpack)
+ nil
+ t)) )))
+
(defun semantic-tag-protected-p (tag protection &optional parent)
"Non-nil if TAG is protected.
PROTECTION is a symbol which can be returned by the method
(t nil))
))
-;;; FULL NAMES
-;;
-;; For programmer convenience, a full name is not specified in source
-;; code. Instead some abbreviation is made, and the local environment
-;; will contain the info needed to determine the full name.
-
-(define-overloadable-function semantic-tag-full-name (tag &optional stream-or-buffer)
- "Return the fully qualified name of TAG in the package hierarchy.
-STREAM-OR-BUFFER can be anything convertible by `semantic-something-to-stream',
-but must be a toplevel semantic tag stream that contains TAG.
-A Package Hierarchy is defined in UML by the way classes and methods
-are organized on disk. Some language use this concept such that a
-class can be accessed via it's fully qualified name, (such as Java.)
-Other languages qualify names within a Namespace (such as C++) which
-result in a different package like structure. Languages which do not
-override this function with `tag-full-name' will use
-`semantic-tag-name'. Override functions only need to handle
-STREAM-OR-BUFFER with a tag stream value, or nil."
- (let ((stream (semantic-something-to-tag-table
- (or stream-or-buffer tag))))
- (:override-with-args (tag stream))))
-
-(make-obsolete-overload 'semantic-nonterminal-full-name
- 'semantic-tag-full-name "23.2")
-
-(defun semantic-tag-full-name-default (tag stream)
- "Default method for `semantic-tag-full-name'.
-Return the name of TAG found in the toplevel STREAM."
- (semantic-tag-name tag))
-
(provide 'semantic/tag-ls)
;; Local variables:
(signal 'wrong-type-argument (list tag 'semantic-tag-p)))
(when (not indent) (setq indent 0))
;(princ (make-string indent ? ))
- (princ "(\"")
+ (princ "(")
;; Base parts
(let ((name (semantic-tag-name tag))
(class (semantic-tag-class tag)))
- (princ name)
- (princ "\" ")
+ (prin1 name)
+ (princ " ")
(princ (symbol-name class))
)
(let ((attr (semantic-tag-attributes tag))
(declare-function semantic-analyze-split-name "semantic/analyze/fcn")
(declare-function semantic-fetch-tags "semantic")
(declare-function semantic-clear-toplevel-cache "semantic")
+(declare-function semantic-tag-similar-p "semantic/tag-ls")
(defconst semantic-tag-version "2.0"
"Version string of semantic tags made with this code.")
(equal (semantic-tag-bounds tag1)
(semantic-tag-bounds tag2))))))
-(defun semantic-tag-similar-p (tag1 tag2 &rest ignorable-attributes)
- "Test to see if TAG1 and TAG2 are similar.
-Two tags are similar if their name, datatype, and various attributes
-are the same.
-
-Similar tags that have sub-tags such as arg lists or type members,
-are similar w/out checking the sub-list of tags.
-Optional argument IGNORABLE-ATTRIBUTES are attributes to ignore while comparing similarity."
- (let* ((A1 (and (equal (semantic-tag-name tag1) (semantic-tag-name tag2))
- (semantic-tag-of-class-p tag1 (semantic-tag-class tag2))
- (semantic-tag-of-type-p tag1 (semantic-tag-type tag2))))
- (attr1 (semantic-tag-attributes tag1))
- (A2 (= (length attr1) (length (semantic-tag-attributes tag2))))
- (A3 t)
- )
- (when (and (not A2) ignorable-attributes)
- (setq A2 t))
- (while (and A2 attr1 A3)
- (let ((a (car attr1))
- (v (car (cdr attr1))))
-
- (cond ((or (eq a :type) ;; already tested above.
- (memq a ignorable-attributes)) ;; Ignore them...
- nil)
-
- ;; Don't test sublists of tags
- ((and (listp v) (semantic-tag-p (car v)))
- nil)
-
- ;; The attributes are not the same?
- ((not (equal v (semantic-tag-get-attribute tag2 a)))
- (setq A3 nil))
- (t
- nil))
- )
- (setq attr1 (cdr (cdr attr1))))
-
- (and A1 A2 A3)
- ))
(defun semantic-tag-similar-with-subtags-p (tag1 tag2 &rest ignorable-attributes)
"Test to see if TAG1 and TAG2 are similar.
as argument lists and type members.
Optional argument IGNORABLE-ATTRIBUTES is passed down to
`semantic-tag-similar-p'."
- (let ((C1 (semantic-tag-components tag1))
- (C2 (semantic-tag-components tag2))
- )
- (if (or (/= (length C1) (length C2))
- (not (semantic-tag-similar-p tag1 tag2 ignorable-attributes))
- )
- ;; Basic test fails.
- nil
- ;; Else, check component lists.
- (catch 'component-dissimilar
- (while C1
-
- (if (not (semantic-tag-similar-with-subtags-p
- (car C1) (car C2) ignorable-attributes))
- (throw 'component-dissimilar nil))
-
- (setq C1 (cdr C1))
- (setq C2 (cdr C2))
- )
- ;; If we made it this far, we are ok.
- t) )))
-
+ ;; DEPRECATE THIS.
+ (semantic-tag-similar-p tag1 tag2 ignorable-attributes))
(defun semantic-tag-of-type-p (tag type)
"Compare TAG's type against TYPE. Non nil if equivalent.
"Set TAG name to NAME."
(setcar tag name))
+;;; TAG Proxys
+;;
+;; A new kind of tag is a TAG PROXY. These are tags that have some
+;; minimal number of features set, such as name and class, but have a
+;; marker in them that indicates how to complete them.
+;;
+;; To make the tags easier to view, the proxy is stored as custom
+;; symbol that is not in the global obarray, but has properties set on
+;; it. This prevents saving of massive amounts of proxy data.
+(defun semantic-create-tag-proxy (function data)
+ "Create a tag proxy symbol.
+FUNCTION will be used to resolve the proxy. It should take 3
+two arguments, DATA and TAG. TAG is a proxy tag that needs
+to be resolved, and DATA is the DATA passed into this function.
+DATA is data to help resolve the proxy. DATA can be an EIEIO object,
+such that FUNCTION is a method.
+FUNCTION should return a list of tags, preferrably one tag."
+ (let ((sym (make-symbol ":tag-proxy")))
+ (put sym 'proxy-function function)
+ (put sym 'proxy-data data)
+ sym))
+
+(defun semantic-tag-set-proxy (tag proxy &optional filename)
+ "Set TAG to be a proxy. The proxy can be resolved with PROXY.
+This function will also make TAG be a faux tag with
+`semantic-tag-set-faux', and possibly set the tag's
+:filename with FILENAME.
+To create a proxy, see `semantic-create-tag-proxy'."
+ (semantic-tag-set-faux tag)
+ (semantic--tag-put-property tag :proxy proxy)
+ (when filename
+ (semantic--tag-put-property tag :filename filename)))
+
+(defun semantic-tag-resolve-proxy (tag)
+ "Resolve the proxy in TAG.
+The return value is whatever format the proxy was setup as.
+It should be a list of complete tags.
+If TAG has no proxy, then just return tag."
+ (let* ((proxy (semantic--tag-get-property tag :proxy))
+ (function (get proxy 'proxy-function))
+ (data (get proxy 'proxy-data)))
+ (if proxy
+ (funcall function data tag)
+ tag)))
+
;;; Copying and cloning tags.
;;
(defsubst semantic-tag-clone (tag &optional name)
interfaces, or abstract classes which are parents of TAG."
(cons (semantic-tag-get-attribute tag :superclasses)
(semantic-tag-type-interfaces tag)))
+
(make-obsolete 'semantic-token-type-parent
"\
use `semantic-tag-type-superclass' \
(defvar semantic-imenu-bucketize-file)
(defvar semantic-imenu-bucketize-type-members)
+;;;###autoload
(defun semantic-default-texi-setup ()
"Set up a buffer for parsing of Texinfo files."
;; This will use our parser.
(provide 'semantic/texi)
+;; Local variables:
+;; generated-autoload-file: "loaddefs.el"
+;; generated-autoload-load-name: "semantic/texi"
+;; End:
+
;;; semantic/texi.el ends here
semantic-dump-parse
semantic-type-relation-separator-character
semantic-command-separation-character
+ semantic-new-buffer-fcn-was-run
)))
(dolist (V vars)
(semantic-describe-buffer-var-helper V buff)))
;;;; ------------------------
(defconst wisent-BITS-PER-WORD
- (let ((i 1))
- (while (not (zerop (lsh 1 i)))
+ (let ((i 1)
+ (do-shift (if (boundp 'most-positive-fixnum)
+ (lambda (i) (lsh most-positive-fixnum (- i)))
+ (lambda (i) (lsh 1 i)))))
+ (while (not (zerop (funcall do-shift i)))
(setq i (1+ i)))
i))
(provide 'semantic/wisent/comp)
+;; Disable messages with regards to lexical scoping, since this will
+;; produce a bunch of 'lacks a prefix' warnings with the
+;; `wisent-defcontext' trickery above.
+
+;; Local variables:
+;; byte-compile-warnings: (not lexical)
+;; End:
+
;;; semantic/wisent/comp.el ends here
collect tags, such as local variables or prototypes.
This function override `get-local-variables'."
(let ((vars nil)
+ (ct (semantic-current-tag))
;; We want nothing to do with funny syntaxing while doing this.
(semantic-unmatched-syntax-hook nil))
(while (not (semantic-up-context (point) 'function))
'field_declaration
0 t)
vars))))
+ ;; Add 'this' if in a fcn
+ (when (semantic-tag-of-class-p ct 'function)
+ ;; Append a new tag THIS into our space.
+ (setq vars (cons (semantic-tag-new-variable
+ "this" (semantic-tag-name (semantic-current-tag-parent))
+ nil)
+ vars)))
vars))
+;;;
+;;; Analyzer and type cache support
+;;;
+(define-mode-local-override semantic-analyze-split-name java-mode (name)
+ "Split up tag names on colon . boundaries."
+ (let ((ans (split-string name "\\.")))
+ (if (= (length ans) 1)
+ name
+ (delete "" ans))))
+
+(define-mode-local-override semantic-analyze-unsplit-name java-mode (namelist)
+ "Assemble the list of names NAMELIST into a namespace name."
+ (mapconcat 'identity namelist "."))
+
+
+
;;;;
;;;; Semantic integration of the Java LALR parser
;;;;
(package . "Package")))
;; navigation inside 'type children
senator-step-at-tag-classes '(function variable)
+ ;; Remove 'recursive from the default semanticdb find throttle
+ ;; since java imports never recurse.
+ semanticdb-find-default-throttle
+ (remq 'recursive (default-value 'semanticdb-find-default-throttle))
)
;; Setup javadoc stuff
(semantic-java-doc-setup))
start (if elts (car (cddr elt)) (semantic-tag-start tag))
end (if xpand (cdr (cddr elt)) (semantic-tag-end tag))
xpand (cons clone xpand))
- ;; Set the definition of the cloned tag
- (semantic-tag-put-attribute clone :default-value value)
+ ;; Set the definition of the cloned tag
+ (semantic-tag-put-attribute clone :default-value value)
;; Set the bounds of the cloned tag with those of the name
;; element.
(semantic-tag-set-bounds clone start end))
;; Does javascript have identifiable local variables?
nil)
+(define-mode-local-override semantic-tag-protection javascript-mode (tag &optional parent)
+ "Return protection information about TAG with optional PARENT.
+This function returns on of the following symbols:
+ nil - No special protection. Language dependent.
+ 'public - Anyone can access this TAG.
+ 'private - Only methods in the local scope can access TAG.
+ 'protected - Like private for outside scopes, like public for child
+ classes.
+Some languages may choose to provide additional return symbols specific
+to themselves. Use of this function should allow for this.
+
+The default behavior (if not overridden with `tag-protection'
+is to return a symbol based on type modifiers."
+ nil)
+
+(define-mode-local-override semantic-analyze-scope-calculate-access javascript-mode (type scope)
+ "Calculate the access class for TYPE as defined by the current SCOPE.
+Access is related to the :parents in SCOPE. If type is a member of SCOPE
+then access would be 'private. If TYPE is inherited by a member of SCOPE,
+the access would be 'protected. Otherwise, access is 'public."
+ nil)
+(define-mode-local-override semantic-ctxt-current-symbol javascript-mode (&optional point)
+ "Return the current symbol the cursor is on at POINT in a list.
+This is a very simple implementation for Javascript symbols. It
+will at maximum do one split, so that the first part is seen as
+one type. For example: $('#sel').foo.bar will return (\"$('sel').foo\" \"bar\").
+This is currently needed for the mozrepl omniscient database."
+ (save-excursion
+ (if point (goto-char point))
+ (let* ((case-fold-search semantic-case-fold)
+ symlist tmp end)
+ (with-syntax-table semantic-lex-syntax-table
+ (save-excursion
+ (when (looking-at "\\w\\|\\s_")
+ (forward-sexp 1))
+ (setq end (point))
+ (unless (re-search-backward "\\s-" (point-at-bol) t)
+ (beginning-of-line))
+ (setq tmp (buffer-substring-no-properties (point) end))
+ (if (string-match "\\(.+\\)\\." tmp)
+ (setq symlist (list (match-string 1 tmp)
+ (substring tmp (1+ (match-end 1)) (length tmp))))
+ (setq symlist (list tmp))))))))
+
;;; Setup Function
;;
-;; This sets up the javascript parser
+;; Since javascript-mode is an alias for js-mode, let it inherit all
+;; the overrides.
+(define-child-mode js-mode javascript-mode)
;; Since javascript-mode is an alias for js-mode, let it inherit all
;; the overrides.
;;; Code:
(require 'semantic/lex)
+(eval-when-compile (require 'semantic/bovine))
\f
;;; Prologue
;;
\f
;;; Analyzers
+;;
+(define-lex-block-type-analyzer wisent-javascript-jv-wy--<block>-block-analyzer
+ "block analyzer for <block> tokens."
+ "\\s(\\|\\s)"
+ '((("(" OPEN_PARENTHESIS PAREN_BLOCK)
+ ("{" START_BLOCK BRACE_BLOCK)
+ ("[" OPEN_SQ_BRACKETS BRACK_BLOCK))
+ (")" CLOSE_PARENTHESIS)
+ ("}" END_BLOCK)
+ ("]" CLOSE_SQ_BRACKETS))
+ )
+
+(define-lex-regex-type-analyzer wisent-javascript-jv-wy--<symbol>-regexp-analyzer
+ "regexp analyzer for <symbol> tokens."
+ "\\(\\sw\\|\\s_\\)+"
+ nil
+ 'VARIABLE)
+
+(define-lex-regex-type-analyzer wisent-javascript-jv-wy--<number>-regexp-analyzer
+ "regexp analyzer for <number> tokens."
+ semantic-lex-number-expression
+ nil
+ 'NUMBER)
(define-lex-string-type-analyzer wisent-javascript-jv-wy--<punctuation>-string-analyzer
"string analyzer for <punctuation> tokens."
(ASSIGN_SYMBOL . "="))
'punctuation)
-(define-lex-block-type-analyzer wisent-javascript-jv-wy--<block>-block-analyzer
- "block analyzer for <block> tokens."
- "\\s(\\|\\s)"
- '((("(" OPEN_PARENTHESIS PAREN_BLOCK)
- ("{" START_BLOCK BRACE_BLOCK)
- ("[" OPEN_SQ_BRACKETS BRACK_BLOCK))
- (")" CLOSE_PARENTHESIS)
- ("}" END_BLOCK)
- ("]" CLOSE_SQ_BRACKETS))
- )
-
-(define-lex-regex-type-analyzer wisent-javascript-jv-wy--<symbol>-regexp-analyzer
- "regexp analyzer for <symbol> tokens."
- "\\(\\sw\\|\\s_\\)+"
- nil
- 'VARIABLE)
-
-(define-lex-regex-type-analyzer wisent-javascript-jv-wy--<number>-regexp-analyzer
- "regexp analyzer for <number> tokens."
- semantic-lex-number-expression
- nil
- 'NUMBER)
-
(define-lex-sexp-type-analyzer wisent-javascript-jv-wy--<string>-sexp-analyzer
"sexp analyzer for <string> tokens."
"\\s\""
;;; semantic/wisent/python-wy.el --- Generated parser support file
-;; Copyright (C) 2002-2004, 2007, 2010-2012 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2012 Free Software Foundation, Inc.
;; Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
;; 2009, 2010 Python Software Foundation; All Rights Reserved
;;; Code:
(require 'semantic/lex)
+(eval-when-compile (require 'semantic/bovine))
\f
;;; Prologue
;;
+(declare-function wisent-python-reconstitute-function-tag "semantic/wisent/python")
+(declare-function wisent-python-reconstitute-class-tag "semantic/wisent/python")
\f
;;; Declarations
;;
("return" . RETURN)
("try" . TRY)
("while" . WHILE)
+ ("with" . WITH)
("yield" . YIELD))
'(("yield" summary "Create a generator function")
+ ("with" summary "Start statement with an associated context object")
("while" summary "Start a 'while' loop")
("try" summary "Start of statements protected by exception handlers")
("return" summary "Return from a function")
("string"
(STRING_LITERAL))
("punctuation"
+ (AT . "@")
(BACKQUOTE . "`")
(ASSIGN . "=")
(COMMA . ",")
(eval-when-compile
(require 'semantic/wisent/comp))
(wisent-compile-grammar
- '((BACKSLASH NEWLINE INDENT DEDENT INDENT_BLOCK PAREN_BLOCK BRACE_BLOCK BRACK_BLOCK LPAREN RPAREN LBRACE RBRACE LBRACK RBRACK LTLTEQ GTGTEQ EXPEQ DIVDIVEQ DIVDIV LTLT GTGT EXPONENT EQ GE LE PLUSEQ MINUSEQ MULTEQ DIVEQ MODEQ AMPEQ OREQ HATEQ LTGT NE HAT LT GT AMP MULT DIV MOD PLUS MINUS PERIOD TILDE BAR COLON SEMICOLON COMMA ASSIGN BACKQUOTE STRING_LITERAL NUMBER_LITERAL NAME AND AS ASSERT BREAK CLASS CONTINUE DEF DEL ELIF ELSE EXCEPT EXEC FINALLY FOR FROM GLOBAL IF IMPORT IN IS LAMBDA NOT OR PASS PRINT RAISE RETURN TRY WHILE YIELD)
+ '((BACKSLASH NEWLINE INDENT DEDENT INDENT_BLOCK PAREN_BLOCK BRACE_BLOCK BRACK_BLOCK LPAREN RPAREN LBRACE RBRACE LBRACK RBRACK LTLTEQ GTGTEQ EXPEQ DIVDIVEQ DIVDIV LTLT GTGT EXPONENT EQ GE LE PLUSEQ MINUSEQ MULTEQ DIVEQ MODEQ AMPEQ OREQ HATEQ LTGT NE HAT LT GT AMP MULT DIV MOD PLUS MINUS PERIOD TILDE BAR COLON SEMICOLON COMMA ASSIGN BACKQUOTE AT STRING_LITERAL NUMBER_LITERAL NAME AND AS ASSERT BREAK CLASS CONTINUE DEF DEL ELIF ELSE EXCEPT EXEC FINALLY FOR FROM GLOBAL IF IMPORT IN IS LAMBDA NOT OR PASS PRINT RAISE RETURN TRY WHILE WITH YIELD)
nil
(goal
((NEWLINE))
(wisent-raw-tag
(semantic-tag-new-include $2 nil))))
(dotted_as_name_list
- ((dotted_as_name))
- ((dotted_as_name_list COMMA dotted_as_name)))
+ ((dotted_as_name_list COMMA dotted_as_name)
+ (cons $3 $1))
+ ((dotted_as_name)
+ (list $1)))
(star_or_import_as_name_list
((MULT)
nil)
((while_stmt))
((for_stmt))
((try_stmt))
+ ((with_stmt))
((funcdef))
((class_declaration)))
(if_stmt
(nil)
((test zero_or_one_comma_test)
nil))
+ (with_stmt
+ ((WITH test COLON suite)
+ (wisent-raw-tag
+ (semantic-tag-new-code $1 nil)))
+ ((WITH test with_var COLON suite)
+ (wisent-raw-tag
+ (semantic-tag-new-code $1 nil))))
+ (with_var
+ ((AS expr)
+ nil))
+ (decorator
+ ((AT dotted_name varargslist_opt NEWLINE)
+ (wisent-raw-tag
+ (semantic-tag-new-function $2 "decorator" $3))))
+ (decorators
+ ((decorator)
+ (list $1))
+ ((decorator decorators)
+ (cons $1 $2)))
(funcdef
((DEF NAME function_parameter_list COLON suite)
- (wisent-raw-tag
- (semantic-tag-new-function $2 nil $3))))
+ (wisent-python-reconstitute-function-tag
+ (wisent-raw-tag
+ (semantic-tag-new-function $2 nil $3))
+ $5))
+ ((decorators DEF NAME function_parameter_list COLON suite)
+ (wisent-python-reconstitute-function-tag
+ (wisent-raw-tag
+ (semantic-tag-new-function $3 nil $4 :decorators $1))
+ $6)))
(function_parameter_list
((PAREN_BLOCK)
(let
(semantic-tag-new-variable $2 nil nil))))
(class_declaration
((CLASS NAME paren_class_list_opt COLON suite)
- (wisent-raw-tag
- (semantic-tag-new-type $2 $1 $5
- (cons $3 nil)))))
+ (wisent-python-reconstitute-class-tag
+ (wisent-raw-tag
+ (semantic-tag-new-type $2 $1 $5
+ (cons $3 nil))))))
(paren_class_list_opt
(nil)
((paren_class_list)))
\f
;;; Analyzers
-
+;;
(define-lex-block-type-analyzer wisent-python-wy--<block>-block-analyzer
"block analyzer for <block> tokens."
"\\s(\\|\\s)"
("]" RBRACK))
)
+(define-lex-regex-type-analyzer wisent-python-wy--<symbol>-regexp-analyzer
+ "regexp analyzer for <symbol> tokens."
+ "\\(\\sw\\|\\s_\\)+"
+ nil
+ 'NAME)
+
+(define-lex-regex-type-analyzer wisent-python-wy--<number>-regexp-analyzer
+ "regexp analyzer for <number> tokens."
+ semantic-lex-number-expression
+ nil
+ 'NUMBER_LITERAL)
+
(define-lex-string-type-analyzer wisent-python-wy--<punctuation>-string-analyzer
"string analyzer for <punctuation> tokens."
"\\(\\s.\\|\\s$\\|\\s'\\)+"
- '((BACKQUOTE . "`")
+ '((AT . "@")
+ (BACKQUOTE . "`")
(ASSIGN . "=")
(COMMA . ",")
(SEMICOLON . ";")
(LTLTEQ . "<<="))
'punctuation)
-(define-lex-regex-type-analyzer wisent-python-wy--<symbol>-regexp-analyzer
- "regexp analyzer for <symbol> tokens."
- "\\(\\sw\\|\\s_\\)+"
- nil
- 'NAME)
-
-(define-lex-regex-type-analyzer wisent-python-wy--<number>-regexp-analyzer
- "regexp analyzer for <number> tokens."
- semantic-lex-number-expression
- nil
- 'NUMBER_LITERAL)
-
(define-lex-keyword-type-analyzer wisent-python-wy--<keyword>-keyword-analyzer
"keyword analyzer for <keyword> tokens."
"\\(\\sw\\|\\s_\\)+")
;;; Code:
+(require 'rx)
+
+;; Try to load python support, but fail silently since it is only used
+;; for optional functionality
+(require 'python nil t)
+
(require 'semantic/wisent)
(require 'semantic/wisent/python-wy)
+(require 'semantic/find)
(require 'semantic/dep)
(require 'semantic/ctxt)
+(eval-when-compile
+ (require 'cl))
+
+;;; Customization
+;;
+
+(defun semantic-python-get-system-include-path ()
+ "Evaluate some Python code that determines the system include path."
+ (python-proc)
+ (if python-buffer
+ (with-current-buffer python-buffer
+ (set (make-local-variable 'python-preoutput-result) nil)
+ (python-send-string
+ "import sys; print '_emacs_out ' + '\\0'.join(sys.path)")
+ (accept-process-output (python-proc) 2)
+ (if python-preoutput-result
+ (split-string python-preoutput-result "[\0\n]" t)
+ ;; Try a second, Python3k compatible shot
+ (python-send-string
+ "import sys; print('_emacs_out ' + '\\0'.join(sys.path))")
+ (accept-process-output (python-proc) 2)
+ (if python-preoutput-result
+ (split-string python-preoutput-result "[\0\n]" t)
+ (message "Timeout while querying Python for system include path.")
+ nil)))
+ (message "Python seems to be unavailable on this system.")))
+
+(defcustom-mode-local-semantic-dependency-system-include-path
+ python-mode semantic-python-dependency-system-include-path
+ (when (and (featurep 'python)
+ ;; python-mode and batch somehow often hangs.
+ (not noninteractive))
+ (semantic-python-get-system-include-path))
+ "The system include path used by Python language.")
\f
;;; Lexical analysis
;;
;; Python strings are delimited by either single quotes or double
-;; quotes, e.g., "I'm a string" and 'I too am s string'.
+;; quotes, e.g., "I'm a string" and 'I too am a string'.
;; In addition a string can have either a 'r' and/or 'u' prefix.
;; The 'r' prefix means raw, i.e., normal backslash substitutions are
;; to be suppressed. For example, r"01\n34" is a string with six
;; characters 0, 1, \, n, 3 and 4. The 'u' prefix means the following
;; string is Unicode.
-(defconst wisent-python-string-re
- (concat (regexp-opt '("r" "u" "ur" "R" "U" "UR" "Ur" "uR") t)
- "?['\"]")
+(defconst wisent-python-string-start-re "[uU]?[rR]?['\"]"
"Regexp matching beginning of a Python string.")
+(defconst wisent-python-string-re
+ (rx
+ (opt (any "uU")) (opt (any "rR"))
+ (or
+ ;; Triple-quoted string using apostrophes
+ (: "'''" (zero-or-more (or "\\'"
+ (not (any "'"))
+ (: (repeat 1 2 "'") (not (any "'")))))
+ "'''")
+ ;; String using apostrophes
+ (: "'" (zero-or-more (or "\\'"
+ (not (any "'"))))
+ "'")
+ ;; Triple-quoted string using quotation marks.
+ (: "\"\"\"" (zero-or-more (or "\\\""
+ (not (any "\""))
+ (: (repeat 1 2 "\"") (not (any "\"")))))
+ "\"\"\"")
+ ;; String using quotation marks.
+ (: "\"" (zero-or-more (or "\\\""
+ (not (any "\""))))
+ "\"")))
+ "Regexp matching a complete Python string.")
+
(defvar wisent-python-EXPANDING-block nil
"Non-nil when expanding a paren block for Python lexical analyzer.")
(defsubst wisent-python-forward-string ()
"Move point at the end of the Python string at point."
- (when (looking-at wisent-python-string-re)
- ;; skip the prefix
- (and (match-end 1) (goto-char (match-end 1)))
- ;; skip the quoted part
- (cond
- ((looking-at "\"\"\"[^\"]")
- (search-forward "\"\"\"" nil nil 2))
- ((looking-at "'''[^']")
- (search-forward "'''" nil nil 2))
- ((forward-sexp 1)))))
+ (if (looking-at wisent-python-string-re)
+ (let ((start (match-beginning 0))
+ (end (match-end 0)))
+ ;; Incomplete triple-quoted string gets matched instead as a
+ ;; complete single quoted string. (This special case would be
+ ;; unnecessary if Emacs regular expressions had negative
+ ;; look-ahead assertions.)
+ (when (and (= (- end start) 2)
+ (looking-at "\"\\{3\\}\\|'\\{3\\}"))
+ (error "unterminated syntax"))
+ (goto-char end))
+ (error "unterminated syntax")))
+
+(defun wisent-python-forward-balanced-expression ()
+ "Move point to the end of the balanced expression at point.
+Here 'balanced expression' means anything matched by Emacs'
+open/close parenthesis syntax classes. We can't use forward-sexp
+for this because that Emacs built-in can't parse Python's
+triple-quoted string syntax."
+ (let ((end-char (cdr (syntax-after (point)))))
+ (forward-char 1)
+ (while (not (or (eobp) (eq (char-after (point)) end-char)))
+ (cond
+ ;; Skip over python strings.
+ ((looking-at wisent-python-string-start-re)
+ (wisent-python-forward-string))
+ ;; At a comment start just goto end of line.
+ ((looking-at "\\s<")
+ (end-of-line))
+ ;; Skip over balanced expressions.
+ ((looking-at "\\s(")
+ (wisent-python-forward-balanced-expression))
+ ;; Skip over white space, word, symbol, punctuation, paired
+ ;; delimiter (backquote) characters, line continuation, and end
+ ;; of comment characters (AKA newline characters in Python).
+ ((zerop (skip-syntax-forward "-w_.$\\>"))
+ (error "can't figure out how to go forward from here"))))
+ ;; Skip closing character. As a last resort this should raise an
+ ;; error if we hit EOB before we find our closing character..
+ (forward-char 1)))
(defun wisent-python-forward-line ()
"Move point to the beginning of the next logical line.
(progn
(cond
;; Skip over python strings.
- ((looking-at wisent-python-string-re)
+ ((looking-at wisent-python-string-start-re)
(wisent-python-forward-string))
;; At a comment start just goto end of line.
((looking-at "\\s<")
(end-of-line))
- ;; Skip over generic lists and strings.
- ((looking-at "\\(\\s(\\|\\s\"\\)")
- (forward-sexp 1))
+ ;; Skip over balanced expressions.
+ ((looking-at "\\s(")
+ (wisent-python-forward-balanced-expression))
;; At the explicit line continuation character
;; (backslash) move to next line.
((looking-at "\\s\\")
(defun wisent-python-forward-line-skip-indented ()
"Move point to the next logical line, skipping indented lines.
-That is the next line whose indentation is less than or equal to the
-indentation of the current line."
+That is the next line whose indentation is less than or equal to
+the indentation of the current line."
(let ((indent (current-indentation)))
(while (progn (wisent-python-forward-line)
(and (not (eobp))
;; Loop lexer to handle tokens in current line.
t)
;; Indentation decreased
- (t
- ;; Pop items from indentation stack
- (while (< curr-indent last-indent)
- (pop wisent-python-indent-stack)
- (setq semantic-lex-current-depth (1- semantic-lex-current-depth)
- last-indent (car wisent-python-indent-stack))
- (semantic-lex-push-token
- (semantic-lex-token 'DEDENT last-pos (point))))
+ ((progn
+ ;; Pop items from indentation stack
+ (while (< curr-indent last-indent)
+ (pop wisent-python-indent-stack)
+ (setq semantic-lex-current-depth (1- semantic-lex-current-depth)
+ last-indent (car wisent-python-indent-stack))
+ (semantic-lex-push-token
+ (semantic-lex-token 'DEDENT last-pos (point))))
+ (= last-pos (point)))
;; If pos did not change, then we must return nil so that
;; other lexical analyzers can be run.
- (/= last-pos (point))))))
+ nil))))
;; All the work was done in the above analyzer matching condition.
)
(define-lex-regex-analyzer wisent-python-lex-string
"Detect and create python string tokens."
- wisent-python-string-re
+ wisent-python-string-start-re
(semantic-lex-push-token
(semantic-lex-token
'STRING_LITERAL
semantic-lex-ignore-comments
;; Signal error on unhandled syntax.
semantic-lex-default-action)
+
+\f
+;;; Parsing
+;;
+
+(defun wisent-python-reconstitute-function-tag (tag suite)
+ "Move a docstring from TAG's members into its :documentation attribute.
+Set attributes for constructors, special, private and static methods."
+ ;; Analyze first statement to see whether it is a documentation
+ ;; string.
+ (let ((first-statement (car suite)))
+ (when (semantic-python-docstring-p first-statement)
+ (semantic-tag-put-attribute
+ tag :documentation
+ (semantic-python-extract-docstring first-statement))))
+
+ ;; TODO HACK: we try to identify methods using the following
+ ;; heuristic:
+ ;; + at least one argument
+ ;; + first argument is self
+ (when (and (> (length (semantic-tag-function-arguments tag)) 0)
+ (string= (semantic-tag-name
+ (first (semantic-tag-function-arguments tag)))
+ "self"))
+ (semantic-tag-put-attribute tag :parent "dummy"))
+
+ ;; Identify constructors, special and private functions
+ (cond
+ ;; TODO only valid when the function resides inside a class
+ ((string= (semantic-tag-name tag) "__init__")
+ (semantic-tag-put-attribute tag :constructor-flag t)
+ (semantic-tag-put-attribute tag :suite suite))
+
+ ((semantic-python-special-p tag)
+ (semantic-tag-put-attribute tag :special-flag t))
+
+ ((semantic-python-private-p tag)
+ (semantic-tag-put-attribute tag :protection "private")))
+
+ ;; If there is a staticmethod decorator, add a static typemodifier
+ ;; for the function.
+ (when (semantic-find-tags-by-name
+ "staticmethod"
+ (semantic-tag-get-attribute tag :decorators))
+ (semantic-tag-put-attribute
+ tag :typemodifiers
+ (cons "static"
+ (semantic-tag-get-attribute tag :typemodifiers))))
+
+ ;; TODO
+ ;; + check for decorators classmethod
+ ;; + check for operators
+ tag)
+
+(defun wisent-python-reconstitute-class-tag (tag)
+ "Move a docstring from TAG's members into its :documentation attribute."
+ ;; The first member of TAG may be a documentation string. If that is
+ ;; the case, remove of it from the members list and stick its
+ ;; content into the :documentation attribute.
+ (let ((first-member (car (semantic-tag-type-members tag))))
+ (when (semantic-python-docstring-p first-member)
+ (semantic-tag-put-attribute
+ tag :members
+ (cdr (semantic-tag-type-members tag)))
+ (semantic-tag-put-attribute
+ tag :documentation
+ (semantic-python-extract-docstring first-member))))
+
+ ;; Try to find the constructor, determine the name of the instance
+ ;; parameter, find assignments to instance variables and add
+ ;; corresponding variable tags to the list of members.
+ (dolist (member (semantic-tag-type-members tag))
+ (when (semantic-tag-function-constructor-p member)
+ (let ((self (semantic-tag-name
+ (car (semantic-tag-function-arguments member)))))
+ (dolist (statement (semantic-tag-get-attribute member :suite))
+ (when (semantic-python-instance-variable-p statement self)
+ (let ((variable (semantic-tag-clone
+ statement
+ (substring (semantic-tag-name statement) 5)))
+ (members (semantic-tag-get-attribute tag :members)))
+ (when (semantic-python-private-p variable)
+ (semantic-tag-put-attribute variable :protection "private"))
+ (setcdr (last members) (list variable))))))))
+
+ ;; TODO remove the :suite attribute
+ tag)
+
+(defun semantic-python-expand-tag (tag)
+ "Expand compound declarations found in TAG into separate tags.
+TAG contains compound declaration if the NAME part of the tag is
+a list. In python, this can happen with `import' statements."
+ (let ((class (semantic-tag-class tag))
+ (elts (semantic-tag-name tag))
+ (expand nil))
+ (cond
+ ((and (eq class 'include) (listp elts))
+ (dolist (E elts)
+ (setq expand (cons (semantic-tag-clone tag E) expand)))
+ (setq expand (nreverse expand)))
+ )))
+
+
\f
;;; Overridden Semantic API.
;;
+
(define-mode-local-override semantic-lex python-mode
(start end &optional depth length)
"Lexically analyze Python code in current buffer.
To be implemented for Python! For now just return nil."
nil)
-(defcustom-mode-local-semantic-dependency-system-include-path
- python-mode semantic-python-dependency-system-include-path
- nil
- "The system include path used by Python language.")
+;; Adapted from the semantic Java support by Andrey Torba
+(define-mode-local-override semantic-tag-include-filename python-mode (tag)
+ "Return a suitable path for (some) Python imports."
+ (let ((name (semantic-tag-name tag)))
+ (concat (mapconcat 'identity (split-string name "\\.") "/") ".py")))
;;; Enable Semantic in `python-mode'.
;;
"Setup buffer for parse."
(wisent-python-wy--install-parser)
(set (make-local-variable 'parse-sexp-ignore-comments) t)
+ ;; Give python modes the possibility to overwrite this:
+ (if (not comment-start-skip)
+ (set (make-local-variable 'comment-start-skip) "#+\\s-*"))
(setq
- ;; Character used to separation a parent/child relationship
+ ;; Character used to separation a parent/child relationship
semantic-type-relation-separator-character '(".")
semantic-command-separation-character ";"
- ;; The following is no more necessary as semantic-lex is overridden
- ;; in python-mode.
- ;; semantic-lex-analyzer 'wisent-python-lexer
+ ;; Parsing
+ semantic-tag-expand-function 'semantic-python-expand-tag
;; Semantic to take over from the one provided by python.
;; The python one, if it uses the senator advice, will hang
(define-child-mode python-2-mode python-mode "Python 2 mode")
(define-child-mode python-3-mode python-mode "Python 3 mode")
+\f
+;;; Utility functions
+;;
+
+(defun semantic-python-special-p (tag)
+ "Return non-nil if the name of TAG is a special identifier of
+the form __NAME__. "
+ (string-match
+ (rx (seq string-start "__" (1+ (syntax symbol)) "__" string-end))
+ (semantic-tag-name tag)))
+
+(defun semantic-python-private-p (tag)
+ "Return non-nil if the name of TAG follows the convention _NAME
+for private names."
+ (string-match
+ (rx (seq string-start "_" (0+ (syntax symbol)) string-end))
+ (semantic-tag-name tag)))
+
+(defun semantic-python-instance-variable-p (tag &optional self)
+ "Return non-nil if TAG is an instance variable of the instance
+SELF or the instance name \"self\" if SELF is nil."
+ (when (semantic-tag-of-class-p tag 'variable)
+ (let ((name (semantic-tag-name tag)))
+ (when (string-match
+ (rx-to-string
+ `(seq string-start ,(or self "self") "."))
+ name)
+ (not (string-match "\\." (substring name 5)))))))
+
+(defun semantic-python-docstring-p (tag)
+ "Return non-nil, when TAG is a Python documentation string."
+ ;; TAG is considered to be a documentation string if the first
+ ;; member is of class 'code and its name looks like a documentation
+ ;; string.
+ (let ((class (semantic-tag-class tag))
+ (name (semantic-tag-name tag)))
+ (and (eq class 'code)
+ (string-match
+ (rx (seq string-start "\"\"\"" (0+ anything) "\"\"\"" string-end))
+ name))))
+
+(defun semantic-python-extract-docstring (tag)
+ "Return the Python documentation string contained in TAG."
+ ;; Strip leading and trailing """
+ (let ((name (semantic-tag-name tag)))
+ (substring name 3 -3)))
+
\f
;;; Test
;;
+
(defun wisent-python-lex-buffer ()
"Run `wisent-python-lexer' on current buffer."
(interactive)
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Keywords: codegeneration
-;; Version: 1.0pre7
;; This file is part of GNU Emacs.
(buffer-file-name))))
(mode nil)
(application nil)
+ (framework nil)
(priority nil)
(project nil)
(vars nil)
)
((string= name "application")
(setq application (read firstvalue)))
+ ((string= name "framework")
+ (setq framework (read firstvalue)))
((string= name "priority")
(setq priority (read firstvalue)))
((string= name "project")
priority))
;; Save it up!
- (srecode-compile-template-table table mode priority application project vars)
+ (srecode-compile-template-table table mode priority application framework project vars)
)
)
(while (and comp (stringp (car comp)))
(setq comp (cdr comp)))
(or (not comp)
- (require 'srecode/insert)
- (srecode-template-inserter-newline-child-p (car comp))))
+ (progn (require 'srecode/insert)
+ (srecode-template-inserter-newline-child-p (car comp)))))
(defun srecode-compile-split-code (tag str STATE
&optional end-name)
(if (not new) (error "SRECODE: Unknown macro code %S" key))
new)))
-(defun srecode-compile-template-table (templates mode priority application project vars)
+(defun srecode-compile-template-table (templates mode priority application framework 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.
+FRAMEWORK is the name of the framework 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
:major-mode mode
:priority priority
:application application
+ :framework framework
:project project))
(tmpl (oref table templates)))
;; Loop over all the templates, and xref.
:group 'srecode-cpp
:type '(repeat string))
-;;; :cpp ARGUMENT HANDLING
+;;; :c ARGUMENT HANDLING
;;
-;; When a :cpp argument is required, fill the dictionary with
-;; information about the current C++ file.
+;; When a :c argument is required, fill the dictionary with
+;; information about the current C file.
;;
-;; Error if not in a C++ mode.
+;; Error if not in a C mode.
;;;###autoload
-(defun srecode-semantic-handle-:cpp (dict)
- "Add macros into the dictionary DICT based on the current c++ file.
+(defun srecode-semantic-handle-:c (dict)
+ "Add macros into the dictionary DICT based on the current c file.
Adds the following:
FILENAME_SYMBOL - filename converted into a C compat symbol.
HEADER - Shown section if in a header file."
)
)
+;;; :cpp ARGUMENT HANDLING
+;;
+;; When a :cpp argument is required, fill the dictionary with
+;; information about the current C++ file.
+;;
+;; Error if not in a C++ mode.
+;;;###autoload
+(defun srecode-semantic-handle-:cpp (dict)
+ "Add macros into the dictionary DICT based on the current c file.
+Calls `srecode-semantic-handle-:c.
+Also adds the following:
+ - nothing -"
+ (srecode-semantic-handle-:c dict)
+ )
+
(defun srecode-semantic-handle-:using-namespaces (dict)
"Add macros into the dictionary DICT based on used namespaces.
Adds the following:
)
(define-mode-local-override srecode-semantic-apply-tag-to-dict
- c++-mode (tag-wrapper dict)
- "Apply C++ specific features from TAG-WRAPPER into DICT.
+ c-mode (tag-wrapper dict)
+ "Apply C and C++ specific features from TAG-WRAPPER into DICT.
Calls `srecode-semantic-apply-tag-to-dict-default' first. Adds
-special behavior for tag of classes include, using and function."
+special behavior for tag of classes include, using and function.
+
+This function cannot be split into C and C++ specific variants, as
+the way the tags are created from the parser does not distinguish
+either. The side effect is that you could get some C++ tag properties
+specified in a C file."
;; Use default implementation to fill in the basic properties.
(srecode-semantic-apply-tag-to-dict-default tag-wrapper dict)
(templates (semantic-tag-get-attribute tag :template))
(modifiers (semantic-tag-modifiers tag)))
- ;; Add modifiers into the dictionary
+ ;; Mark constructors and destructors as such.
+ (when (semantic-tag-function-constructor-p tag)
+ (srecode-dictionary-show-section dict "CONSTRUCTOR"))
+ (when (semantic-tag-function-destructor-p tag)
+ (srecode-dictionary-show-section dict "DESTRUCTOR"))
+
+ ;; Add modifiers into the dictionary.
(dolist (modifier modifiers)
(let ((modifier-dict (srecode-dictionary-add-section-dictionary
dict "MODIFIERS")))
(srecode-dictionary-set-value modifier-dict "NAME" modifier)))
;; Add templates into child dictionaries.
- (srecode-cpp-apply-templates dict templates)
+ (srecode-c-apply-templates dict templates)
;; When the function is a member function, it can have
;; additional modifiers.
;; If the member function is pure virtual, add a dictionary
;; entry.
(when (semantic-tag-get-attribute tag :pure-virtual-flag)
- (srecode-dictionary-show-section dict "PURE"))
- )))
+ (srecode-dictionary-show-section dict "PURE")))))
;;
;; CLASS
;; Add templates into child dictionaries.
(let ((templates (semantic-tag-get-attribute tag :template)))
- (srecode-cpp-apply-templates dict templates))))
+ (srecode-c-apply-templates dict templates))))
))
)
;;; Helper functions
;;
-(defun srecode-cpp-apply-templates (dict templates)
+(defun srecode-c-apply-templates (dict templates)
"Add section dictionaries for TEMPLATES to DICT."
(when templates
(let ((templates-dict (srecode-dictionary-add-section-dictionary
(cons (car fields) newfields))))
(setq fields (cdr (cdr fields))))
- (when (not state)
- (error "Cannot create compound variable without :state"))
+ ;;(when (not state)
+ ;; (error "Cannot create compound variable outside of sectiondictionary"))
(call-next-method this (nreverse newfields))
(when (not (slot-boundp this 'compiled))
"Insert into DICT the variables found in table TPL.
TPL is an object representing a compiled template file."
(when tpl
- (let ((tabs (oref tpl :tables)))
+ ;; Tables are sorted with highest priority first, useful for looking
+ ;; up templates, but this means we need to install the variables in
+ ;; reverse order so higher priority variables override lower ones.
+ (let ((tabs (reverse (oref tpl :tables))))
(require 'srecode/find) ; For srecode-template-table-in-project-p
(while tabs
(when (srecode-template-table-in-project-p (car tabs))
\f
;;; Higher level dictionary functions
;;
-(defun srecode-create-section-dictionary (sectiondicts STATE)
- "Create a dictionary with section entries for a template.
-The format for SECTIONDICTS is what is emitted from the template parsers.
-STATE is the current compiler state."
- (when sectiondicts
- (let ((new (srecode-create-dictionary t)))
- ;; Loop over each section. The section is a macro w/in the
- ;; template.
- (while sectiondicts
- (let* ((sect (car (car sectiondicts)))
- (entries (cdr (car sectiondicts)))
- (subdict (srecode-dictionary-add-section-dictionary new sect))
- )
- ;; Loop over each entry. This is one variable in the
- ;; section dictionary.
- (while entries
- (let ((tname (semantic-tag-name (car entries)))
- (val (semantic-tag-variable-default (car entries))))
- (if (eq val t)
- (srecode-dictionary-show-section subdict tname)
- (cond
- ((and (stringp (car val))
- (= (length val) 1))
- (setq val (car val)))
- (t
- (setq val (srecode-dictionary-compound-variable
- tname :value val :state STATE))))
- (srecode-dictionary-set-value
- subdict tname val))
- (setq entries (cdr entries))))
- )
- (setq sectiondicts (cdr sectiondicts)))
- new)))
-
(defun srecode-create-dictionaries-from-tags (tags state)
"Create a dictionary with entries according to TAGS.
(defvar srecode-read-template-name-history nil
"History for completing reads for template names.")
-(defun srecode-all-template-hash (&optional mode hash)
+(defun srecode-user-template-p (template)
+ "Non-nil if TEMPLATE is intended for user insertion.
+Templates not matching this predicate are used for code
+generation or other internal purposes."
+ t)
+
+(defun srecode-all-template-hash (&optional mode hash predicate)
"Create a hash table of all the currently available templates.
Optional argument MODE is the major mode to look for.
-Optional argument HASH is the hash table to fill in."
- (let* ((mhash (or hash (make-hash-table :test 'equal)))
- (mmode (or mode major-mode))
- (mp (get-mode-local-parent mmode))
- )
+Optional argument HASH is the hash table to fill in.
+Optional argument PREDICATE can be used to filter the returned
+templates."
+ (let* ((mhash (or hash (make-hash-table :test 'equal)))
+ (mmode (or mode major-mode))
+ (parent-mode (get-mode-local-parent mmode)))
;; Get the parent hash table filled into our current hash.
- (when (not (eq mode 'default))
- (if mp
- (srecode-all-template-hash mp mhash)
- (srecode-all-template-hash 'default mhash)))
+ (unless (eq mode 'default)
+ (srecode-all-template-hash (or parent-mode 'default) mhash))
+
;; Load up the hash table for our current mode.
- (let* ((mt (srecode-get-mode-table mmode))
- (tabs (when mt (oref mt :tables)))
- )
- (while tabs
+ (let* ((mt (srecode-get-mode-table mmode))
+ (tabs (when mt (oref mt :tables))))
+ (dolist (tab tabs)
;; Exclude templates for a particular application.
- (when (and (not (oref (car tabs) :application))
- (srecode-template-table-in-project-p (car tabs)))
+ (when (and (not (oref tab :application))
+ (srecode-template-table-in-project-p tab))
(maphash (lambda (key temp)
- (puthash key temp mhash)
- )
- (oref (car tabs) namehash)))
- (setq tabs (cdr tabs)))
+ (when (or (not predicate)
+ (funcall predicate temp))
+ (puthash key temp mhash)))
+ (oref tab namehash))))
mhash)))
(defun srecode-calculate-default-template-string (hash)
(let* ((kids (semantic-find-tags-by-class
'variable (semantic-tag-type-members class)))
(sel (completing-read "Use Field: " kids))
- )
-
- (or (semantic-find-tags-by-name sel kids)
- sel)
+ (fields (semantic-find-tags-by-name sel kids)))
+ (if fields
+ (car fields)
+ sel)
))
(defun srecode-auto-choose-class (point)
;; area. Return value is not important.
))
+(defun srecode-insert-show-error-report (dictionary format &rest args)
+ "Display an error report based on DICTIONARY, FORMAT and ARGS.
+This is intended to diagnose problems with failed template
+insertions."
+ (with-current-buffer (data-debug-new-buffer "*SRECODE INSERTION ERROR*")
+ (erase-buffer)
+ ;; Insert the stack of templates that are currently being
+ ;; inserted.
+ (insert (propertize "Template Stack" 'face '(:weight bold))
+ (propertize " (most recent at bottom)" 'face '(:slant italic))
+ ":\n")
+ (data-debug-insert-stuff-list
+ (reverse (oref srecode-template active)) "> ")
+ ;; Show the current dictionary.
+ (insert (propertize "Dictionary" 'face '(:weight bold)) "\n")
+ (data-debug-insert-thing dictionary "" "> ")
+ ;; Show the error message.
+ (insert (propertize "Error" 'face '(:weight bold)) "\n")
+ (insert (apply #'format format args))
+ (pop-to-buffer (current-buffer))))
+
+(defun srecode-insert-report-error (dictionary format &rest args)
+ ;; TODO only display something when inside an interactive call?
+ (srecode-insert-show-error-report dictionary format args)
+ (apply #'error format args))
+
;;; TEMPLATE ARGUMENTS
;;
;; Some templates have arguments. Each argument is associated with
(let ((srecode-inserter-variable-current-dictionary dictionary))
(funcall fcnpart value))
;; Else, warn.
- (error "Variable insertion second arg %s is not a function"
- secondname)))
+ (srecode-insert-report-error
+ dictionary
+ "Variable inserter %s: second argument `%s' is not a function"
+ (object-print sti) secondname)))
value))
(defmethod srecode-insert-method ((sti srecode-template-inserter-variable)
;; If the value returned is nil, then it may be a special
;; field inserter that requires us to set do-princ to nil.
(when (not val)
- (setq do-princ nil)
- )
- )
+ (setq do-princ nil)))
+
;; Dictionaries... not allowed in this style
((srecode-dictionary-child-p val)
- (error "Macro %s cannot insert a dictionary - use section macros instead"
- name))
+ (srecode-insert-report-error
+ dictionary
+ "Macro %s cannot insert a dictionary - use section macros instead"
+ name))
+
;; Other stuff... convert
(t
- (error "Macro %s cannot insert arbitrary data" name)
- ;;(if (and val (not (stringp val)))
- ;; (setq val (format "%S" val))))
- ))
+ (srecode-insert-report-error
+ dictionary
+ "Macro %s cannot insert arbitrary data" name)))
;; Output the dumb thing unless the type of thing specifically
;; did the inserting for us.
(when do-princ
"Derive the default value for an askable inserter STI.
DICTIONARY is used to derive some values."
(let ((defaultfcn (oref sti :defaultfcn)))
- (cond ((stringp defaultfcn)
- defaultfcn)
- ((functionp defaultfcn)
- (funcall defaultfcn))
- ((and (listp defaultfcn)
- (eq (car defaultfcn) 'macro))
- (srecode-dictionary-lookup-name
- dictionary (cdr defaultfcn)))
- ((null defaultfcn)
- "")
- (t
- (error "Unknown default for prompt: %S"
- defaultfcn)))))
+ (cond
+ ((stringp defaultfcn)
+ defaultfcn)
+
+ ((functionp defaultfcn)
+ (funcall defaultfcn))
+
+ ((and (listp defaultfcn)
+ (eq (car defaultfcn) 'macro))
+ (srecode-dictionary-lookup-name
+ dictionary (cdr defaultfcn)))
+
+ ((null defaultfcn)
+ "")
+
+ (t
+ (srecode-insert-report-error
+ dictionary
+ "Unknown default for prompt: %S" defaultfcn)))))
(defmethod srecode-insert-method-ask ((sti srecode-template-inserter-ask)
dictionary)
"For VALUE handle WIDTH behaviors for this variable inserter.
Return the result as a string.
By default, treat as a function name."
- (if width
- ;; Trim or pad to new length
- (let* ((split (split-string width ":"))
- (width (string-to-number (nth 0 split)))
- (second (nth 1 split))
- (pad (cond ((or (null second) (string= "right" second))
- 'right)
- ((string= "left" second)
- 'left)
- (t
- (error "Unknown pad type %s" second)))))
- (if (>= (length value) width)
- ;; Simple case - too long.
- (substring value 0 width)
- ;; We need to pad on one side or the other.
- (let ((padchars (make-string (- width (length value)) ? )))
- (if (eq pad 'left)
- (concat padchars value)
- (concat value padchars)))))
- (error "Width not specified for variable/width inserter")))
+ ;; Cannot work without width.
+ (unless width
+ (srecode-insert-report-error
+ dictionary
+ "Width not specified for variable/width inserter"))
+
+ ;; Trim or pad to new length
+ (let* ((split (split-string width ":"))
+ (width (string-to-number (nth 0 split)))
+ (second (nth 1 split))
+ (pad (cond
+ ((or (null second) (string= "right" second))
+ 'right)
+ ((string= "left" second)
+ 'left)
+ (t
+ (srecode-insert-report-error
+ dictionary
+ "Unknown pad type %s" second)))))
+ (if (>= (length value) width)
+ ;; Simple case - too long.
+ (substring value 0 width)
+ ;; We need to pad on one side or the other.
+ (let ((padchars (make-string (- width (length value)) ? )))
+ (if (eq pad 'left)
+ (concat padchars value)
+ (concat value padchars))))))
(defmethod srecode-inserter-prin-example :STATIC ((ins srecode-template-inserter-width)
escape-start escape-end)
(defmethod srecode-insert-subtemplate ((sti srecode-template-inserter-subtemplate)
dict slot)
"Insert a subtemplate for the inserter STI with dictionary DICT."
- ;; make sure that only dictionaries are used.
- (when (not (srecode-dictionary-child-p dict))
- (error "Only section dictionaries allowed for %s"
- (object-name-string sti)))
+ ;; Make sure that only dictionaries are used.
+ (unless (srecode-dictionary-child-p dict)
+ (srecode-insert-report-error
+ dict
+ "Only section dictionaries allowed for `%s'"
+ (object-name-string sti)))
+
;; Output the code from the sub-template.
- (srecode-insert-method (slot-value sti slot) dict)
- )
+ (srecode-insert-method (slot-value sti slot) dict))
(defmethod srecode-insert-method-helper ((sti srecode-template-inserter-subtemplate)
dictionary 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)))
+ (srecode-insert-report-error
+ dictionary
+ "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-report-error
+ dictionary
+ "Cannot insert section %S from non-section variable."
+ (oref sti :object-name)))
(srecode-insert-subtemplate sti (car dicts) slot)
(setq dicts (cdr dicts)))))
"For the template inserter STI, lookup the template to include.
Finds the template with this macro function part and stores it in
this template instance."
- (let* ((templatenamepart (oref sti :secondname))
- )
- ;; If there was no template name, throw an error
- (if (not templatenamepart)
- (error "Include macro %s needs a template name" (oref sti :object-name)))
+ (let ((templatenamepart (oref sti :secondname)))
+ ;; If there was no template name, throw an error.
+ (unless templatenamepart
+ (srecode-insert-report-error
+ dictionary
+ "Include macro `%s' needs a template name"
+ (oref sti :object-name)))
;; 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
;; 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.
- (error "No template \"%s\" found for include macro `%s'"
- templatenamepart (oref sti :object-name)))
- ))
+ (unless (oref sti includedtemplate)
+ ;; @todo - Call into a debugger to help find the template in question.
+ (srecode-insert-report-error
+ dictionary
+ "No template \"%s\" found for include macro `%s'"
+ templatenamepart (oref sti :object-name)))))
(defmethod srecode-insert-method ((sti srecode-template-inserter-include)
dictionary)
;;; Code:
(require 'srecode/dictionary)
+(require 'semantic/tag)
+
+(eval-when-compile
+ (require 'semantic/find))
;;;###autoload
(defun srecode-semantic-handle-:java (dict)
Adds the following:
FILENAME_AS_PACKAGE - file/dir converted into a java package name.
FILENAME_AS_CLASS - file converted to a Java class name."
- ;; A symbol representing
+ ;; Symbols needed by empty files.
(let* ((fsym (file-name-nondirectory (buffer-file-name)))
(fnox (file-name-sans-extension fsym))
(dir (file-name-directory (buffer-file-name)))
(if (string-match "src/" dir)
(setq dir (substring dir (match-end 0)))
(setq dir (file-name-nondirectory (directory-file-name dir))))
+ (setq dir (directory-file-name dir))
(while (string-match "/" dir)
- (setq dir (replace-match "_" t t dir)))
- (srecode-dictionary-set-value dict "FILENAME_AS_PACKAGE"
- (concat dir "." fpak))
+ (setq dir (replace-match "." t t dir)))
+ (srecode-dictionary-set-value dict "FILENAME_AS_PACKAGE" dir)
(srecode-dictionary-set-value dict "FILENAME_AS_CLASS" fnox)
- ))
+ )
+ ;; Symbols needed for most other files with stuff in them.
+ (let ((pkg (semantic-find-tags-by-class 'package (current-buffer))))
+ (when pkg
+ (srecode-dictionary-set-value dict "CURRENT_PACKAGE" (semantic-tag-name (car pkg)))
+ ))
+ )
(provide 'srecode/java)
(when (not srecode-current-map)
(condition-case nil
(setq srecode-current-map
- (eieio-persistent-read srecode-map-save-file))
+ (eieio-persistent-read srecode-map-save-file srecode-map))
(error
;; There was an error loading the old map. Create a new one.
(setq srecode-current-map
(require 'srecode/map)
(require 'semantic/decorate)
(require 'semantic/wisent)
+(require 'semantic/senator)
+(require 'semantic/wisent)
-(eval-when-compile (require 'semantic/find))
+(eval-when-compile
+ (require 'semantic/find))
;;; Code:
:keymap srecode-mode-map
;; If we are turning things on, make sure we have templates for
;; this mode first.
- (when srecode-minor-mode
- (when (not (apply
+ (if srecode-minor-mode
+ (if (not (apply
'append
(mapcar (lambda (map)
(srecode-map-entries-for-mode map major-mode))
(srecode-get-maps))))
- (setq srecode-minor-mode nil))))
+ (setq srecode-minor-mode nil)
+ ;; Else, we have success, do stuff
+ (add-hook 'cedet-m3-menu-do-hooks 'srecode-m3-items nil t)
+ )
+ (remove-hook 'cedet-m3-menu-do-hooks 'srecode-m3-items t)
+ )
+ ;; Run hooks if we are turning this on.
+ (when srecode-minor-mode
+ (run-hooks 'srecode-minor-mode-hook))
+ srecode-minor-mode)
;;;###autoload
(define-minor-mode global-srecode-minor-mode
(setq temp (srecode-semantic-find-template
"variable-const" prototype ctxt))
)
+
+ ((and (semantic-tag-of-class-p tag 'include)
+ (semantic-tag-get-attribute tag :system-flag))
+ (setq temp (srecode-semantic-find-template
+ "system-include" prototype ctxt))
+ )
)
(when (not temp)
(3 font-lock-builtin-face ))
("^\\(sectiondictionary\\)\\s-+\""
(1 font-lock-keyword-face))
+ ("^\\s\s*\\(section\\)\\s-+\""
+ (1 font-lock-keyword-face))
+ ("^\\s\s*\\(end\\)"
+ (1 font-lock-keyword-face))
("^\\(bind\\)\\s-+\""
(1 font-lock-keyword-face))
;; Variable type setting
- ("^\\(set\\)\\s-+\\(\\w+\\)\\s-+"
+ ("^\\s\s*\\(set\\)\\s-+\\(\\w+\\)\\s-+"
(1 font-lock-keyword-face)
(2 font-lock-variable-name-face))
- ("^\\(show\\)\\s-+\\(\\w+\\)\\s-*$"
+ ("^\\s\s*\\(show\\)\\s-+\\(\\w+\\)\\s-*$"
(1 font-lock-keyword-face)
(2 font-lock-variable-name-face))
("\\<\\(macro\\)\\s-+\""
;;; Code:
(require 'semantic/lex)
+(eval-when-compile (require 'semantic/bovine))
\f
;;; Prologue
;;
("context" . CONTEXT)
("template" . TEMPLATE)
("sectiondictionary" . SECTIONDICTIONARY)
+ ("section" . SECTION)
+ ("end" . END)
("prompt" . PROMPT)
("default" . DEFAULT)
("defaultmacro" . DEFAULTMACRO)
("defaultmacro" summary "prompt <symbol> \"Describe Symbol: \" [default[macro] <lispsym>|\"valuetext\"] [read <lispsym>]")
("default" summary "prompt <symbol> \"Describe Symbol: \" [default[macro] <lispsym>|\"valuetext\"] [read <lispsym>]")
("prompt" summary "prompt <symbol> \"Describe Symbol: \" [default[macro] <lispsym>|\"valuetext\"] [read <lispsym>]")
+ ("end" summary "section ... end")
+ ("section" summary "section <name>\\n <dictionary entries>\\n end")
("sectiondictionary" summary "sectiondictionary <name>\\n <dictionary entries>")
("template" summary "template <name>\\n <template definition>")
("context" summary "context <name>")
'(("number" :declared t)
("string" :declared t)
("symbol" :declared t)
+ ("property" syntax ":\\(\\w\\|\\s_\\)*")
("property" :declared t)
("newline" :declared t)
("punctuation" syntax "\\s.+")
(eval-when-compile
(require 'semantic/wisent/comp))
(wisent-compile-grammar
- '((SET SHOW MACRO CONTEXT TEMPLATE SECTIONDICTIONARY PROMPT DEFAULT DEFAULTMACRO READ BIND newline TEMPLATE_BLOCK property symbol string number)
+ '((SET SHOW MACRO CONTEXT TEMPLATE SECTIONDICTIONARY SECTION END PROMPT DEFAULT DEFAULTMACRO READ BIND newline TEMPLATE_BLOCK property symbol string number)
nil
(template_file
((newline)
(cons 'macro
(read $2))))
(template
- ((TEMPLATE templatename opt-dynamic-arguments newline opt-string opt-section-dictionaries TEMPLATE_BLOCK newline opt-bind)
+ ((TEMPLATE templatename opt-dynamic-arguments newline opt-string section-dictionary-list TEMPLATE_BLOCK newline opt-bind)
(wisent-raw-tag
(semantic-tag-new-function $2 nil $3 :documentation $5 :code $7 :dictionaries $6 :binding $9))))
(templatename
((string newline)
(read $1))
(nil nil))
- (opt-section-dictionaries
- (nil nil)
- ((section-dictionary-list)))
(section-dictionary-list
- ((one-section-dictionary)
- (list $1))
- ((section-dictionary-list one-section-dictionary)
+ (nil nil)
+ ((section-dictionary-list flat-section-dictionary)
+ (append $1
+ (list $2)))
+ ((section-dictionary-list section-dictionary)
(append $1
(list $2))))
- (one-section-dictionary
- ((SECTIONDICTIONARY string newline variable-list)
+ (flat-section-dictionary
+ ((SECTIONDICTIONARY string newline flat-dictionary-entry-list)
+ (cons
+ (read $2)
+ $4)))
+ (flat-dictionary-entry-list
+ (nil nil)
+ ((flat-dictionary-entry-list flat-dictionary-entry)
+ (append $1 $2)))
+ (flat-dictionary-entry
+ ((variable)
+ (wisent-cook-tag $1)))
+ (section-dictionary
+ ((SECTION string newline dictionary-entry-list END newline)
(cons
(read $2)
$4)))
- (variable-list
+ (dictionary-entry-list
+ (nil nil)
+ ((dictionary-entry-list dictionary-entry)
+ (append $1 $2)))
+ (dictionary-entry
((variable)
(wisent-cook-tag $1))
- ((variable-list variable)
- (append $1
- (wisent-cook-tag $2))))
+ ((section-dictionary)
+ (list $1)))
(opt-bind
((BIND string newline)
(read $2))
\f
;;; Analyzers
-
-(define-lex-string-type-analyzer srecode-template-wy--<punctuation>-string-analyzer
- "string analyzer for <punctuation> tokens."
- "\\s.+"
+;;
+(define-lex-regex-type-analyzer srecode-template-wy--<property>-regexp-analyzer
+ "regexp analyzer for <property> tokens."
+ ":\\(\\w\\|\\s_\\)*"
nil
- 'punctuation)
+ 'property)
(define-lex-regex-type-analyzer srecode-template-wy--<symbol>-regexp-analyzer
"regexp analyzer for <symbol> tokens."
nil
'number)
+(define-lex-string-type-analyzer srecode-template-wy--<punctuation>-string-analyzer
+ "string analyzer for <punctuation> tokens."
+ "\\s.+"
+ nil
+ 'punctuation)
+
(define-lex-sexp-type-analyzer srecode-template-wy--<string>-sexp-analyzer
"sexp analyzer for <string> tokens."
"\\s\""
templates that can be used with no additional dictionary values.
When it is non-nil, it is assumed the template macros need specialized
Emacs Lisp code to fill in the dictionary.")
+ (framework :initarg :framework
+ :type symbol
+ :documentation
+ "Tracks the name of the framework these templates belong to.
+If nil, then this template table belongs to any framework, or can be
+considered generic for all files of this language.
+A framework might be a specific library or build environment for which
+special templates are desired. OpenGL might be a framework that
+exists for multiple languages.")
(priority :initarg :priority
:type number
:documentation
(major-mode :initarg :major-mode
:documentation
"Table of template tables for this major-mode.")
+ (modetables :initarg :modetables
+ :documentation
+ "All that tables unique to this major mode.")
(tables :initarg :tables
:documentation
- "All the tables that have been defined for this major mode.")
+ "All the tables that can be used for this major mode.")
)
"Track template tables for a particular major mode.
Tracks all the template-tables for a specific major mode.")
(defun srecode-get-mode-table (mode)
"Get the SRecoder mode table for the major mode MODE.
-Optional argument SOFT indicates to not make a new one if a table
-was not found."
- (let ((ans nil))
- (while (and (not ans) mode)
- (setq ans (eieio-instance-tracker-find
- mode 'major-mode 'srecode-mode-table-list)
- mode (get-mode-local-parent mode)))
- ans))
+This will find the mode table specific to MODE, and then
+calculate all inherited templates from parent modes."
+ (let ((table nil)
+ (tmptable nil))
+ (while mode
+ (setq tmptable (eieio-instance-tracker-find
+ mode 'major-mode 'srecode-mode-table-list)
+ mode (get-mode-local-parent mode))
+ (when tmptable
+ (if (not table)
+ (progn
+ ;; If this is the first, update tables to have
+ ;; all the mode specific tables in it.
+ (setq table tmptable)
+ (oset table tables (oref table modetables)))
+ ;; If there already is a table, then reset the tables
+ ;; slot to include all the tables belonging to this new child node.
+ (oset table tables (append (oref table modetables)
+ (oref tmptable modetables)))))
+ )
+ table))
(defun srecode-make-mode-table (mode)
"Get the SRecoder mode table for the major mode MODE."
(let* ((ms (if (stringp mode) mode (symbol-name mode)))
(new (srecode-mode-table ms
:major-mode mode
+ :modetables nil
:tables nil)))
;; Save this new mode table in that mode's variable.
(eval `(setq-mode-local ,mode srecode-table ,new))
(defmethod srecode-mode-table-find ((mt srecode-mode-table) file)
"Look in the mode table MT for a template table from FILE.
Return nil if there was none."
- (object-assoc file 'file (oref mt tables)))
+ (object-assoc file 'file (oref mt modetables)))
(defun srecode-mode-table-new (mode file &rest init)
"Create a new template table for MODE in FILE.
init
)))
;; Whack the old table.
- (when old (object-remove-from-list mt 'tables old))
+ (when old (object-remove-from-list mt 'modetables old))
;; Add the new table
- (object-add-to-list mt 'tables new)
+ (object-add-to-list mt 'modetables new)
;; Sort the list in reverse order. When other routines
;; go front-to-back, the highest priority items are put
;; into the search table first, allowing lower priority items
;; to be the items found in the search table.
- (object-sort-list mt 'tables (lambda (a b)
- (> (oref a :priority)
- (oref b :priority))))
+ (object-sort-list mt 'modetables (lambda (a b)
+ (> (oref a :priority)
+ (oref b :priority))))
;; Return it.
new))
(when (oref tab :application)
(princ "\nApplication: ")
(princ (oref tab :application)))
+ (when (oref tab :framework)
+ (princ "\nFramework: ")
+ (princ (oref tab :framework)))
(when (oref tab :project)
(require 'srecode/find) ; For srecode-template-table-in-project-p
(princ "\nProject Directory: ")
;;; Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
-;; Version: 0.2
;; Keywords: OO, lisp
;; Package: eieio
))))
(oref this file))
-(defun eieio-persistent-read (filename)
- "Read a persistent object from FILENAME, and return it."
+(defun eieio-persistent-read (filename &optional class allow-subclass)
+ "Read a persistent object from FILENAME, and return it.
+Signal an error if the object in FILENAME is not a constructor
+for CLASS. Optional ALLOW-SUBCLASS says that it is ok for
+`eieio-peristent-read' to load in subclasses of class instead of
+being pendantic."
+ (unless class
+ (message "Unsafe call to `eieio-persistent-read'."))
+ (when (and class (not (class-p class)))
+ (signal 'wrong-type-argument (list 'class-p class)))
(let ((ret nil)
(buffstr nil))
(unwind-protect
;; so that any initialize-instance calls that depend on
;; the current buffer will work.
(setq ret (read buffstr))
- (if (not (child-of-class-p (car ret) 'eieio-persistent))
- (error "Corrupt object on disk"))
- (setq ret (eval ret))
+ (when (not (child-of-class-p (car ret) 'eieio-persistent))
+ (error "Corrupt object on disk: Unknown saved object"))
+ (when (and class
+ (not (or (eq (car ret) class ) ; same class
+ (and allow-subclass
+ (child-of-class-p (car ret) class)) ; subclasses
+ )))
+ (error "Corrupt object on disk: Invalid saved class"))
+ (setq ret (eieio-persistent-convert-list-to-object ret))
(oset ret file filename))
(kill-buffer " *tmp eieio read*"))
ret))
+(defun eieio-persistent-convert-list-to-object (inputlist)
+ "Convert the INPUTLIST, representing object creation to an object.
+While it is possible to just `eval' the INPUTLIST, this code instead
+validates the existing list, and explicitly creates objects instead of
+calling eval. This avoids the possibility of accidentally running
+malicious code.
+
+Note: This function recurses when a slot of :type of some object is
+identified, and needing more object creation."
+ (let ((objclass (nth 0 inputlist))
+ (objname (nth 1 inputlist))
+ (slots (nthcdr 2 inputlist))
+ (createslots nil))
+
+ ;; If OBJCLASS is an eieio autoload object, then we need to load it.
+ (eieio-class-un-autoload objclass)
+
+ (while slots
+ (let ((name (car slots))
+ (value (car (cdr slots))))
+
+ ;; Make sure that the value proposed for SLOT is valid.
+ ;; In addition, strip out quotes, list functions, and update
+ ;; object constructors as needed.
+ (setq value (eieio-persistent-validate/fix-slot-value
+ objclass name value))
+
+ (push name createslots)
+ (push value createslots)
+ )
+
+ (setq slots (cdr (cdr slots))))
+
+ (apply 'make-instance objclass objname (nreverse createslots))
+
+ ;;(eval inputlist)
+ ))
+
+(defun eieio-persistent-validate/fix-slot-value (class slot proposed-value)
+ "Validate that in CLASS, the SLOT with PROPOSED-VALUE is good, then fix.
+A limited number of functions, such as quote, list, and valid object
+constructor functions are considered valid.
+Secondarilly, any text properties will be stripped from strings."
+ (cond ((consp proposed-value)
+ ;; Lists with something in them need special treatment.
+ (let ((slot-idx (eieio-slot-name-index class nil slot))
+ (type nil)
+ (classtype nil))
+ (setq slot-idx (- slot-idx 3))
+ (setq type (aref (aref (class-v class) class-public-type)
+ slot-idx))
+
+ (setq classtype (eieio-persistent-slot-type-is-class-p
+ type))
+
+ (cond ((eq (car proposed-value) 'quote)
+ (car (cdr proposed-value)))
+
+ ;; An empty list sometimes shows up as (list), which is dumb, but
+ ;; we need to support it for backward compat.
+ ((and (eq (car proposed-value) 'list)
+ (= (length proposed-value) 1))
+ nil)
+
+ ;; We have a slot with a single object that can be
+ ;; saved here. Recurse and evaluate that
+ ;; sub-object.
+ ((and classtype (class-p classtype)
+ (child-of-class-p (car proposed-value) classtype))
+ (eieio-persistent-convert-list-to-object
+ proposed-value))
+
+ ;; List of object constructors.
+ ((and (eq (car proposed-value) 'list)
+ ;; 2nd item is a list.
+ (consp (car (cdr proposed-value)))
+ ;; 1st elt of 2nd item is a class name.
+ (class-p (car (car (cdr proposed-value))))
+ )
+
+ ;; Check the value against the input class type.
+ ;; If something goes wrong, issue a smart warning
+ ;; about how a :type is needed for this to work.
+ (unless (and
+ ;; Do we have a type?
+ (consp classtype) (class-p (car classtype)))
+ (error "In save file, list of object constructors found, but no :type specified for slot %S"
+ slot))
+
+ ;; We have a predicate, but it doesn't satisfy the predicate?
+ (dolist (PV (cdr proposed-value))
+ (unless (child-of-class-p (car PV) (car classtype))
+ (error "Corrupt object on disk")))
+
+ ;; We have a list of objects here. Lets load them
+ ;; in.
+ (let ((objlist nil))
+ (dolist (subobj (cdr proposed-value))
+ (push (eieio-persistent-convert-list-to-object subobj)
+ objlist))
+ ;; return the list of objects ... reversed.
+ (nreverse objlist)))
+ (t
+ proposed-value))))
+
+ ((stringp proposed-value)
+ ;; Else, check for strings, remove properties.
+ (substring-no-properties proposed-value))
+
+ (t
+ ;; Else, just return whatever the constant was.
+ proposed-value))
+ )
+
+(defun eieio-persistent-slot-type-is-class-p (type)
+ "Return the class refered to in TYPE.
+If no class is referenced there, then return nil."
+ (cond ((class-p type)
+ ;; If the type is a class, then return it.
+ type)
+
+ ((and (symbolp type) (string-match "-child$" (symbol-name type))
+ (class-p (intern-soft (substring (symbol-name type) 0
+ (match-beginning 0)))))
+ ;; If it is the predicate ending with -child, then return
+ ;; that class. Unfortunately, in EIEIO, typep of just the
+ ;; class is the same as if we used -child, so no further work needed.
+ (intern-soft (substring (symbol-name type) 0
+ (match-beginning 0))))
+
+ ((and (symbolp type) (string-match "-list$" (symbol-name type))
+ (class-p (intern-soft (substring (symbol-name type) 0
+ (match-beginning 0)))))
+ ;; If it is the predicate ending with -list, then return
+ ;; that class and the predicate to use.
+ (cons (intern-soft (substring (symbol-name type) 0
+ (match-beginning 0)))
+ type))
+
+ ((and (consp type) (eq (car type) 'or))
+ ;; If type is a list, and is an or, it is possibly something
+ ;; like (or null myclass), so check for that.
+ (let ((ans nil))
+ (dolist (subtype (cdr type))
+ (setq ans (eieio-persistent-slot-type-is-class-p
+ subtype)))
+ ans))
+
+ (t
+ ;; No match, not a class.
+ nil)))
+
(defmethod object-write ((this eieio-persistent) &optional comment)
"Write persistent object THIS out to the current stream.
Optional argument COMMENT is a header line comment."
Optional argument GROUP is the sub-group of slots to display."
(eieio-customize-object obj group))
+(defvar eieio-custom-mode-map
+ (let ((map (make-sparse-keymap)))
+ (set-keymap-parent map widget-keymap)
+ map)
+ "Keymap for EIEIO Custom mode")
+
+(define-derived-mode eieio-custom-mode fundamental-mode "EIEIO Custom"
+ "Major mode for customizing EIEIO objects.
+\\{eieio-custom-mode-map}")
+
(defmethod eieio-customize-object ((obj eieio-default-superclass)
&optional group)
"Customize OBJ in a specialized custom buffer.
(symbol-name g) "*")))
(setq buffer-read-only nil)
(kill-all-local-variables)
+ (eieio-custom-mode)
(erase-buffer)
(let ((all (overlay-lists)))
;; Delete all the overlays.
(widget-insert "\n")
(eieio-custom-object-apply-reset obj)
;; Now initialize the buffer
- (use-local-map widget-keymap)
(widget-setup)
;;(widget-minor-mode)
(goto-char (point-min))
(provide 'eieio-custom)
-;; Local variables:
-;; generated-autoload-file: "eieio.el"
-;; End:
-
;;; eieio-custom.el ends here
"Class: ")
;; Loop over all the public slots
(let ((publa (aref cv class-public-a))
- (publd (aref cv class-public-d))
)
(while publa
(if (slot-boundp obj (car publa))
- (let ((i (class-slot-initarg cl (car publa)))
- (v (eieio-oref obj (car publa))))
+ (let* ((i (class-slot-initarg cl (car publa)))
+ (v (eieio-oref obj (car publa))))
(data-debug-insert-thing
v prefix (concat
(if i (symbol-name i)
" ")
'font-lock-keyword-face))
)
- (setq publa (cdr publa) publd (cdr publd))))))
+ (setq publa (cdr publa))))))
;;; Augment the Data debug thing display list.
(data-debug-add-specialized-thing (lambda (thing) (object-p thing))
;; Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
-;; Version: 0.2
;; Keywords: OO, lisp
;; Package: eieio
;;
(require 'eieio)
+(require 'button)
+(require 'help-mode)
+(require 'find-func)
;;; Code:
;;;###autoload
(called-interactively-p 'interactive))
(when headerfcn (funcall headerfcn))
-
- (if (class-option class :abstract)
- (princ "Abstract "))
- (princ "Class ")
(prin1 class)
+ (princ " is a")
+ (if (class-option class :abstract)
+ (princ "n abstract"))
+ (princ " class")
+ ;; Print file location
+ (when (get class 'class-location)
+ (princ " in `")
+ (princ (file-name-nondirectory (get class 'class-location)))
+ (princ "'"))
(terpri)
;; Inheritance tree information
(let ((pl (class-parents class)))
(eieio-describe-class
fcn (lambda ()
;; Describe the constructor part.
- (princ "Object Constructor Function: ")
(prin1 fcn)
+ (princ " is an object constructor function")
+ ;; Print file location
+ (when (get fcn 'class-location)
+ (princ " in `")
+ (princ (file-name-nondirectory (get fcn 'class-location)))
+ (princ "'"))
(terpri)
(princ "Creates an object of class ")
(prin1 fcn)
))
)
+(defun eieio-build-class-list (class)
+ "Return a list of all classes that inherit from CLASS."
+ (if (class-p class)
+ (apply #'append
+ (mapcar
+ (lambda (c)
+ (append (list c) (eieio-build-class-list c)))
+ (class-children-fast class)))
+ (list class)))
+
(defun eieio-build-class-alist (&optional class instantiable-only buildlist)
"Return an alist of all currently active classes for completion purposes.
Optional argument CLASS is the class to start with.
Optional argument BUILDLIST is more list to attach and is used internally."
(let* ((cc (or class eieio-default-superclass))
(sublst (aref (class-v cc) class-children)))
- (if (or (not instantiable-only) (not (class-abstract-p cc)))
- (setq buildlist (cons (cons (symbol-name cc) 1) buildlist)))
+ (unless (assoc (symbol-name cc) buildlist)
+ (when (or (not instantiable-only) (not (class-abstract-p cc)))
+ (setq buildlist (cons (cons (symbol-name cc) 1) buildlist))))
(while sublst
(setq buildlist (eieio-build-class-alist
(car sublst) instantiable-only buildlist))
(princ "Implementations:")
(terpri)
(terpri)
- (let ((i 3)
+ (let ((i 4)
(prefix [ ":STATIC" ":BEFORE" ":PRIMARY" ":AFTER" ] ))
;; Loop over fanciful generics
- (while (< i 6)
+ (while (< i 7)
(let ((gm (aref (get generic 'eieio-method-tree) i)))
(when gm
(princ "Generic ")
(setq i (1+ i)))
(setq i 0)
;; Loop over defined class-specific methods
- (while (< i 3)
- (let ((gm (reverse (aref (get generic 'eieio-method-tree) i))))
+ (while (< i 4)
+ (let ((gm (reverse (aref (get generic 'eieio-method-tree) i)))
+ location)
(while gm
(princ "`")
(prin1 (car (car gm)))
;; 3 because of cdr
(princ (or (documentation (cdr (car gm)))
"Undocumented"))
+ ;; Print file location if available
+ (when (and (setq location (get generic 'method-locations))
+ (setq location (assoc (caar gm) location)))
+ (setq location (cadr location))
+ (princ "\n\nDefined in `")
+ (princ (file-name-nondirectory location))
+ (princ "'\n"))
(setq gm (cdr gm))
(terpri)
(terpri)))
;;; HELP AUGMENTATION
;;
-;;;###autoload
+(define-button-type 'eieio-method-def
+ :supertype 'help-xref
+ 'help-function (lambda (class method file)
+ (eieio-help-find-method-definition class method file))
+ 'help-echo (purecopy "mouse-2, RET: find method's definition"))
+
+(define-button-type 'eieio-class-def
+ :supertype 'help-xref
+ 'help-function (lambda (class file)
+ (eieio-help-find-class-definition class file))
+ 'help-echo (purecopy "mouse-2, RET: find class definition"))
+
+(defun eieio-help-find-method-definition (class method file)
+ (let ((filename (find-library-name file))
+ location buf)
+ (when (null filename)
+ (error "Cannot find library %s" file))
+ (setq buf (find-file-noselect filename))
+ (with-current-buffer buf
+ (goto-char (point-min))
+ (when
+ (re-search-forward
+ ;; Regexp for searching methods.
+ (concat "(defmethod[ \t\r\n]+" method
+ "\\([ \t\r\n]+:[a-zA-Z]+\\)?"
+ "[ \t\r\n]+(\\s-*(\\(\\sw\\|\\s_\\)+\\s-+"
+ class
+ "\\s-*)")
+ nil t)
+ (setq location (match-beginning 0))))
+ (if (null location)
+ (message "Unable to find location in file")
+ (pop-to-buffer buf)
+ (goto-char location)
+ (recenter)
+ (beginning-of-line))))
+
+(defun eieio-help-find-class-definition (class file)
+ (let ((filename (find-library-name file))
+ location buf)
+ (when (null filename)
+ (error "Cannot find library %s" file))
+ (setq buf (find-file-noselect filename))
+ (with-current-buffer buf
+ (goto-char (point-min))
+ (when
+ (re-search-forward
+ ;; Regexp for searching a class.
+ (concat "(defclass[ \t\r\n]+" class "[ \t\r\n]+")
+ nil t)
+ (setq location (match-beginning 0))))
+ (if (null location)
+ (message "Unable to find location in file")
+ (pop-to-buffer buf)
+ (goto-char location)
+ (recenter)
+ (beginning-of-line))))
+
+
(defun eieio-help-mode-augmentation-maybee (&rest unused)
"For buffers thrown into help mode, augment for EIEIO.
Arguments UNUSED are not used."
(goto-char (point-min))
(while (re-search-forward "^\\(Private \\)?Slot:" nil t)
(put-text-property (match-beginning 0) (match-end 0) 'face 'bold))
+ (goto-char (point-min))
+ (cond
+ ((looking-at "\\(.+\\) is a generic function")
+ (let ((mname (match-string 1))
+ cname)
+ (while (re-search-forward "^`\\(.+\\)'[^\0]+?Defined in `\\(.+\\)'" nil t)
+ (setq cname (match-string-no-properties 1))
+ (help-xref-button 2 'eieio-method-def cname
+ mname
+ (cadr (assoc (intern cname)
+ (get (intern mname)
+ 'method-locations)))))))
+ ((looking-at "\\(.+\\) is an object constructor function in `\\(.+\\)'")
+ (let ((cname (match-string-no-properties 1)))
+ (help-xref-button 2 'eieio-class-def cname
+ (get (intern cname) 'class-location))))
+ ((looking-at "\\(.+\\) is a\\(n abstract\\)? class in `\\(.+\\)'")
+ (let ((cname (match-string-no-properties 1)))
+ (help-xref-button 3 'eieio-class-def cname
+ (get (intern cname) 'class-location)))))
))))
;;; SPEEDBAR SUPPORT
(provide 'eieio-opt)
-;; Local variables:
-;; generated-autoload-file: "eieio.el"
-;; End:
-
;;; eieio-opt.el ends here
;; Copyright (C) 1999-2002, 2005, 2007-2012 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
-;; Version: 0.2
;; Keywords: OO, tools
;; Package: eieio
\f
;;; DEFAULT SUPERCLASS baseline methods
;;
-;; First, define methods onto the superclass so all classes
-;; will have some minor support.
+;; First, define methods with no class defined. These will work as if
+;; on the default superclass. Specifying no class will allow these to be used
+;; when no other methods are found, allowing multiple inheritance to work
+;; reliably with eieio-speedbar.
-(defmethod eieio-speedbar-description ((object eieio-default-superclass))
+(defmethod eieio-speedbar-description (object)
"Return a string describing OBJECT."
(object-name-string object))
-(defmethod eieio-speedbar-derive-line-path ((object eieio-default-superclass))
+(defmethod eieio-speedbar-derive-line-path (object)
"Return the path which OBJECT has something to do with."
nil)
-(defmethod eieio-speedbar-object-buttonname ((object eieio-default-superclass))
+(defmethod eieio-speedbar-object-buttonname (object)
"Return a string to use as a speedbar button for OBJECT."
(object-name-string object))
-(defmethod eieio-speedbar-make-tag-line ((object eieio-default-superclass)
- depth)
+(defmethod eieio-speedbar-make-tag-line (object depth)
"Insert a tag line into speedbar at point for OBJECT.
By default, all objects appear as simple TAGS with no need to inherit from
the special `eieio-speedbar' classes. Child classes should redefine this
'speedbar-tag-face
depth))
-(defmethod eieio-speedbar-handle-click ((object eieio-default-superclass))
+(defmethod eieio-speedbar-handle-click (object)
"Handle a click action on OBJECT in speedbar.
Any object can be represented as a tag in SPEEDBAR without special
attributes. These default objects will be pulled up in a custom
;; Copyright (C) 1995-1996, 1998-2012 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
-;; Version: 1.3
;; Keywords: OO, lisp
;; This file is part of GNU Emacs.
(defvar eieio-optimize-primary-methods-flag t
"Non-nil means to optimize the method dispatch on primary methods.")
-;; State Variables
-;; FIXME: These two constants below should have an `eieio-' prefix added!!
-(defvar this nil
- "Inside a method, this variable is the object in question.
-DO NOT SET THIS YOURSELF unless you are trying to simulate friendly slots.
-
-Note: Embedded methods are no longer supported. The variable THIS is
-still set for CLOS methods for the sake of routines like
-`call-next-method'.")
-
-(defvar scoped-class nil
- "This is set to a class when a method is running.
-This is so we know we are allowed to check private parts or how to
-execute a `call-next-method'. DO NOT SET THIS YOURSELF!")
-
(defvar eieio-initializing-object nil
"Set to non-nil while initializing an object.")
(autoload cname filename doc nil nil)
(autoload (intern (concat (symbol-name cname) "-p")) filename "" nil nil)
(autoload (intern (concat (symbol-name cname) "-child-p")) filename "" nil nil)
+ (autoload (intern (concat (symbol-name cname) "-list-p")) filename "" nil nil)
))))
(and (eieio-object-p obj)
(object-of-class-p obj ,cname))))
+ ;; Create a handy list of the class test too
+ (let ((csym (intern (concat (symbol-name cname) "-list-p"))))
+ (fset csym
+ `(lambda (obj)
+ ,(format
+ "Test OBJ to see if it a list of objects which are a child of type %s"
+ cname)
+ (when (listp obj)
+ (let ((ans t)) ;; nil is valid
+ ;; Loop over all the elements of the input list, test
+ ;; each to make sure it is a child of the desired object class.
+ (while (and obj ans)
+ (setq ans (and (eieio-object-p (car obj))
+ (object-of-class-p (car obj) ,cname)))
+ (setq obj (cdr obj)))
+ ans)))))
+
;; When using typep, (typep OBJ 'myclass) returns t for objects which
;; are subclasses of myclass. For our predicates, however, it is
;; important for EIEIO to be backwards compatible, where
(put cname 'variable-documentation
(class-option-assoc options :documentation))
+ ;; Save the file location where this class is defined.
+ (let ((fname (if load-in-progress
+ load-file-name
+ buffer-file-name))
+ loc)
+ (when fname
+ (when (string-match "\\.elc$" fname)
+ (setq fname (substring fname 0 (1- (length fname)))))
+ (put cname 'class-location fname)))
+
;; We have a list of custom groups. Store them into the options.
(let ((g (class-option-assoc options :custom-groups)))
(mapc (lambda (cg) (add-to-list 'g cg)) groups)
(eieio-generic-call-methodname ',method)
(eieio-generic-call-arglst local-args)
)
- (apply #',impl local-args)
- ;;(,impl local-args)
+ ,(if (< emacs-major-version 24)
+ `(apply ,(list 'quote impl) local-args)
+ `(apply #',impl local-args))
+ ;(,impl local-args)
)))))))
(defsubst eieio-defgeneric-reset-generic-form-primary-only-one (method)
((not (get fsym 'protection))
(+ 3 fsi))
((and (eq (get fsym 'protection) 'protected)
- scoped-class
+ (bound-and-true-p scoped-class)
(or (child-of-class-p class scoped-class)
(and (eieio-object-p obj)
(child-of-class-p class (object-class obj)))))
(+ 3 fsi))
((and (eq (get fsym 'protection) 'private)
- (or (and scoped-class
+ (or (and (bound-and-true-p scoped-class)
(eieio-slot-originating-class-p scoped-class slot))
eieio-initializing-object))
(+ 3 fsi))
arguments passed in at the top level.
Use `next-method-p' to find out if there is a next method to call."
- (if (not scoped-class)
+ (if (not (bound-and-true-p scoped-class))
(error "`call-next-method' not called within a class specific method"))
(if (and (/= eieio-generic-call-key method-primary)
(/= eieio-generic-call-key method-static))
(if (< key method-num-lists)
(let ((nsym (intern (symbol-name class) (aref emto key))))
(fset nsym method)))
+ ;; Save the defmethod file location in a symbol property.
+ (let ((fname (if load-in-progress
+ load-file-name
+ buffer-file-name))
+ loc)
+ (when fname
+ (when (string-match "\\.elc$" fname)
+ (setq fname (substring fname 0 (1- (length fname)))))
+ (setq loc (get method-name 'method-locations))
+ (add-to-list 'loc
+ (list class fname))
+ (put method-name 'method-locations loc)))
;; Now optimize the entire obarray
(if (< key method-num-lists)
(let ((eieiomt-optimizing-obarray (aref emto key)))
(princ (make-string (* eieio-print-depth 2) ? ))
(princ "(")
(princ (symbol-name (class-constructor (object-class this))))
- (princ " \"")
- (princ (object-name-string this))
- (princ "\"\n")
+ (princ " ")
+ (prin1 (object-name-string this))
+ (princ "\n")
;; Loop over all the public slots
(let ((publa (aref cv class-public-a))
(publd (aref cv class-public-d))
)
-\f
;;; Obsolete backward compatibility functions.
;; Needed to run byte-code compiled with the EIEIO of Emacs-23.