diff options
Diffstat (limited to 'lisp/cedet/ede')
-rw-r--r-- | lisp/cedet/ede/auto.el | 182 | ||||
-rw-r--r-- | lisp/cedet/ede/autoconf-edit.el | 1 | ||||
-rw-r--r-- | lisp/cedet/ede/base.el | 2 | ||||
-rw-r--r-- | lisp/cedet/ede/config.el | 416 | ||||
-rw-r--r-- | lisp/cedet/ede/cpp-root.el | 110 | ||||
-rw-r--r-- | lisp/cedet/ede/detect.el | 210 | ||||
-rw-r--r-- | lisp/cedet/ede/emacs.el | 66 | ||||
-rw-r--r-- | lisp/cedet/ede/files.el | 322 | ||||
-rw-r--r-- | lisp/cedet/ede/generic.el | 278 | ||||
-rw-r--r-- | lisp/cedet/ede/linux.el | 83 | ||||
-rw-r--r-- | lisp/cedet/ede/pconf.el | 5 | ||||
-rw-r--r-- | lisp/cedet/ede/proj-elisp.el | 3 | ||||
-rw-r--r-- | lisp/cedet/ede/proj.el | 7 | ||||
-rw-r--r-- | lisp/cedet/ede/project-am.el | 10 | ||||
-rw-r--r-- | lisp/cedet/ede/shell.el | 13 |
15 files changed, 1054 insertions, 654 deletions
diff --git a/lisp/cedet/ede/auto.el b/lisp/cedet/ede/auto.el index 337cd77b4e6..63e0504689f 100644 --- a/lisp/cedet/ede/auto.el +++ b/lisp/cedet/ede/auto.el @@ -47,8 +47,13 @@ :initform nil :documentation "An index into the match-data of `configregex'.") - (configdatastash :initform nil - :documentation + (subdir-only :initarg :subdir-only + :initform t + :documentation + "Non-nil means an exact match to the found directory is a non-match. +This implies projects exist only in subdirectories of the configuration path. +If `:subdir-only' is nil, then the directory from the configuration file is the project.") + (configdatastash :documentation "Save discovered match string.") ) "Support complex matches for projects that live in named directories. @@ -80,8 +85,11 @@ into memory.") ;; 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 + (let ((matchstring + (if (slot-boundp dirmatch 'configdatastash) + (oref dirmatch configdatastash) + nil))) + (when (and (not matchstring) (not (slot-boundp dirmatch 'configdatastash))) (save-current-buffer (let* ((buff (get-file-buffer fc)) (readbuff @@ -94,12 +102,27 @@ into memory.") (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)) + (when matchstring + ;; If this dirmatch only finds subdirs of matchstring, then + ;; force matchstring to be a directory. + (when (oref dirmatch subdir-only) + (setq matchstring (file-name-as-directory matchstring))) + ;; Convert matchstring to a regexp + (setq matchstring (concat "^" (regexp-quote matchstring))) + ;; Stash it for later. + (oset dirmatch configdatastash matchstring)) + ;; Debug + ;;(message "Stashing config data for dirmatch %S as %S" (eieio-object-name dirmatch) matchstring) + ) + ;;(message "dirmatch %s against %s" matchstring (expand-file-name file)) ;; Match against our discovered string - (and matchstring (string-match (regexp-quote matchstring) file)) + (setq file (file-name-as-directory (expand-file-name file))) + (and matchstring (string-match matchstring (expand-file-name file)) + (or (not (oref dirmatch subdir-only)) + (not (= (match-end 0) (length file)))) + ) ))) - + ;; Add new matches here ;; ((stringp somenewslot ...) ;; ) @@ -119,13 +142,21 @@ into memory.") :documentation "The lisp file belonging to this class.") (proj-file :initarg :proj-file :documentation "Name of a project file of this type.") + (root-only :initarg :root-only + :initform t ;; Default - majority case. + :documentation + "Non-nil if project detection only finds proj-file @ project root.") (proj-root-dirmatch :initarg :proj-root-dirmatch - :initform "" - :type (or string ede-project-autoload-dirmatch) + :initform nil + :type (or null 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.") +Specifying this matcher object will allow EDE to perform a complex +check without loading the project. + +NOTE: If you use dirmatch, you may need to set :root-only to `nil'. +While it may be a root based project, all subdirs will happen to return +true for the dirmatch, so for scanning purposes, set it to `nil'.") (proj-root :initarg :proj-root :type function :documentation "A function symbol to call for the project root. @@ -168,12 +199,14 @@ type is required and the load function used.") (ede-project-autoload "edeproject-makefile" :name "Make" :file 'ede/proj :proj-file "Project.ede" + :root-only nil :load-type 'ede-proj-load :class-sym 'ede-proj-project :safe-p nil) (ede-project-autoload "edeproject-automake" :name "Automake" :file 'ede/proj :proj-file "Project.ede" + :root-only nil :initializers '(:makefile-type Makefile.am) :load-type 'ede-proj-load :class-sym 'ede-proj-project @@ -181,6 +214,7 @@ type is required and the load function used.") (ede-project-autoload "automake" :name "automake" :file 'ede/project-am :proj-file "Makefile.am" + :root-only nil :load-type 'project-am-load :class-sym 'project-am-makefile :new-p nil @@ -233,97 +267,33 @@ added. Possible values are: ;; Splice into the list. (setcdr prev (cons projauto next)))))))) -;;; EDE project-autoload methods +;;; Project Autoload Methods ;; -(defmethod ede-project-root ((this ede-project-autoload)) - "If a project knows its root, return it here. -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. -Allows for one-project-object-for-a-tree type systems. -Optional FILE is the file to test. If there is no FILE, use -the current buffer." - (when (not file) - (setq file default-directory)) - (when (slot-boundp this :proj-root) - (let ((dirmatch (oref this proj-root-dirmatch)) - (rootfcn (oref this proj-root)) - (callfcn t)) - (when 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 programmatic 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) - "Return a full file name of project THIS found in DIR. -Return nil if the project file does not exist." +;; New method using detect.el +(defmethod ede-auto-detect-in-dir ((this ede-project-autoload) dir) + "Return non-nil if THIS project autoload is found in 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)) - ;; 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))) + (f (when (stringp pf) (expand-file-name pf d)))) + (if f + (and f (file-exists-p f)) + (let ((dirmatch (oref this proj-root-dirmatch))) + (cond + ((stringp dirmatch) + nil) ; <- do something here - maybe obsolete the option? + ((ede-project-autoload-dirmatch-p dirmatch) + (if (and dirmatch (ede-dirmatch-installed dirmatch)) + (ede-do-dirmatch dirmatch dir) + ;(message "Dirmatch %S not installed." dirmatch) + ))))))) (defmethod ede-auto-load-project ((this ede-project-autoload) dir) "Load in the project associated with THIS project autoload description. THIS project description should be valid for DIR, where the project will -be loaded." +be loaded. + +NOTE: Do not call this - it should only be called from `ede-load-project-file'." ;; Last line of defense: don't load unsafe projects. (when (not (or (oref this :safe-p) (ede-directory-safe-p dir))) @@ -332,7 +302,27 @@ be loaded." (let ((o (funcall (oref this load-type) dir))) (when (not o) (error "Project type error: :load-type failed to create a project")) - (ede-add-project-to-global-list o))) + (ede-add-project-to-global-list o) + ;; @TODO - Add to hash over at `ede-inode-directory-hash'. + )) + + + + + + +;;; -------- Old Methods +;; See if we can do without them. + +;; @FIXME - delete from loaddefs to remove this. +(defmethod ede-project-root ((this ede-project-autoload)) + "If a project knows its root, return it here. +Allows for one-project-object-for-a-tree type systems." + nil) + +;; @FIXME - delete from loaddefs to remove this. +(defmethod ede-project-root-directory ((this ede-project-autoload) &optional file) + "" nil) (provide 'ede/auto) diff --git a/lisp/cedet/ede/autoconf-edit.el b/lisp/cedet/ede/autoconf-edit.el index 3ac6949fbb6..0e829def562 100644 --- a/lisp/cedet/ede/autoconf-edit.el +++ b/lisp/cedet/ede/autoconf-edit.el @@ -60,6 +60,7 @@ configure the initial configure script using `autoconf-new-automake-string'" (defvar autoconf-preferred-macro-order '("AC_INIT" + "AC_CONFIG_SRCDIR" "AM_INIT_AUTOMAKE" "AM_CONFIG_HEADER" ;; Arg parsing diff --git a/lisp/cedet/ede/base.el b/lisp/cedet/ede/base.el index 283f9dccac7..4183ff4c61a 100644 --- a/lisp/cedet/ede/base.el +++ b/lisp/cedet/ede/base.el @@ -605,7 +605,7 @@ Display the results as a debug list." "Return the ede project which is the root of the current project. Optional argument SUBPROJ indicates a subproject to start from instead of the current project." - (or ede-object-root-project + (or (when (not subproj) ede-object-root-project) (let* ((cp (or subproj (ede-current-project)))) (or (and cp (ede-project-root cp)) (progn diff --git a/lisp/cedet/ede/config.el b/lisp/cedet/ede/config.el new file mode 100644 index 00000000000..3ac3c06f335 --- /dev/null +++ b/lisp/cedet/ede/config.el @@ -0,0 +1,416 @@ +;;; ede/config.el --- Configuration Handler baseclass + +;; Copyright (C) 2014 Free Software Foundation, Inc. + +;; Author: Eric 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/>. + +;;; Commentary: +;; +;; Some auto-detecting projects (such as the 'generic' project type) +;; can be enhanced by also saving a configuration file that is EDE +;; specific. EDE will be able to load that configuration from the save +;; file as a way of augmenting what is normally already detected. +;; +;; How To Use: +;; +;; Subclass `ede-extra-config', and add the features you want to use. +;; Several mixins are available for adding in C++ or Java support. Bring +;; in the pieces you need. +;; +;; Your project and targets should all have a common baseclass from +;; `ede-project-with-config' or `ede-target-with-config'. When +;; subclassing the project, be sure to override the class allocated +;; slots for the `config-class'. This will tie your new project to +;; the new configuration type. +;; +;; You can also override the file name used to save the configuration +;; object in. +;; +;; If you need to take special action in `project-rescan' be sure to also +;; call `call-next-method' to also get the configuration rescanned. +;; +;; Note on config file safety: +;; +;; Normally an EDE project that loads a save file should have it's +;; autoload slot :safe-p set to nil. Projects who save data via +;; config.el can mark their project as :safe-p t. The config system will +;; do the queries needed to protect the user. This allows a generic +;; project to become active in cases where no save file exists, nor is +;; needed. + +;;; Code: +(require 'ede) + +;;; CONFIG +;; +;; This is the base of a configuration class supported by the +;; `ede-project-with-config' baseclass. +;; +(defclass ede-extra-config (eieio-persistent) + ((extension :initform ".ede") + (file-header-line :initform ";; EDE Project Configuration") + (project :type ede-project-with-config-child + :documentation + "The project this config is bound to.") + (ignored-file :initform nil + :type (or null symbol) + :documentation + "Set to non-nil if this was created and an on-disk file +was ignored. Use this to warn the user that they might want to load in +an on-disk version.") + ) + "Baseclass for auxilliary configuration files for EDE. +This should be subclassed by projects that auto detect a project +and also want to save some extra level of configuration.") + +;;; PROJECT BASECLASS +;; +;; Subclass this baseclass if you want your EDE project to also +;; support saving an extra configuration file of unique data +;; needed for this project. +;; +(defclass ede-project-with-config (ede-project) + ((menu :initform nil) + (config-file-basename + :initform "Config.ede" + :allocation :class + :type string + :documentation + "The filename to use for saving the configuration. +This filename excludes the directory name and is used to +initalize the :file slot of the persistent baseclass.") + (config-class + :initform ede-extra-config + :allocation :class + :type class + :documentation + "The class of the configuration used by this project.") + (config :initform nil + :type (or null ede-extra-config-child) + :documentation + "The configuration object for this project.") + ) + "Baseclass for projects that save a configuration.") + +(defclass ede-target-with-config (ede-target) + () + "Baseclass for targetes of classes that use a config object.") + +;;; Rescanning + +(defmethod project-rescan ((this ede-project-with-config)) + "Rescan this generic project from the sources." + ;; Force the config to be rescanned. + (oset this config nil) + ;; Ask if it is safe to load the config from disk. + (ede-config-get-configuration this t) + ) + +;;; Project Methods for configuration + +(defmethod ede-config-get-configuration ((proj ede-project-with-config) &optional loadask) + "Return the configuration for the project PROJ. +If optional LOADASK is non-nil, then if a project file exists, and if +the directory isn't on the `safe' list, ask to add it to the safe list." + (let ((config (oref proj config))) + + ;; If the request is coming at a time when we want to ask the user, + ;; and there already is a configuration, AND the last time we ignored + ;; the on-file version we did so automatically (without asking) then + ;; in theory there are NO mods to this config, and we should re-ask, + ;; and possibly re-load. + (when (and loadask config (eq (oref config ignored-file) 'auto)) + (setq config nil)) + + (when (not config) + (let* ((top (oref proj :directory)) + (fname (expand-file-name (oref proj config-file-basename) top)) + (class (oref proj config-class)) + (ignore-type nil)) + (if (and (file-exists-p fname) + (or (ede-directory-safe-p top) + ;; Only force the load if someone asked. + (and loadask (ede-check-project-directory top)))) + ;; Load in the configuration + (setq config (eieio-persistent-read fname class)) + ;; If someone said not to load stuff from here then + ;; pop up a warning. + (when (file-exists-p fname) + (message "Ignoring EDE config file for now and creating a new one. Use C-c . g to load it.") + ;; Set how it was ignored. + (if loadask + (setq ignore-type 'manual) + (setq ignore-type 'auto)) + ) + ;; Create a new one. + (setq config (make-instance class + "Configuration" + :file fname)) + (oset config ignored-file ignore-type) + + ;; Set initial values based on project. + (ede-config-setup-configuration proj config)) + ;; Link things together. + (oset proj config config) + (oset config project proj))) + config)) + +(defmethod ede-config-setup-configuration ((proj ede-project-with-config) config) + "Default configuration setup method." + nil) + +(defmethod ede-commit-project ((proj ede-project-with-config)) + "Commit any change to PROJ to its file." + (let ((config (ede-config-get-configuration proj))) + (ede-commit config))) + +;;; Customization +;; +(defmethod ede-customize ((proj ede-project-with-config)) + "Customize the EDE project PROJ by actually configuring the config object." + (let ((config (ede-config-get-configuration proj t))) + (eieio-customize-object config))) + +(defmethod ede-customize ((target ede-target-with-config)) + "Customize the EDE TARGET by actually configuring the config object." + ;; Nothing unique for the targets, use the project. + (ede-customize-project)) + +(defmethod eieio-done-customizing ((config ede-extra-config)) + "Called when EIEIO is done customizing the configuration object. +We need to go back through the old buffers, and update them with +the new configuration." + (ede-commit config) + ;; Loop over all the open buffers, and re-apply. + (ede-map-targets + (oref config project) + (lambda (target) + (ede-map-target-buffers + target + (lambda (b) + (with-current-buffer b + (ede-apply-target-options))))))) + +(defmethod ede-commit ((config ede-extra-config)) + "Commit all changes to the configuration to disk." + ;; So long as the user is trying to safe this config, make sure they can + ;; get at it again later. + (let ((dir (file-name-directory (oref config file)))) + (ede-check-project-directory dir)) + + (eieio-persistent-save config)) + +;;; PROJECT MIXINS +;; +;; These are project part mixins. Use multiple inheritence for each +;; piece of these configuration optiosn you would like to have as part +;; of your project. + +;;; PROGRAM +;; If there is a program that can be run or debugged that is unknown +;; and needs to be configured. +(defclass ede-extra-config-program () + ((debug-command :initarg :debug-command + :initform "gdb " + :type string + :group commands + :custom string + :group (default build) + :documentation + "Command used for debugging this project.") + (run-command :initarg :run-command + :initform "" + :type string + :group commands + :custom string + :group (default build) + :documentation + "Command used to run something related to this project.")) + "Class to mix into a configuration for debug/run of programs.") + +(defclass ede-project-with-config-program () + () + "Class to mix into a project with configuration for programs.") + +(defclass ede-target-with-config-program () + () + "Class to mix into a project with configuration for programs. +This class brings in method overloads for running and debugging +programs from a project.") + +(defmethod project-debug-target ((target ede-target-with-config-program)) + "Run the current project derived from TARGET in a debugger." + (let* ((proj (ede-target-parent target)) + (config (ede-config-get-configuration proj t)) + (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-target-with-config-program)) + "Run the current project derived from TARGET." + (let* ((proj (ede-target-parent target)) + (config (ede-config-get-configuration proj t)) + (run (concat "./" (oref config :run-command))) + (cmd (read-from-minibuffer "Run (like this): " run))) + (ede-shell-run-something target cmd))) + +;;; BUILD +;; If the build style is unknown and needs to be configured. +(defclass ede-extra-config-build () + ((build-command :initarg :build-command + :initform "make -k" + :type string + :group commands + :custom string + :group (default build) + :documentation + "Command used for building this project.")) + "Class to mix into a configuration for compilation.") + +(defclass ede-project-with-config-build () + () + "Class to mix into a project with configuration for builds. +This class brings in method overloads for building.") + +(defclass ede-target-with-config-build () + () + "Class to mix into a project with configuration for builds. +This class brings in method overloads for for building.") + +(defmethod project-compile-project ((proj ede-project-with-config-build) &optional command) + "Compile the entire current project PROJ. +Argument COMMAND is the command to use when compiling." + (let* ((config (ede-config-get-configuration proj t)) + (comp (oref config :build-command))) + (compile comp))) + +(defmethod project-compile-target ((obj ede-target-with-config-build) &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)) + +;;; C / C++ +;; Configure includes and preprocessor symbols for C/C++ needed by +;; Semantic. +(defclass ede-extra-config-c () + ((c-include-path :initarg :c-include-path + :initform nil + :type list + :custom (repeat (string :tag "Path")) + :group c + :documentation + "The include path used by C/C++ projects. +The include path is used when searching for symbols.") + (c-preprocessor-table :initarg :c-preprocessor-table + :initform nil + :type list + :custom (repeat (cons (string :tag "Macro") + (string :tag "Value"))) + :group c + :documentation + "Preprocessor Symbols for this project. +When files within this project are parsed by CEDET, these symbols will be +used to resolve macro occurrences in source fies. +If you modify this slot, you will need to force your source files to be +parsed again.") + (c-preprocessor-files :initarg :c-preprocessor-files + :initform nil + :type list + :group c + :custom (repeat (string :tag "Include File")) + :documentation + "Files parsed and used to populate preprocessor tables. +When files within this project are parsed by CEDET, these symbols will be used to +resolve macro occurences in source files. +If you modify this slot, you will need to force your source files to be +parsed again.")) + "Class to mix into a configuration for compilation.") + +(defclass ede-project-with-config-c () + () + "Class to mix into a project for C/C++ support.") + +(defclass ede-target-with-config-c () + () + "Class to mix into a project for C/C++ support. +This target brings in methods used by Semantic to query +the preprocessor map, and include paths.") + +(defmethod ede-preprocessor-map ((this ede-target-with-config-c)) + "Get the pre-processor map for some generic C code." + (let* ((proj (ede-target-parent this)) + (root (ede-project-root proj)) + (config (ede-config-get-configuration proj)) + filemap + ) + ;; Preprocessor files + (dolist (G (oref config :c-preprocessor-files)) + (let ((table (semanticdb-file-table-object + (ede-expand-filename root G)))) + (when table + (when (semanticdb-needs-refresh-p table) + (semanticdb-refresh-table table)) + (setq filemap (append filemap (oref table lexical-table))) + ))) + ;; The core table + (setq filemap (append filemap (oref config :c-preprocessor-table))) + + filemap + )) + +(defmethod ede-system-include-path ((this ede-target-with-config-c)) + "Get the system include path used by project THIS." + (let* ((proj (ede-target-parent this)) + (config (ede-config-get-configuration proj))) + (oref config c-include-path))) + +;;; Java +;; Configuration needed for programming with Java. +(defclass ede-extra-config-java () + () + "Class to mix into a configuration for compilation.") + +(defclass ede-project-with-config-java () + () + "Class to mix into a project to support java. +This brings in methods to support Semantic querying the +java class path.") + +(defclass ede-target-with-config-java () + () + "Class to mix into a project to support java.") + +(defmethod ede-java-classpath ((proj ede-project-with-config-java)) + "Return the classpath for this project." + (oref (ede-config-get-configuration proj) :classpath)) + +;; Local variables: +;; generated-autoload-file: "loaddefs.el" +;; generated-autoload-load-name: "ede/config" +;; End: + +(provide 'ede/config) + +;;; ede/config.el ends here diff --git a/lisp/cedet/ede/cpp-root.el b/lisp/cedet/ede/cpp-root.el index bf5c8257c90..7ea92364f28 100644 --- a/lisp/cedet/ede/cpp-root.el +++ b/lisp/cedet/ede/cpp-root.el @@ -116,11 +116,6 @@ ;; <write your code here, or return nil> ;; ) ;; -;; (defun MY-ROOT-FCN () -;; "Return the root directory for `default-directory'" -;; ;; You might be able to use `ede-cpp-root-project-root'. -;; ) -;; ;; (defun MY-LOAD (dir) ;; "Load a project of type `cpp-root' for the directory DIR. ;; Return nil if there isn't one." @@ -128,16 +123,14 @@ ;; :locate-fcn 'MYFCN) ;; ) ;; -;; (add-to-list 'ede-project-class-files -;; (ede-project-autoload "cpp-root" +;; (ede-add-project-autoload +;; (ede-project-autoload "cpp-root" ;; :name "CPP ROOT" ;; :file 'ede/cpp-root ;; :proj-file 'MY-FILE-FOR-DIR -;; :proj-root 'MY-ROOT-FCN ;; :load-type 'MY-LOAD ;; :class-sym 'ede-cpp-root-project -;; :safe-p t) -;; t) +;; :safe-p t)) ;; ;;; TODO ;; @@ -168,91 +161,13 @@ ;;; PROJECT CACHE: ;; -;; cpp-root projects are created in a .emacs or other config file, but -;; there still needs to be a way for a particular file to be -;; identified against it. The cache is where we look to map a file -;; against a project. -;; -;; Setting up a simple in-memory cache of active projects allows the -;; user to re-load their configuration file several times without -;; messing up the active project set. +;; cpp-root projects are created in a .emacs or other config file. We +;; need to cache them so if the user re-loads a lisp file with the +;; config in it, we can flush out the old one and replace it. ;; (defvar ede-cpp-root-project-list nil "List of projects created by option `ede-cpp-root-project'.") -(defun ede-cpp-root-file-existing (dir) - "Find a cpp-root project in the list of cpp-root projects. -DIR is the directory to search from." - (let ((projs ede-cpp-root-project-list) - (ans nil)) - (while (and projs (not ans)) - (let ((root (ede-project-root-directory (car projs)))) - (when (string-match (concat "^" (regexp-quote root)) dir) - (setq ans (car projs)))) - (setq projs (cdr projs))) - ans)) - -;;; PROJECT AUTOLOAD CONFIG -;; -;; Each project type registers itself into the project-class list. -;; This way, each time a file is loaded, EDE can map that file to a -;; project. This project type checks files against the internal cache -;; of projects created by the user. -;; -;; EDE asks two kinds of questions. One is, does this DIR belong to a -;; project. If it does, it then asks, what is the ROOT directory to -;; the project in DIR. This is easy for cpp-root projects, but more -;; complex for multiply nested projects. -;; -;; If EDE finds out that a project exists for DIR, it then loads that -;; project. The LOAD routine can either create a new project object -;; (if it needs to load it off disk) or more likely can return an -;; existing object for the discovered directory. cpp-root always uses -;; the second case. - -(defun ede-cpp-root-project-file-for-dir (&optional dir) - "Return a full file name to the project file stored in DIR." - (let ((proj (ede-cpp-root-file-existing dir))) - (when proj (oref proj :file)))) - -(defvar ede-cpp-root-count 0 - "Count number of hits to the cpp root thing. -This is a debugging variable to test various optimizations in file -lookup in the main EDE logic.") - -;;;###autoload -(defun ede-cpp-root-project-root (&optional dir) - "Get the root directory for DIR." - (let ((projfile (ede-cpp-root-project-file-for-dir - (or dir default-directory)))) - (setq ede-cpp-root-count (1+ ede-cpp-root-count)) - ;(debug) - (when projfile - (file-name-directory projfile)))) - -(defun ede-cpp-root-load (dir &optional rootproj) - "Return a CPP root object if you created one. -Return nil if there isn't one. -Argument DIR is the directory it is created for. -ROOTPROJ is nil, since there is only one project." - ;; Snoop through our master list. - (ede-cpp-root-file-existing dir)) - -;;;###autoload -(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-project - :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 ;; @@ -372,6 +287,7 @@ Each directory needs a project file to control it.") :directory 'ede-cpp-root-project-list))) ;; This is safe, because :directory isn't filled in till later. (when (and old (not (eq old this))) + (ede-delete-project-from-global-list old) (delete-instance old))) ;; Basic initialization. (when (or (not (file-exists-p f)) @@ -381,11 +297,13 @@ Each directory needs a project file to control it.") (oset this :file f) (oset this :directory (file-name-directory f)) (ede-project-directory-remove-hash (file-name-directory f)) + ;; NOTE: We must add to global list here because these classes are not + ;; created via the typial loader, but instead via calls from a .emacs + ;; file. (ede-add-project-to-global-list this) + (unless (slot-boundp this 'targets) (oset this :targets nil)) - ;; We need to add ourselves to the master list. - ;;(setq ede-projects (cons this ede-projects)) )) ;;; SUBPROJ Management. @@ -465,7 +383,7 @@ This knows details about or source tree." (defmethod ede-project-root-directory ((this ede-cpp-root-project)) "Return my root." - (file-name-directory (oref this file))) + (oref this directory)) ;;; C/CPP SPECIFIC CODE ;; @@ -558,6 +476,10 @@ Argument COMMAND is the command to use for compiling the target." (project-compile-project (oref obj :project) command))) +(defmethod project-rescan ((this ede-cpp-root-project)) + "Don't rescan this project from the sources." + (message "cpp-root has nothing to rescan.")) + ;;; Quick Hack (defun ede-create-lots-of-projects-under-dir (dir projfile &rest attributes) "Create a bunch of projects under directory DIR. diff --git a/lisp/cedet/ede/detect.el b/lisp/cedet/ede/detect.el new file mode 100644 index 00000000000..2b329185c84 --- /dev/null +++ b/lisp/cedet/ede/detect.el @@ -0,0 +1,210 @@ +;;; ede/detect.el --- EDE project detection and file associations + +;; Copyright (C) 2014 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/>. + +;;; Commentary: +;; +;; Project detection for EDE; +;; +;; Detection comes in multiple forms: +;; +;; `ede-detect-scan-directory-for-project' - +;; Scan for a project via the file system. +;; `ede-detect-directory-for-project' - +;; Check our file cache for a project. If that failes, use +;; the scan fcn above. + +;;; Code: + +(require 'ede/auto) ;; Autoload settings. + +(when (or (<= emacs-major-version 23) + ;; predicate as name added in Emacs 24.2 + (and (= emacs-major-version 24) + (< emacs-minor-version 2))) + (message "Loading CEDET fallback autoload library.") + (require 'cedet/dominate + (expand-file-name "../../../etc/fallback-libraries/dominate.el" + (file-name-directory load-file-name)))) + + +;;; BASIC PROJECT SCAN +;; +(defun ede--detect-stop-scan-p (dir) + "Return non-nil if we need to stop scanning upward in DIR." + ;;(let ((stop + (file-exists-p (expand-file-name ".ede_stop_scan" dir))) +;;) +;;(when stop +;;(message "Stop Scan at %s" dir)) +;;stop)) + +(defvar ede--detect-found-project nil + "When searching for a project, temporarilly save that file.") + +(defun ede--detect-ldf-predicate (dir) + "Non-nil if DIR contain any known EDE project types." + (if (ede--detect-stop-scan-p dir) + (throw 'stopscan nil) + (let ((types ede-project-class-files)) + ;; Loop over all types, loading in the first type that we find. + (while (and types (not ede--detect-found-project)) + (if (ede-auto-detect-in-dir (car types) dir) + (progn + ;; We found one! + (setq ede--detect-found-project (car types))) + (setq types (cdr types))) + ) + ede--detect-found-project))) + +(defun ede--detect-scan-directory-for-project (directory) + "Detect an EDE project for the current DIRECTORY by scanning. +This function ALWAYS scans files and directories and DOES NOT +use any file caches. +Return a cons cell: + ( ROOTDIR . PROJECT-AUTOLOAD)" + (let* ((ede--detect-found-project nil) + (root + (catch 'stopscan + (locate-dominating-file directory + 'ede--detect-ldf-predicate)))) + (when root + (cons root ede--detect-found-project)))) + +;;; Root Only project detect +;; +;; For projects that only have a detectible ROOT file, but may in fact +;; contain a generic file such as a Makefile, we need to do a second scan +;; to make sure we don't miss-match. +(defun ede--detect-ldf-rootonly-predicate (dir) + "Non-nil if DIR contain any known EDE project types." + (if (ede--detect-stop-scan-p dir) + (throw 'stopscan nil) + (let ((types ede-project-class-files)) + ;; Loop over all types, loading in the first type that we find. + (while (and types (not ede--detect-found-project)) + (if (and + (oref (car types) root-only) + (ede-auto-detect-in-dir (car types) dir)) + (progn + ;; We found one! + (setq ede--detect-found-project (car types))) + (setq types (cdr types))) + ) + ede--detect-found-project))) + +(defun ede--detect-scan-directory-for-rootonly-project (directory) + "Detect an EDE project for the current DIRECTORY by scanning. +This function ALWAYS scans files and directories and DOES NOT +use any file caches. +Return a cons cell: + ( ROOTDIR . PROJECT-AUTOLOAD)" + (let* ((ede--detect-found-project nil) + (root + (catch 'stopscan + (locate-dominating-file directory + 'ede--detect-ldf-rootonly-predicate)))) + (when root + (cons root ede--detect-found-project)))) + + +;;; NESTED PROJECT SCAN +;; +;; For projects that can have their dominating file exist in all their +;; sub-directories as well. + +(defvar ede--detect-nomatch-auto nil + "An ede autoload that needs to be un-matched.") + +(defun ede--detect-ldf-root-predicate (dir) + "Non-nil if DIR no longer match `ede--detect-nomatch-auto'." + (or (ede--detect-stop-scan-p dir) + ;; To know if DIR is at the top, we need to look just above + ;; to see if there is a match. + (let ((updir (file-name-directory (directory-file-name dir)))) + (if (equal updir dir) + ;; If it didn't change, then obviously this must be the top. + t + ;; If it is different, check updir for the file. + (not (ede-auto-detect-in-dir ede--detect-nomatch-auto updir)))))) + +(defun ede--detect-scan-directory-for-project-root (directory auto) + "If DIRECTORY has already been detected with AUTO, find the root. +Some projects have their dominating file in all their directories, such +as Project.ede. In that case we will detect quickly, but then need +to scan upward to find the topmost occurance of that file." + (let* ((ede--detect-nomatch-auto auto) + (root (locate-dominating-file directory + 'ede--detect-ldf-root-predicate))) + root)) + +;;; TOP LEVEL SCAN +;; +;; This function for combining the above scans. +(defun ede-detect-directory-for-project (directory) + "Detect an EDE project for the current DIRECTORY. +Scan the filesystem for a project. +Return a cons cell: + ( ROOTDIR . PROJECT-AUTOLOAD)" + (let* ((scan (ede--detect-scan-directory-for-project directory)) + (root (car scan)) + (auto (cdr scan))) + (when scan + ;; If what we found is already a root-only project, return it. + (if (oref auto root-only) + scan + + ;; If what we found is a generic project, check to make sure we aren't + ;; in some other kind of root project. + (if (oref auto generic-p) + (let ((moreroot (ede--detect-scan-directory-for-rootonly-project root))) + ;; If we found a rootier project, return that. + (if moreroot + moreroot + + ;; If we didn't find a root from the generic project, then + ;; we need to rescan upward. + (cons (ede--detect-scan-directory-for-project-root root auto) auto))) + + ;; Non-generic non-root projects also need to rescan upward. + (cons (ede--detect-scan-directory-for-project-root root auto) auto))) + + ))) + +;;; TEST +;; +;; A quick interactive testing fcn. +(defun ede-detect-qtest () + "Run a quick test for autodetecting on BUFFER." + (interactive) + (let ((start (current-time)) + (ans (ede-detect-directory-for-project default-directory)) + (end (current-time))) + (if ans + (message "Project found in %d sec @ %s of type %s" + (float-time (time-subtract end start)) + (car ans) + (eieio-object-name-string (cdr ans))) + (message "No Project found.") ))) + + +(provide 'ede/detect) + +;;; ede/detect.el ends here diff --git a/lisp/cedet/ede/emacs.el b/lisp/cedet/ede/emacs.el index 76925a66713..88df1d2963f 100644 --- a/lisp/cedet/ede/emacs.el +++ b/lisp/cedet/ede/emacs.el @@ -38,37 +38,12 @@ (declare-function semanticdb-refresh-table "semantic/db") ;;; Code: -(defvar ede-emacs-project-list nil - "List of projects created by option `ede-emacs-project'.") - -(defun ede-emacs-file-existing (dir) - "Find a Emacs project in the list of Emacs projects. -DIR is the directory to search from." - (let ((projs ede-emacs-project-list) - (ans nil)) - (while (and projs (not ans)) - (let ((root (ede-project-root-directory (car projs)))) - (when (string-match (concat "^" (regexp-quote root)) - (file-name-as-directory dir)) - (setq ans (car projs)))) - (setq projs (cdr projs))) - ans)) -;;;###autoload +;; @TODO - get rid of this. Stuck in loaddefs right now. + (defun ede-emacs-project-root (&optional dir) "Get the root directory for DIR." - (when (not dir) (setq dir default-directory)) - (let ((case-fold-search t) - (proj (ede-files-find-existing dir ede-emacs-project-list))) - (if proj - (ede-up-directory (file-name-directory - (oref proj :file))) - ;; No pre-existing project. Let's take a wild-guess if we have - ;; an Emacs project here. - (when (string-match "emacs[^/]*" dir) - (let ((base (substring dir 0 (match-end 0)))) - (when (file-exists-p (expand-file-name "src/emacs.c" base)) - base)))))) + nil) (defun ede-emacs-version (dir) "Find the Emacs version for the Emacs src in DIR. @@ -118,8 +93,8 @@ m4_define(\\[SXEM4CS_BETA_VERSION\\], \\[\\([0-9]+\\)\\])") ;; Return a tuple (cons emacs ver)))) -(defclass ede-emacs-project (ede-project eieio-instance-tracker) - ((tracking-symbol :initform 'ede-emacs-project-list) +(defclass ede-emacs-project (ede-project) + ( ) "Project Type for the Emacs source code." :method-invocation-order :depth-first) @@ -129,17 +104,15 @@ m4_define(\\[SXEM4CS_BETA_VERSION\\], \\[\\([0-9]+\\)\\])") Return nil if there isn't one. Argument DIR is the directory it is created for. ROOTPROJ is nil, since there is only one project." - (or (ede-files-find-existing dir ede-emacs-project-list) - ;; Doesn't already exist, so let's make one. - (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)))) + ;; 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)))) ;;;###autoload (ede-add-project-autoload @@ -147,8 +120,6 @@ ROOTPROJ is nil, since there is only one project." :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 @@ -302,6 +273,15 @@ Knows about how the Emacs source tree is organized." (ede-emacs-find-in-directories name dir dirs)) )) +;;; Command Support +;; +(defmethod project-rescan ((this ede-emacs-project)) + "Rescan this Emacs project from the sources." + (let ((ver (ede-emacs-version (ede-project-root-directory this)))) + (oset this name (car ver)) + (oset this version (cdr ver)) + )) + (provide 'ede/emacs) ;; Local variables: diff --git a/lisp/cedet/ede/files.el b/lisp/cedet/ede/files.el index ac245cf61bd..1a97bfc4a5d 100644 --- a/lisp/cedet/ede/files.el +++ b/lisp/cedet/ede/files.el @@ -80,46 +80,15 @@ Allows for one-project-object-for-a-tree type systems." Allows for one-project-object-for-a-tree type systems. Optional FILE is the file to test. It is ignored in preference of the anchor file for the project." - (file-name-directory (expand-file-name (oref this file)))) + (let ((root (or (ede-project-root this) this))) + (file-name-directory (expand-file-name (oref this file))))) -(defmethod ede--project-inode ((proj ede-project-placeholder)) - "Get the inode of the directory project PROJ is in." - (if (slot-boundp proj 'dirinode) - (oref proj dirinode) - (oset proj dirinode (ede--inode-for-dir (oref proj :directory))))) - -(defmethod ede-find-subproject-for-directory ((proj ede-project-placeholder) - dir) - "Find a subproject of PROJ that corresponds to DIR." - (if ede--disable-inode - (let ((ans nil)) - ;; Try to find the right project w/out inodes. - (ede-map-subprojects - proj - (lambda (SP) - (when (not ans) - (if (string= (file-truename dir) (oref SP :directory)) - (setq ans SP) - (ede-find-subproject-for-directory SP dir))))) - ans) - ;; We can use inodes, so let's try it. - (let ((ans nil) - (inode (ede--inode-for-dir dir))) - (ede-map-subprojects - proj - (lambda (SP) - (when (not ans) - (if (equal (ede--project-inode SP) inode) - (setq ans SP) - (setq ans (ede-find-subproject-for-directory SP dir)))))) - ans))) +;; Why INODEs? +;; An inode represents is a unique id that trancends symlinks, hardlinks, etc +;; so when we cache an inode in a project, and hash directories to inodes, we +;; can avoid costly filesystem queries and regex matches. -;;; DIRECTORY IN OPEN PROJECT -;; -;; These routines match some directory name to one of the many pre-existing -;; open projects. This should avoid hitting the disk, or asking lots of questions -;; if used throughout the other routines. (defvar ede-inode-directory-hash (make-hash-table ;; Note on test. Can we compare inodes or something? :test 'equal) @@ -147,6 +116,32 @@ of the anchor file for the project." (ede--put-inode-dir-hash dir (nth 10 fattr)) ))))) +(defmethod ede--project-inode ((proj ede-project-placeholder)) + "Get the inode of the directory project PROJ is in." + (if (slot-boundp proj 'dirinode) + (oref proj dirinode) + (oset proj dirinode (ede--inode-for-dir (oref proj :directory))))) + +(defun ede--inode-get-toplevel-open-project (inode) + "Return an already open toplevel project that is managing INODE. +Does not check subprojects." + (when (or (and (numberp inode) (/= inode 0)) + (consp inode)) + (let ((all ede-projects) + (found nil) + ) + (while (and all (not found)) + (when (equal inode (ede--project-inode (car all))) + (setq found (car all))) + (setq all (cdr all))) + found))) + +;;; DIRECTORY IN OPEN PROJECT +;; +;; These routines match some directory name to one of the many pre-existing +;; open projects. This should avoid hitting the disk, or asking lots of questions +;; if used throughout the other routines. + (defun ede-directory-get-open-project (dir &optional rootreturn) "Return an already open project that is managing DIR. Optional ROOTRETURN specifies a symbol to set to the root project. @@ -156,66 +151,105 @@ If DIR is the root project, then it is the same." (proj (ede--inode-get-toplevel-open-project inode)) (ans nil)) ;; Try file based search. - (when (not proj) + (when (or ede--disable-inode (not proj)) (setq proj (ede-directory-get-toplevel-open-project ft))) ;; Default answer is this project (setq ans proj) ;; Save. (when rootreturn (set rootreturn proj)) ;; Find subprojects. - (when (and proj (or ede--disable-inode - (not (equal inode (ede--project-inode proj))))) + (when (and proj (if ede--disable-inode + (not (string= ft (expand-file-name (oref proj :directory)))) + (not (equal inode (ede--project-inode proj))))) (setq ans (ede-find-subproject-for-directory proj ft))) ans)) -(defun ede--inode-get-toplevel-open-project (inode) - "Return an already open toplevel project that is managing INODE. -Does not check subprojects." - (when (or (and (numberp inode) (/= inode 0)) - (consp inode)) - (let ((all ede-projects) - (found nil) - ) - (while (and all (not found)) - (when (equal inode (ede--project-inode (car all))) - (setq found (car all))) - (setq all (cdr all))) - found))) - -(defun ede-directory-get-toplevel-open-project (dir) - "Return an already open toplevel project that is managing DIR." +;; Force all users to switch to `ede-directory-get-open-project' +;; for performance reasons. +(defun ede-directory-get-toplevel-open-project (dir &optional exact) + "Return an already open toplevel project that is managing DIR. +If optional EXACT is non-nil, only return exact matches for DIR." (let ((ft (file-name-as-directory (expand-file-name dir))) (all ede-projects) - (ans nil)) + (ans nil) + (shortans nil)) (while (and all (not ans)) ;; Do the check. - (let ((pd (oref (car all) :directory)) + (let ((pd (expand-file-name (oref (car all) :directory))) ) (cond ;; Exact text match. ((string= pd ft) (setq ans (car all))) ;; Some sub-directory - ((string-match (concat "^" (regexp-quote pd)) ft) - (setq ans (car all))) + ((and (not exact) (string-match (concat "^" (regexp-quote pd)) ft)) + (if (not shortans) + (setq shortans (car all)) + ;; We already have a short answer, so see if pd (the match we found) + ;; is longer. If it is longer, then it is more precise. + (when (< (length (oref shortans :directory)) + (length pd)) + (setq shortans (car all)))) + ) ;; Exact inode match. Useful with symlinks or complex automounters. - ((let ((pin (ede--project-inode (car all))) - (inode (ede--inode-for-dir dir))) - (and (not (eql pin 0)) (equal pin inode))) - (setq ans (car all))) + ((and (not ede--disable-inode) + (let ((pin (ede--project-inode (car all))) + (inode (ede--inode-for-dir dir))) + (and (not (eql pin 0)) (equal pin inode)))) + (setq ans (car all))) ;; Subdir via truename - slower by far, but faster than a traditional lookup. - ((let ((ftn (file-truename ft)) - (ptd (file-truename (oref (car all) :directory)))) - (string-match (concat "^" (regexp-quote ptd)) ftn)) - (setq ans (car all))) - )) + ;; Note that we must resort to truename in order to resolve issues such as + ;; cross-symlink projects. + ((and (not exact) + (let ((ftn (file-truename ft)) + (ptd (file-truename pd))) + (string-match (concat "^" (regexp-quote ptd)) ftn))) + (if (not shortans) + (setq shortans (car all)) + ;; We already have a short answer, so see if pd (the match we found) + ;; is longer. If it is longer, then it is more precise. + (when (< (length (expand-file-name (oref shortans :directory))) + (length pd)) + (setq shortans (car all)))) + ))) (setq all (cdr all))) - ans)) + ;; If we have an exact answer, use that, otherwise use + ;; the short answer we found -> ie - we are in a subproject. + (or ans shortans))) + +(defmethod ede-find-subproject-for-directory ((proj ede-project-placeholder) + dir) + "Find a subproject of PROJ that corresponds to DIR." + (if ede--disable-inode + (let ((ans nil) + (fulldir (file-truename dir))) + ;; Try to find the right project w/out inodes. + (ede-map-subprojects + proj + (lambda (SP) + (when (not ans) + (if (string= fulldir (file-truename (oref SP :directory))) + (setq ans SP) + (ede-find-subproject-for-directory SP dir))))) + ans) + ;; We can use inodes, so let's try it. + (let ((ans nil) + (inode (ede--inode-for-dir dir))) + (ede-map-subprojects + proj + (lambda (SP) + (when (not ans) + (if (equal (ede--project-inode SP) inode) + (setq ans SP) + (setq ans (ede-find-subproject-for-directory SP dir)))))) + ans))) -;;; DIRECTORY-PROJECT-P +;;; DIRECTORY HASH ;; -;; For a fresh buffer, or for a path w/ no open buffer, use this -;; routine to determine if there is a known project type here. +;; The directory hash matches expanded directory names to already detected +;; projects. By hashing projects to directories, we can detect projects in +;; places we have been before much more quickly. + (defvar ede-project-directory-hash (make-hash-table ;; Note on test. Can we compare inodes or something? :test 'equal) @@ -237,7 +271,7 @@ Do this only when developing new projects that are incorrectly putting "Reset the directory hash for DIR. Do this whenever a new project is created, as opposed to loaded." ;; TODO - Use maphash, and delete by regexp, not by dir searching! - + (setq dir (expand-file-name dir)) (when (fboundp 'remhash) (remhash (file-name-as-directory dir) ede-project-directory-hash) ;; Look for all subdirs of D, and remove them. @@ -248,98 +282,95 @@ Do this whenever a new project is created, as opposed to loaded." ede-project-directory-hash)) )) -(defun ede-directory-project-from-hash (dir) +(defun ede--directory-project-from-hash (dir) "If there is an already loaded project for DIR, return it from the hash." (when (fboundp 'gethash) + (setq dir (expand-file-name dir)) (gethash dir ede-project-directory-hash nil))) -(defun ede-directory-project-add-description-to-hash (dir desc) +(defun ede--directory-project-add-description-to-hash (dir desc) "Add to the EDE project hash DIR associated with DESC." (when (fboundp 'puthash) + (setq dir (expand-file-name dir)) (puthash dir desc ede-project-directory-hash) desc)) +;;; DIRECTORY-PROJECT-P, -CONS +;; +;; These routines are useful for detecting if a project exists +;; in a provided directory. +;; +;; Note that -P provides less information than -CONS, so use -CONS +;; instead so that -P can be obsoleted. (defun ede-directory-project-p (dir &optional force) - "Return a project description object if DIR has a project. + "Return a project description object if DIR is in a project. Optional argument FORCE means to ignore a hash-hit of 'nomatch. This depends on an up to date `ede-project-class-files' variable. Any directory that contains the file .ede-ignore will always -return nil." +return nil. + +Consider using `ede-directory-project-cons' instead if the next +question you want to ask is where the root of found project is." + ;; @TODO - We used to have a full impl here, but moved it all + ;; to ede-directory-project-cons, and now hash contains only + ;; the results of detection which includes the root dir. + ;; Perhaps we can eventually remove this fcn? + (let ((detect (ede-directory-project-cons dir force))) + (cdr detect))) + +(defun ede-directory-project-cons (dir &optional force) + "Return a project CONS (ROOTDIR . AUTOLOAD) for DIR. +If there is no project in DIR, return nil. +Optional FORCE means to ignore the hash of known directories." (when (not (file-exists-p (expand-file-name ".ede-ignore" dir))) (let* ((dirtest (expand-file-name dir)) - (match (ede-directory-project-from-hash dirtest))) + (match (ede--directory-project-from-hash dirtest))) (cond ((and (eq match 'nomatch) (not force)) nil) ((and match (not (eq match 'nomatch))) match) (t - (let ((types ede-project-class-files) - (ret nil)) - ;; Loop over all types, loading in the first type that we find. - (while (and types (not ret)) - (if (ede-dir-to-projectfile (car types) dirtest) - (progn - ;; We found one! Require it now since we will need it. - (require (oref (car types) file)) - (setq ret (car types)))) - (setq types (cdr types))) - (ede-directory-project-add-description-to-hash dirtest (or ret 'nomatch)) - ret)))))) + ;; First time here? Use the detection code to identify if we have + ;; a project here. + (let* ((detect (ede-detect-directory-for-project dirtest)) + (autoloader (cdr detect))) ;; autoloader + (when autoloader (require (oref autoloader file))) + (ede--directory-project-add-description-to-hash dirtest (or detect 'nomatch)) + detect) + ))))) + ;;; TOPLEVEL ;; ;; These utilities will identify the "toplevel" of a project. ;; -(defun ede-toplevel-project-or-nil (dir) - "Starting with DIR, find the toplevel project directory, or return nil. -nil is returned if the current directory is not a part of a project." - (let* ((ans (ede-directory-get-toplevel-open-project dir))) - (if ans - (oref ans :directory) - (if (ede-directory-project-p dir) - (ede-toplevel-project dir) - nil)))) +;; NOTE: These two -toplevel- functions return a directory even though +;; the function name implies a project. (defun ede-toplevel-project (dir) - "Starting with DIR, find the toplevel project directory." - (if (and (string= dir default-directory) + "Starting with DIR, find the toplevel project directory. +If DIR is not part of a project, return nil." + (let ((ans nil)) + + (cond + ;; Check if it is cached in the current buffer. + ((and (string= dir default-directory) ede-object-root-project) ;; Try the local buffer cache first. - (oref ede-object-root-project :directory) - ;; Otherwise do it the hard way. - (let* ((thisdir (ede-directory-project-p dir)) - (ans (ede-directory-get-toplevel-open-project dir))) - (if (and ans ;; We have an answer - (or (not thisdir) ;; this dir isn't setup - (and (object-of-class-p ;; Same as class for this dir? - ans (oref thisdir :class-sym))) - )) - (oref ans :directory) - (let* ((toppath (expand-file-name dir)) - (newpath toppath) - (proj (ede-directory-project-p dir)) - (ans nil)) - (if proj - ;; If we already have a project, ask it what the root is. - (setq ans (ede-project-root-directory proj))) - - ;; If PROJ didn't know, or there is no PROJ, then - - ;; Loop up to the topmost project, and then load that single - ;; project, and its sub projects. When we are done, identify the - ;; sub-project object belonging to file. - (while (and (not ans) newpath proj) - (setq toppath newpath - newpath (ede-up-directory toppath)) - (when newpath - (setq proj (ede-directory-project-p newpath))) - - (when proj - ;; We can home someone in the middle knows too. - (setq ans (ede-project-root-directory proj))) - ) - (or ans toppath)))))) + (oref ede-object-root-project :directory)) + + ;; See if there is an existing project in DIR. + ((setq ans (ede-directory-get-toplevel-open-project dir)) + (oref ans :directory)) + + ;; Detect using our file system detector. + ((setq ans (ede-detect-directory-for-project dir)) + (car ans)) + + (t nil)))) + +(defalias 'ede-toplevel-project-or-nil 'ede-toplevel-project) ;;; DIRECTORY CONVERSION STUFF ;; @@ -509,25 +540,6 @@ Argument DIR is the directory to trim upwards." nil fnd))) -(defun ede-find-project-root (prj-file-name &optional dir) - "Tries to find directory with given project file" - (let ((prj-dir (locate-dominating-file (or dir default-directory) - prj-file-name))) - (when prj-dir - (expand-file-name prj-dir)))) - -(defun ede-files-find-existing (dir prj-list) - "Find a project in the list of projects stored in given variable. -DIR is the directory to search from." - (let ((projs prj-list) - (ans nil)) - (while (and projs (not ans)) - (let ((root (ede-project-root-directory (car projs)))) - (when (string-match (concat "^" (regexp-quote root)) dir) - (setq ans (car projs)))) - (setq projs (cdr projs))) - ans)) - (provide 'ede/files) diff --git a/lisp/cedet/ede/generic.el b/lisp/cedet/ede/generic.el index d6f0385cf97..f0314cb7f22 100644 --- a/lisp/cedet/ede/generic.el +++ b/lisp/cedet/ede/generic.el @@ -78,61 +78,18 @@ ;; the above described support features. (require 'eieio-opt) -(require 'ede) +(require 'ede/config) (require 'ede/shell) (require 'semantic/db) ;;; Code: ;; ;; Start with the configuration system -(defclass ede-generic-config (eieio-persistent) - ((extension :initform ".ede") - (file-header-line :initform ";; EDE Generic Project Configuration") - (project :initform nil - :documentation - "The project this config is bound to.") - ;; Generic customizations - (build-command :initarg :build-command - :initform "make -k" - :type string - :custom string - :group (default build) - :documentation - "Command used for building this project.") - (debug-command :initarg :debug-command - :initform "gdb " - :type string - :custom string - :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 - :type list - :custom (repeat (string :tag "Path")) - :group c - :documentation - "The include path used by C/C++ projects.") - (c-preprocessor-table :initarg :c-preprocessor-table - :initform nil - :type list - :custom (repeat (cons (string :tag "Macro") - (string :tag "Value"))) - :group c - :documentation - "Preprocessor Symbols for this project.") - (c-preprocessor-files :initarg :c-preprocessor-files - :initform nil - :type list - :custom (repeat (string :tag "Include File"))) +(defclass ede-generic-config (ede-extra-config + ede-extra-config-build + ede-extra-config-program + ede-extra-config-c) + ((file-header-line :initform ";; EDE Generic Project Configuration") ) "User Configuration object for a generic project.") @@ -142,23 +99,24 @@ Return nil if there isn't one. Argument DIR is the directory it is created for. ROOTPROJ is nil, since there is only one project." ;; Doesn't already exist, so let's make one. - (let* ((alobj ede-constructing) - (this nil)) + (let* ((alobj ede-constructing)) (when (not alobj) (error "Cannot load generic project without the autoload instance")) - - (setq this - (funcall (oref alobj class-sym) - (symbol-name (oref alobj class-sym)) - :name (file-name-nondirectory - (directory-file-name dir)) - :version "1.0" - :directory (file-name-as-directory dir) - :file (expand-file-name (oref alobj :proj-file)) )) - (ede-add-project-to-global-list this) + ;;; + ;; TODO - find the root dir. + (let ((rootdir dir)) + (funcall (oref alobj class-sym) + (symbol-name (oref alobj class-sym)) + :name (file-name-nondirectory (directory-file-name dir)) + :version "1.0" + :directory (file-name-as-directory rootdir) + :file (expand-file-name (oref alobj :proj-file) + rootdir))) )) ;;; Base Classes for the system -(defclass ede-generic-target (ede-target) +(defclass ede-generic-target (ede-target-with-config + ede-target-with-config-build + ede-target-with-config-program) ((shortname :initform "" :type string :allocation :class @@ -174,16 +132,18 @@ subclasses of this base target will override the default value.") "Baseclass for all targets belonging to the generic ede system." :abstract t) -(defclass ede-generic-project (ede-project) - ((buildfile :initform "" +(defclass ede-generic-project (ede-project-with-config + ede-project-with-config-build + ede-project-with-config-program + ede-project-with-config-c + ede-project-with-config-java) + ((config-class :initform ede-generic-config) + (config-file-basename :initform "EDEConfig.el") + (buildfile :initform "" :type string :allocation :class :documentation "The file name that identifies a project of this type. The class allocated value is replace by different sub classes.") - (config :initform nil - :type (or null ede-generic-config) - :documentation - "The configuration object for this project.") ) "The baseclass for all generic EDE project types." :abstract t) @@ -196,37 +156,18 @@ The class allocated value is replace by different sub classes.") (oset this :targets nil)) ) -(defmethod ede-generic-get-configuration ((proj ede-generic-project)) - "Return the configuration for the project PROJ." - (let ((config (oref proj config))) - (when (not config) - (let ((fname (expand-file-name "EDEConfig.el" - (oref proj :directory)))) - (if (file-exists-p fname) - ;; Load in the configuration - (setq config (eieio-persistent-read fname 'ede-generic-config)) - ;; Create a new one. - (setq config (ede-generic-config - "Configuration" - :file fname)) - ;; Set initial values based on project. - (ede-generic-setup-configuration proj config)) - ;; Link things together. - (oset proj config config) - (oset config project proj))) - config)) - -(defmethod ede-generic-setup-configuration ((proj ede-generic-project) config) - "Default configuration setup method." - nil) - -(defmethod ede-commit-project ((proj ede-generic-project)) - "Commit any change to PROJ to its file." - (let ((config (ede-generic-get-configuration proj))) - (ede-commit config))) +(defmethod ede-project-root ((this ede-generic-project)) + "Return my root." + this) + +(defmethod ede-find-subproject-for-directory ((proj ede-generic-project) + dir) + "Return PROJ, for handling all subdirs below DIR." + proj) ;;; A list of different targets -(defclass ede-generic-target-c-cpp (ede-generic-target) +(defclass ede-generic-target-c-cpp (ede-generic-target + ede-target-with-config-c) ((shortname :initform "C/C++") (extension :initform "\\([ch]\\(pp\\|xx\\|\\+\\+\\)?\\|cc\\|hh\\|CC?\\)")) "EDE Generic Project target for C and C++ code. @@ -250,6 +191,13 @@ All directories need at least one target.") "EDE Generic Project target for texinfo code. All directories need at least one target.") +(defclass ede-generic-target-java (ede-generic-target + ede-target-with-config-java) + ((shortname :initform "Java") + (extension :initform "java")) + "EDE Generic Project target for texinfo code. +All directories need at least one target.") + ;; MISC must always be last since it will always match the file. (defclass ede-generic-target-misc (ede-generic-target) ((shortname :initform "Misc") @@ -300,103 +248,6 @@ If one doesn't exist, create a new one for this directory." ) ans)) -;;; C/C++ support -(defmethod ede-preprocessor-map ((this ede-generic-target-c-cpp)) - "Get the pre-processor map for some generic C code." - (let* ((proj (ede-target-parent this)) - (root (ede-project-root proj)) - (config (ede-generic-get-configuration proj)) - filemap - ) - ;; Preprocessor files - (dolist (G (oref config :c-preprocessor-files)) - (let ((table (semanticdb-file-table-object - (ede-expand-filename root G)))) - (when table - (when (semanticdb-needs-refresh-p table) - (semanticdb-refresh-table table)) - (setq filemap (append filemap (oref table lexical-table))) - ))) - ;; The core table - (setq filemap (append filemap (oref config :c-preprocessor-table))) - - filemap - )) - -(defmethod ede-system-include-path ((this ede-generic-target-c-cpp)) - "Get the system include path used by project THIS." - (let* ((proj (ede-target-parent this)) - (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." - (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)) - "Customize the EDE project PROJ." - (let ((config (ede-generic-get-configuration proj))) - (eieio-customize-object config))) - -(defmethod ede-customize ((target ede-generic-target)) - "Customize the EDE TARGET." - ;; Nothing unique for the targets, use the project. - (ede-customize-project)) - -(defmethod eieio-done-customizing ((config ede-generic-config)) - "Called when EIEIO is done customizing the configuration object. -We need to go back through the old buffers, and update them with -the new configuration." - (ede-commit config) - ;; Loop over all the open buffers, and re-apply. - (ede-map-targets - (oref config project) - (lambda (target) - (ede-map-target-buffers - target - (lambda (b) - (with-current-buffer b - (ede-apply-target-options))))))) - -(defmethod ede-commit ((config ede-generic-config)) - "Commit all changes to the configuration to disk." - (eieio-persistent-save config)) - ;;; Creating Derived Projects: ;; ;; Derived projects need an autoloader so that EDE can find the @@ -415,13 +266,16 @@ the class `ede-generic-project' project." :name external-name :file 'ede/generic :proj-file projectfile + :root-only nil :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. + ;; NOTE: This project type is SAFE because it handles + ;; the user-query before loading its config file. These + ;; project types are useful without the config file so + ;; do the safe part until the user creates a saved config + ;; file for it. + :safe-p t) ;; Generics must go at the end, since more specific types ;; can create Makefiles also. 'generic)) @@ -436,6 +290,25 @@ the class `ede-generic-project' project." "SConstruct" 'ede-generic-scons-project) (ede-generic-new-autoloader "generic-cmake" "CMake" "CMakeLists" 'ede-generic-cmake-project) + + ;; Super Generic found via revision control tags. + (ede-generic-new-autoloader "generic-git" "Git" + ".git" 'ede-generic-vc-project) + (ede-generic-new-autoloader "generic-bzr" "Bazaar" + ".bzr" 'ede-generic-vc-project) + (ede-generic-new-autoloader "generic-hg" "Mercurial" + ".hg" 'ede-generic-vc-project) + (ede-generic-new-autoloader "generic-svn" "Subversions" + ".svn" 'ede-generic-vc-project) + (ede-generic-new-autoloader "generic-cvs" "CVS" + "CVS" 'ede-generic-vc-project) + + ;; Take advantage of existing 'projectile' based projects. + ;; @TODO - if projectile supports compile commands etc, can we + ;; read that out? Howto if projectile is not part of core emacs. + (ede-generic-new-autoloader "generic-projectile" ".projectile" + ".projectile" 'ede-generic-vc-project) + ) @@ -481,6 +354,15 @@ the class `ede-generic-project' project." (oset config debug-command "gdb ") ) +;;; Generic Version Control System +(defclass ede-generic-vc-project (ede-generic-project) + () + "Generic project found via Version Control files.") + +(defmethod ede-generic-setup-configuration ((proj ede-generic-vc-project) config) + "Setup a configuration for projects identified by revision control." + ) + (provide 'ede/generic) ;; Local variables: diff --git a/lisp/cedet/ede/linux.el b/lisp/cedet/ede/linux.el index 4e8a06ef110..b28301d777f 100644 --- a/lisp/cedet/ede/linux.el +++ b/lisp/cedet/ede/linux.el @@ -73,37 +73,6 @@ :group 'project-linux :type 'string) -(defvar ede-linux-project-list nil - "List of projects created by option `ede-linux-project'.") - -(defun ede-linux-file-existing (dir) - "Find a Linux project in the list of Linux projects. -DIR is the directory to search from." - (let ((projs ede-linux-project-list) - (ans nil)) - (while (and projs (not ans)) - (let ((root (ede-project-root-directory (car projs)))) - (when (string-match (concat "^" (regexp-quote root)) dir) - (setq ans (car projs)))) - (setq projs (cdr projs))) - ans)) - -;;;###autoload -(defun ede-linux-project-root (&optional dir) - "Get the root directory for DIR." - (when (not dir) (setq dir default-directory)) - (let ((case-fold-search t) - (proj (ede-linux-file-existing dir))) - (if proj - (ede-up-directory (file-name-directory - (oref proj :file))) - ;; No pre-existing project. Let's take a wild-guess if we have - ;; an Linux project here. - (when (string-match "linux[^/]*" dir) - (let ((base (substring dir 0 (match-end 0)))) - (when (file-exists-p (expand-file-name "scripts/ver_linux" base)) - base)))))) - (defun ede-linux-version (dir) "Find the Linux version for the Linux src in DIR." (let ((buff (get-buffer-create " *linux-query*"))) @@ -124,9 +93,8 @@ DIR is the directory to search from." (kill-buffer buff) ))))) -(defclass ede-linux-project (ede-project eieio-instance-tracker) - ((tracking-symbol :initform 'ede-linux-project-list) - (build-directory :initarg :build-directory +(defclass ede-linux-project (ede-project) + ((build-directory :initarg :build-directory :type string :documentation "Build directory.") (architecture :initarg :architecture @@ -226,22 +194,20 @@ until Linux is built for the first time." Return nil if there isn't one. Argument DIR is the directory it is created for. ROOTPROJ is nil, since there is only one project." - (or (ede-linux-file-existing dir) - ;; Doesn't already exist, so let's make one. - (let* ((bdir (ede-linux--get-build-directory dir)) - (arch (ede-linux--get-architecture dir bdir)) - (include-path (ede-linux--include-path dir bdir arch)) - (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) - :build-directory bdir - :architecture arch - :include-path include-path))) - (ede-add-project-to-global-list proj)))) + ;; Doesn't already exist, so let's make one. + (let* ((bdir (ede-linux--get-build-directory dir)) + (arch (ede-linux--get-architecture dir bdir)) + (include-path (ede-linux--include-path dir bdir arch))) + (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) + :build-directory bdir + :architecture arch + :include-path include-path))) ;;;###autoload (ede-add-project-autoload @@ -249,8 +215,6 @@ ROOTPROJ is nil, since there is only one project." :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 @@ -376,6 +340,8 @@ Knows about how the Linux source tree is organized." (t nil)))) (or F (call-next-method)))) +;;; Command Support +;; (defmethod project-compile-project ((proj ede-linux-project) &optional command) "Compile the entire current project. @@ -412,6 +378,19 @@ Argument COMMAND is the command to use for compiling the target." (compile command))) +(defmethod project-rescan ((this ede-linux-project)) + "Rescan this Linux project from the sources." + (let* ((dir (ede-project-root-directory this)) + (bdir (ede-linux--get-build-directory dir)) + (arch (ede-linux--get-architecture dir bdir)) + (inc (ede-linux--include-path dir bdir arch)) + (ver (ede-linux-version dir))) + (oset this version ver) + (oset this :build-directory bdir) + (oset this :architecture arch) + (oset this :include-path inc) + )) + (provide 'ede/linux) ;; Local variables: diff --git a/lisp/cedet/ede/pconf.el b/lisp/cedet/ede/pconf.el index dca4b33131a..1fa2a1c4343 100644 --- a/lisp/cedet/ede/pconf.el +++ b/lisp/cedet/ede/pconf.el @@ -100,7 +100,7 @@ don't do it. A value of nil means to just do it.") (ede-map-targets this 'ede-proj-tweak-autoconf))) ;; Now save (save-buffer) - (setq postcmd "autoreconf -i;") + (setq postcmd "autoreconf -f -i;") ;; Verify a bunch of files that are required by automake. (ede-proj-configure-test-required-file this "AUTHORS") @@ -173,11 +173,14 @@ By flushing, remove any cruft that may be in the file. Subsequent calls to `ede-proj-tweak-autoconf' can restore items removed by flush." nil) + +;; @TODO - No-one calls this ??? (defmethod ede-proj-configure-add-missing ((this ede-proj-target)) "Query if any files needed by THIS provided by automake are missing. Results in --add-missing being passed to automake." nil) +;; @TODO - No-one implements this yet. (defmethod ede-proj-configure-create-missing ((this ede-proj-target)) "Add any missing files for THIS by creating them." nil) diff --git a/lisp/cedet/ede/proj-elisp.el b/lisp/cedet/ede/proj-elisp.el index f27ae8adf74..8d5a174b271 100644 --- a/lisp/cedet/ede/proj-elisp.el +++ b/lisp/cedet/ede/proj-elisp.el @@ -267,7 +267,8 @@ is found, such as a `-version' variable, or the standard header." (while paths (ede-proj-elisp-add-path (car paths)) (setq paths (cdr paths)))) - (save-buffer)) ))) + (save-buffer) + (kill-buffer))))) (defmethod ede-proj-flush-autoconf ((this ede-proj-target-elisp)) "Flush the configure file (current buffer) to accommodate THIS." diff --git a/lisp/cedet/ede/proj.el b/lisp/cedet/ede/proj.el index e3c2ea4b914..7f3b186f504 100644 --- a/lisp/cedet/ede/proj.el +++ b/lisp/cedet/ede/proj.el @@ -310,7 +310,7 @@ the PROJECT being read in is the root project." (let ((sd (file-name-as-directory (expand-file-name (car subdirs) project)))) (if (and (file-directory-p sd) - (ede-directory-project-p sd)) + (file-exists-p (expand-file-name "Project.ede" sd))) (oset ret subproj (cons (ede-proj-load sd (or rootproj ret)) (oref ret subproj)))) @@ -690,7 +690,10 @@ Optional argument FORCE will force items to be regenerated." "Rescan the EDE proj project THIS." (let ((root (or (ede-project-root this) this)) ) - (setq ede-projects (delq root ede-projects)) + ;; @TODO - VERIFY THE BELOW WORKS + (ede-project-directory-remove-hash + (file-name-directory (ede-project-root-directory root))) + (ede-delete-project-from-global-list root) ;; NOTE : parent function double-checks that this dir was ;; already in memory once. (ede-load-project-file (ede-project-root-directory root)) diff --git a/lisp/cedet/ede/project-am.el b/lisp/cedet/ede/project-am.el index 43482ce0582..3e7a97cc94c 100644 --- a/lisp/cedet/ede/project-am.el +++ b/lisp/cedet/ede/project-am.el @@ -409,7 +409,7 @@ Argument COMMAND is the command to use for compiling the target." (setq default-directory dd) (setq cmd (read-from-minibuffer "Run (like this): " - (concat (ede-target-name obj)))) + (concat "./" (ede-target-name obj)))) (ede-shell-run-something obj cmd)) (kill-buffer tb)))) @@ -428,12 +428,8 @@ Argument COMMAND is the command to use for compiling the target." If a given set of projects has already been loaded, then do nothing but return the project for the directory given. Optional ROOTPROJ is the root EDE project." - (let* ((ede-constructing t) - (amo (object-assoc (expand-file-name "Makefile.am" directory) - 'file ede-projects))) - (when (not amo) - (setq amo (project-am-load-makefile directory))) - amo)) + ;; Just jump into creating the project from the Makefiles. + (project-am-load-makefile directory)) (defun project-am-find-topmost-level (dir) "Find the topmost automakefile starting with DIR." diff --git a/lisp/cedet/ede/shell.el b/lisp/cedet/ede/shell.el index 3d6eb194e42..d28977bd14f 100644 --- a/lisp/cedet/ede/shell.el +++ b/lisp/cedet/ede/shell.el @@ -42,10 +42,15 @@ COMMAND is a text string representing the thing to be run." ;; Show the new buffer. (when (not (get-buffer-window buff)) (switch-to-buffer-other-window buff t)) - ;; Force a shell into the buffer. - (shell buff) - (while (eq (point-min) (point)) - (accept-process-output)) + ;; Force a shell into the buffer, but only if the buffer + ;; doesn't already have a shell in it. + ;; Newer versions of `shell' pop the window forward. + (set-buffer buff) + (when (not (eq major-mode 'shell-mode)) + (shell buff) + ;; Make sure the shell has started. + (while (eq (point-min) (point)) + (accept-process-output))) ;; Change the default directory (if (not (string= (file-name-as-directory (expand-file-name default-directory)) (file-name-as-directory (expand-file-name dd)))) |