summaryrefslogtreecommitdiff
path: root/lisp/cedet/ede.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/cedet/ede.el')
-rw-r--r--lisp/cedet/ede.el947
1 files changed, 112 insertions, 835 deletions
diff --git a/lisp/cedet/ede.el b/lisp/cedet/ede.el
index 46fcdb000f8..43212b626e7 100644
--- a/lisp/cedet/ede.el
+++ b/lisp/cedet/ede.el
@@ -43,24 +43,24 @@
(require 'eieio)
(require 'eieio-speedbar)
(require 'ede/source)
+(require 'ede/base)
+(require 'ede/auto)
+
(load "ede/loaddefs" nil 'nomessage)
+(declare-function ede-commit-project "ede/custom")
(declare-function ede-convert-path "ede/files")
(declare-function ede-directory-get-open-project "ede/files")
(declare-function ede-directory-get-toplevel-open-project "ede/files")
(declare-function ede-directory-project-p "ede/files")
(declare-function ede-find-subproject-for-directory "ede/files")
(declare-function ede-project-directory-remove-hash "ede/files")
-(declare-function ede-project-root "ede/files")
-(declare-function ede-project-root-directory "ede/files")
(declare-function ede-toplevel "ede/files")
(declare-function ede-toplevel-project "ede/files")
(declare-function ede-up-directory "ede/files")
-(declare-function data-debug-new-buffer "data-debug")
-(declare-function data-debug-insert-object-slots "eieio-datadebug")
(declare-function semantic-lex-make-spp-table "semantic/lex-spp")
-(defconst ede-version "1.0pre7"
+(defconst ede-version "1.0"
"Current version of the Emacs EDE.")
;;; Code:
@@ -94,314 +94,6 @@ target willing to take the file. 'never means never perform the check."
:group 'ede
:type 'sexp) ; make this be a list of options some day
-
-;;; Top level classes for projects and targets
-
-(defclass ede-project-autoload ()
- ((name :initarg :name
- :documentation "Name of this project type")
- (file :initarg :file
- :documentation "The lisp file belonging to this class.")
- (proj-file :initarg :proj-file
- :documentation "Name of a project file of this type.")
- (proj-root :initarg :proj-root
- :type function
- :documentation "A function symbol to call for the project root.
-This function takes no arguments, and returns the current directories
-root, if available. Leave blank to use the EDE directory walking
-routine instead.")
- (initializers :initarg :initializers
- :initform nil
- :documentation
- "Initializers passed to the project object.
-These are used so there can be multiple types of projects
-associated with a single object class, based on the initilizeres used.")
- (load-type :initarg :load-type
- :documentation "Fn symbol used to load this project file.")
- (class-sym :initarg :class-sym
- :documentation "Symbol representing the project class to use.")
- (new-p :initarg :new-p
- :initform t
- :documentation
- "Non-nil if this is an option when a user creates a project.")
- )
- "Class representing minimal knowledge set to run preliminary EDE functions.
-When more advanced functionality is needed from a project type, that projects
-type is required and the load function used.")
-
-(defvar ede-project-class-files
- (list
- (ede-project-autoload "edeproject-makefile"
- :name "Make" :file 'ede/proj
- :proj-file "Project.ede"
- :load-type 'ede-proj-load
- :class-sym 'ede-proj-project)
- (ede-project-autoload "edeproject-automake"
- :name "Automake" :file 'ede/proj
- :proj-file "Project.ede"
- :initializers '(:makefile-type Makefile.am)
- :load-type 'ede-proj-load
- :class-sym 'ede-proj-project)
- (ede-project-autoload "automake"
- :name "automake" :file 'ede/project-am
- :proj-file "Makefile.am"
- :load-type 'project-am-load
- :class-sym 'project-am-makefile
- :new-p nil)
- (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)
- (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)
- (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)
- (ede-project-autoload "simple-overlay"
- :name "Simple" :file 'ede/simple
- :proj-file 'ede-simple-projectfile-for-dir
- :load-type 'ede-simple-load
- :class-sym 'ede-simple-project))
- "List of vectors defining how to determine what type of projects exist.")
-
-;;; Generic project information manager objects
-
-(defclass ede-target (eieio-speedbar-directory-button)
- ((buttonface :initform speedbar-file-face) ;override for superclass
- (name :initarg :name
- :type string
- :custom string
- :label "Name"
- :group (default name)
- :documentation "Name of this target.")
- ;; @todo - I think this should be "dir", and not "path".
- (path :initarg :path
- :type string
- ;:custom string
- ;:label "Path to target"
- ;:group (default name)
- :documentation "The path to the sources of this target.
-Relative to the path of the project it belongs to.")
- (source :initarg :source
- :initform nil
- ;; I'd prefer a list of strings.
- :type list
- :custom (repeat (string :tag "File"))
- :label "Source Files"
- :group (default source)
- :documentation "Source files in this target.")
- (versionsource :initarg :versionsource
- :initform nil
- :type list
- :custom (repeat (string :tag "File"))
- :label "Source Files with Version String"
- :group (source)
- :documentation
- "Source files with a version string in them.
-These files are checked for a version string whenever the EDE version
-of the master project is changed. When strings are found, the version
-previously there is updated.")
- ;; Class level slots
- ;;
-; (takes-compile-command :allocation :class
-; :initarg :takes-compile-command
-; :type boolean
-; :initform nil
-; :documentation
-; "Non-nil if this target requires a user approved command.")
- (sourcetype :allocation :class
- :type list ;; list of symbols
- :documentation
- "A list of `ede-sourcecode' objects this class will handle.
-This is used to match target objects with the compilers they can use, and
-which files this object is interested in."
- :accessor ede-object-sourcecode)
- (keybindings :allocation :class
- :initform (("D" . ede-debug-target))
- :documentation
-"Keybindings specialized to this type of target."
- :accessor ede-object-keybindings)
- (menu :allocation :class
- :initform ( [ "Debug target" ede-debug-target
- (and ede-object
- (obj-of-class-p ede-object ede-target)) ]
- )
- [ "Run target" ede-run-target
- (and ede-object
- (obj-of-class-p ede-object ede-target)) ]
- :documentation "Menu specialized to this type of target."
- :accessor ede-object-menu)
- )
- "A top level target to build.")
-
-(defclass ede-project-placeholder (eieio-speedbar-directory-button)
- ((name :initarg :name
- :initform "Untitled"
- :type string
- :custom string
- :label "Name"
- :group (default name)
- :documentation "The name used when generating distribution files.")
- (version :initarg :version
- :initform "1.0"
- :type string
- :custom string
- :label "Version"
- :group (default name)
- :documentation "The version number used when distributing files.")
- (directory :type string
- :initarg :directory
- :documentation "Directory this project is associated with.")
- (dirinode :documentation "The inode id for :directory.")
- (file :type string
- :initarg :file
- :documentation "File name where this project is stored.")
- (rootproject ; :initarg - no initarg, don't save this slot!
- :initform nil
- :type (or null ede-project-placeholder-child)
- :documentation "Pointer to our root project.")
- )
- "Placeholder object for projects not loaded into memory.
-Projects placeholders will be stored in a user specific location
-and querying them will cause the actual project to get loaded.")
-
-(defclass ede-project (ede-project-placeholder)
- ((subproj :initform nil
- :type list
- :documentation "Sub projects controlled by this project.
-For Automake based projects, each directory is treated as a project.")
- (targets :initarg :targets
- :type list
- :custom (repeat (object :objectcreatefcn ede-new-target-custom))
- :label "Local Targets"
- :group (targets)
- :documentation "List of top level targets in this project.")
- (locate-obj :type (or null ede-locate-base-child)
- :documentation
- "A locate object to use as a backup to `ede-expand-filename'.")
- (tool-cache :initarg :tool-cache
- :type list
- :custom (repeat object)
- :label "Tool: "
- :group tools
- :documentation "List of tool cache configurations in this project.
-This allows any tool to create, manage, and persist project-specific settings.")
- (mailinglist :initarg :mailinglist
- :initform ""
- :type string
- :custom string
- :label "Mailing List Address"
- :group name
- :documentation
- "An email address where users might send email for help.")
- (web-site-url :initarg :web-site-url
- :initform ""
- :type string
- :custom string
- :label "Web Site URL"
- :group name
- :documentation "URL to this projects web site.
-This is a URL to be sent to a web site for documentation.")
- (web-site-directory :initarg :web-site-directory
- :initform ""
- :custom string
- :label "Web Page Directory"
- :group name
- :documentation
- "A directory where web pages can be found by Emacs.
-For remote locations use a path compatible with ange-ftp or EFS.
-You can also use TRAMP for use with rcp & scp.")
- (web-site-file :initarg :web-site-file
- :initform ""
- :custom string
- :label "Web Page File"
- :group name
- :documentation
- "A file which contains the home page for this project.
-This file can be relative to slot `web-site-directory'.
-This can be a local file, use ange-ftp, EFS, or TRAMP.")
- (ftp-site :initarg :ftp-site
- :initform ""
- :type string
- :custom string
- :label "FTP site"
- :group name
- :documentation
- "FTP site where this project's distribution can be found.
-This FTP site should be in Emacs form, as needed by `ange-ftp', but can
-also be of a form used by TRAMP for use with scp, or rcp.")
- (ftp-upload-site :initarg :ftp-upload-site
- :initform ""
- :type string
- :custom string
- :label "FTP Upload site"
- :group name
- :documentation
- "FTP Site to upload new distributions to.
-This FTP site should be in Emacs form as needed by `ange-ftp'.
-If this slot is nil, then use `ftp-site' instead.")
- (configurations :initarg :configurations
- :initform ("debug" "release")
- :type list
- :custom (repeat string)
- :label "Configuration Options"
- :group (settings)
- :documentation "List of available configuration types.
-Individual target/project types can form associations between a configuration,
-and target specific elements such as build variables.")
- (configuration-default :initarg :configuration-default
- :initform "debug"
- :custom string
- :label "Current Configuration"
- :group (settings)
- :documentation "The default configuration.")
- (local-variables :initarg :local-variables
- :initform nil
- :custom (repeat (cons (sexp :tag "Variable")
- (sexp :tag "Value")))
- :label "Project Local Variables"
- :group (settings)
- :documentation "Project local variables")
- (keybindings :allocation :class
- :initform (("D" . ede-debug-target)
- ("R" . ede-run-target))
- :documentation "Keybindings specialized to this type of target."
- :accessor ede-object-keybindings)
- (menu :allocation :class
- :initform
- (
- [ "Update Version" ede-update-version ede-object ]
- [ "Version Control Status" ede-vc-project-directory ede-object ]
- [ "Edit Project Homepage" ede-edit-web-page
- (and ede-object (oref (ede-toplevel) web-site-file)) ]
- [ "Browse Project URL" ede-web-browse-home
- (and ede-object
- (not (string= "" (oref (ede-toplevel) web-site-url)))) ]
- "--"
- [ "Rescan Project Files" ede-rescan-toplevel t ]
- [ "Edit Projectfile" ede-edit-file-target
- (and ede-object
- (or (listp ede-object)
- (not (obj-of-class-p ede-object ede-project)))) ]
- )
- :documentation "Menu specialized to this type of target."
- :accessor ede-object-menu)
- )
- "Top level EDE project specification.
-All specific project types must derive from this project."
- :method-invocation-order :depth-first)
;;; Management variables
@@ -430,109 +122,13 @@ This object's class determines how to compile and debug from a buffer.")
If `ede-object' is nil, then commands will operate on this object.")
(defvar ede-constructing nil
- "Non nil when constructing a project hierarchy.")
+ "Non nil when constructing a project hierarchy.
+If the project is being constructed from an autoload, then the
+value is the autoload object being used.")
(defvar ede-deep-rescan nil
"Non nil means scan down a tree, otherwise rescans are top level only.
Do not set this to non-nil globally. It is used internally.")
-
-;;; The EDE persistent cache.
-;;
-(defcustom ede-project-placeholder-cache-file
- (locate-user-emacs-file "ede-projects.el" ".projects.ede")
- "File containing the list of projects EDE has viewed."
- :group 'ede
- :type 'file)
-
-(defvar ede-project-cache-files nil
- "List of project files EDE has seen before.")
-
-(defun ede-save-cache ()
- "Save a cache of EDE objects that Emacs has seen before."
- (interactive)
- (let ((p ede-projects)
- (c ede-project-cache-files)
- (recentf-exclude '(ignore))
- )
- (condition-case nil
- (progn
- (set-buffer (find-file-noselect ede-project-placeholder-cache-file t))
- (erase-buffer)
- (insert ";; EDE project cache file.
-;; This contains a list of projects you have visited.\n(")
- (while p
- (when (and (car p) (ede-project-p p))
- (let ((f (oref (car p) file)))
- (when (file-exists-p f)
- (insert "\n \"" f "\""))))
- (setq p (cdr p)))
- (while c
- (insert "\n \"" (car c) "\"")
- (setq c (cdr c)))
- (insert "\n)\n")
- (condition-case nil
- (save-buffer 0)
- (error
- (message "File %s could not be saved."
- ede-project-placeholder-cache-file)))
- (kill-buffer (current-buffer))
- )
- (error
- (message "File %s could not be read."
- ede-project-placeholder-cache-file))
-
- )))
-
-(defun ede-load-cache ()
- "Load the cache of EDE projects."
- (save-excursion
- (let ((cachebuffer nil))
- (condition-case nil
- (progn
- (setq cachebuffer
- (find-file-noselect ede-project-placeholder-cache-file t))
- (set-buffer cachebuffer)
- (goto-char (point-min))
- (let ((c (read (current-buffer)))
- (new nil)
- (p ede-projects))
- ;; Remove loaded projects from the cache.
- (while p
- (setq c (delete (oref (car p) file) c))
- (setq p (cdr p)))
- ;; Remove projects that aren't on the filesystem
- ;; anymore.
- (while c
- (when (file-exists-p (car c))
- (setq new (cons (car c) new)))
- (setq c (cdr c)))
- ;; Save it
- (setq ede-project-cache-files (nreverse new))))
- (error nil))
- (when cachebuffer (kill-buffer cachebuffer))
- )))
-
-;;; Important macros for doing commands.
-;;
-(defmacro ede-with-projectfile (obj &rest forms)
- "For the project in which OBJ resides, execute FORMS."
- (list 'save-window-excursion
- (list 'let* (list
- (list 'pf
- (list 'if (list '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.
- (list 'ede-load-project-file
- (list 'oref obj 'path))
- obj))
- '(dbka (get-file-buffer (oref pf file))))
- '(if (not dbka) (find-file (oref pf file))
- (switch-to-buffer dbka))
- (cons 'progn forms)
- '(if (not dbka) (kill-buffer (current-buffer))))))
-(put 'ede-with-projectfile 'lisp-indent-function 1)
;;; Prompting
@@ -610,6 +206,18 @@ Argument LIST-O-O is the list of objects to choose from."
:enable ede-object
:visible global-ede-mode))
+(defun ede-buffer-belongs-to-target-p ()
+ "Return non-nil if this buffer belongs to at least one target."
+ (let ((obj ede-object))
+ (if (consp obj)
+ (setq obj (car obj)))
+ (and obj (obj-of-class-p obj ede-target))))
+
+(defun ede-buffer-belongs-to-project-p ()
+ "Return non-nil if this buffer belongs to at least one target."
+ (if (or (null ede-object) (consp ede-object)) nil
+ (obj-of-class-p ede-object ede-project)))
+
(defun ede-menu-obj-of-class-p (class)
"Return non-nil if some member of `ede-object' is a child of CLASS."
(if (listp ede-object)
@@ -671,9 +279,7 @@ Argument MENU-DEF is the menu definition to use."
(and (ede-current-project)
(oref (ede-current-project) targets)) ]
[ "Remove File" ede-remove-file
- (and ede-object
- (or (listp ede-object)
- (not (obj-of-class-p ede-object ede-project)))) ]
+ (ede-buffer-belongs-to-project-p) ]
"-")
(if (not obj)
nil
@@ -717,7 +323,7 @@ Argument MENU-DEF is the definition of the current menu."
(let* ((obj (ede-current-project))
targ)
(when obj
- (setq targ (when (slot-boundp obj 'targets)
+ (setq targ (when (and obj (slot-boundp obj 'targets))
(oref obj targets)))
;; Make custom menus for everything here.
(append (list
@@ -803,31 +409,49 @@ provided `global-ede-mode' is enabled."
(eq major-mode 'vc-dired-mode))
(ede-dired-minor-mode (if ede-minor-mode 1 -1)))
(ede-minor-mode
- (if (and (not ede-constructing)
- (ede-directory-project-p default-directory t))
- (let* ((ROOT nil)
- (proj (ede-directory-get-open-project default-directory
- 'ROOT)))
- (when (not proj)
- ;; @todo - this could be wasteful.
- (setq proj (ede-load-project-file default-directory 'ROOT)))
- (setq ede-object-project proj)
- (setq ede-object-root-project
- (or ROOT (ede-project-root proj)))
- (setq ede-object (ede-buffer-object))
- (if (and (not ede-object) ede-object-project)
- (ede-auto-add-to-target))
- (ede-apply-target-options))
+ (if (not ede-constructing)
+ (ede-initialize-state-current-buffer)
;; If we fail to have a project here, turn it back off.
(ede-minor-mode -1)))))
+(defun ede-initialize-state-current-buffer ()
+ "Initialize the current buffer's state for EDE.
+Sets buffer local variables for EDE."
+ (let* ((ROOT nil)
+ (proj (ede-directory-get-open-project default-directory
+ 'ROOT)))
+ (when (or proj ROOT
+ (ede-directory-project-p default-directory t))
+
+ (when (not proj)
+ ;; @todo - this could be wasteful.
+ (setq proj (ede-load-project-file default-directory 'ROOT)))
+
+ (setq ede-object (ede-buffer-object (current-buffer)
+ 'ede-object-project))
+
+ (setq ede-object-root-project
+ (or ROOT (ede-project-root ede-object-project)))
+
+ (if (and (not ede-object) ede-object-project)
+ (ede-auto-add-to-target))
+
+ (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."
(let ((b (buffer-list)))
(while b
(when (buffer-file-name (car b))
- (ede-buffer-object (car b))
+ (with-current-buffer (car b)
+ ;; Reset all state variables
+ (setq ede-object nil
+ ede-object-project nil
+ ede-object-root-project nil)
+ ;; Now re-initialize this buffer.
+ (ede-initialize-state-current-buffer)
+ )
)
(setq b (cdr b)))))
@@ -966,6 +590,7 @@ Optional argument NAME is the name to give this project."
r)
)
nil t)))
+ (require 'ede/custom)
;; Make sure we have a valid directory
(when (not (file-exists-p default-directory))
(error "Cannot create project in non-existent directory %s" default-directory))
@@ -1013,20 +638,6 @@ Optional argument NAME is the name to give this project."
"Add into PROJ-A, the subproject PROJ-B."
(oset proj-a subproj (cons proj-b (oref proj-a subproj))))
-(defmethod ede-subproject-relative-path ((proj ede-project) &optional parent-in)
- "Get a path name for PROJ which is relative to the parent project.
-If PARENT is specified, then be relative to the PARENT project.
-Specifying PARENT is useful for sub-sub projects relative to the root project."
- (let* ((parent (or parent-in (ede-parent-project proj)))
- (dir (file-name-directory (oref proj file))))
- (if (and parent (not (eq parent proj)))
- (file-relative-name dir (file-name-directory (oref parent file)))
- "")))
-
-(defmethod ede-subproject-p ((proj ede-project))
- "Return non-nil if PROJ is a sub project."
- (ede-parent-project proj))
-
(defun ede-invoke-method (sym &rest args)
"Invoke method SYM on the current buffer's project object.
ARGS are additional arguments to pass to method sym."
@@ -1161,175 +772,9 @@ Optional argument FORCE forces the file to be removed without asking."
(defun ede-make-dist ()
"Create a distribution from the current project."
(interactive)
- (let ((ede-object (ede-current-project)))
+ (let ((ede-object (ede-toplevel)))
(ede-invoke-method 'project-make-dist)))
-;;; Customization
-;;
-;; Routines for customizing projects and targets.
-
-(defvar eieio-ede-old-variables nil
- "The old variables for a project.")
-
-(defalias 'customize-project 'ede-customize-project)
-(defun ede-customize-project (&optional group)
- "Edit fields of the current project through EIEIO & Custom.
-Optional GROUP specifies the subgroup of slots to customize."
- (interactive "P")
- (require 'eieio-custom)
- (let* ((ov (oref (ede-current-project) local-variables))
- (cp (ede-current-project))
- (group (if group (eieio-read-customization-group cp))))
- (eieio-customize-object cp group)
- (make-local-variable 'eieio-ede-old-variables)
- (setq eieio-ede-old-variables ov)))
-
-(defalias 'customize-target 'ede-customize-current-target)
-(defun ede-customize-current-target(&optional group)
- "Edit fields of the current target through EIEIO & Custom.
-Optional argument OBJ is the target object to customize.
-Optional argument GROUP is the slot group to display."
- (interactive "P")
- (require 'eieio-custom)
- (if (not (obj-of-class-p ede-object ede-target))
- (error "Current file is not part of a target"))
- (let ((group (if group (eieio-read-customization-group ede-object))))
- (ede-customize-target ede-object group)))
-
-(defun ede-customize-target (obj group)
- "Edit fields of the current target through EIEIO & Custom.
-Optional argument OBJ is the target object to customize.
-Optional argument GROUP is the slot group to display."
- (require 'eieio-custom)
- (if (and obj (not (obj-of-class-p obj ede-target)))
- (error "No logical target to customize"))
- (eieio-customize-object obj (or group 'default)))
-;;; Target Sorting
-;;
-;; Target order can be important, but custom doesn't support a way
-;; to resort items in a list. This function by David Engster allows
-;; targets to be re-arranged.
-
-(defvar ede-project-sort-targets-order nil
- "Variable for tracking target order in `ede-project-sort-targets'.")
-
-(defun ede-project-sort-targets ()
- "Create a custom-like buffer for sorting targets of current project."
- (interactive)
- (let ((proj (ede-current-project))
- (count 1)
- current order)
- (switch-to-buffer (get-buffer-create "*EDE sort targets*"))
- (erase-buffer)
- (setq ede-object-project proj)
- (widget-create 'push-button
- :notify (lambda (&rest ignore)
- (let ((targets (oref ede-object-project targets))
- cur newtargets)
- (while (setq cur (pop ede-project-sort-targets-order))
- (setq newtargets (append newtargets
- (list (nth cur targets)))))
- (oset ede-object-project targets newtargets))
- (ede-commit-project ede-object-project)
- (kill-buffer))
- " Accept ")
- (widget-insert " ")
- (widget-create 'push-button
- :notify (lambda (&rest ignore)
- (kill-buffer))
- " Cancel ")
- (widget-insert "\n\n")
- (setq ede-project-sort-targets-order nil)
- (mapc (lambda (x)
- (add-to-ordered-list
- 'ede-project-sort-targets-order
- x x))
- (number-sequence 0 (1- (length (oref proj targets)))))
- (ede-project-sort-targets-list)
- (use-local-map widget-keymap)
- (widget-setup)
- (goto-char (point-min))))
-
-(defun ede-project-sort-targets-list ()
- "Sort the target list while using `ede-project-sort-targets'."
- (save-excursion
- (let ((count 0)
- (targets (oref ede-object-project targets))
- (inhibit-read-only t)
- (inhibit-modification-hooks t))
- (goto-char (point-min))
- (forward-line 2)
- (delete-region (point) (point-max))
- (while (< count (length targets))
- (if (> count 0)
- (widget-create 'push-button
- :notify `(lambda (&rest ignore)
- (let ((cur ede-project-sort-targets-order))
- (add-to-ordered-list
- 'ede-project-sort-targets-order
- (nth ,count cur)
- (1- ,count))
- (add-to-ordered-list
- 'ede-project-sort-targets-order
- (nth (1- ,count) cur) ,count))
- (ede-project-sort-targets-list))
- " Up ")
- (widget-insert " "))
- (if (< count (1- (length targets)))
- (widget-create 'push-button
- :notify `(lambda (&rest ignore)
- (let ((cur ede-project-sort-targets-order))
- (add-to-ordered-list
- 'ede-project-sort-targets-order
- (nth ,count cur) (1+ ,count))
- (add-to-ordered-list
- 'ede-project-sort-targets-order
- (nth (1+ ,count) cur) ,count))
- (ede-project-sort-targets-list))
- " Down ")
- (widget-insert " "))
- (widget-insert (concat " " (number-to-string (1+ count)) ".: "
- (oref (nth (nth count ede-project-sort-targets-order)
- targets) name) "\n"))
- (setq count (1+ count))))))
-
-;;; Customization hooks
-;;
-;; These hooks are used when finishing up a customization.
-(defmethod eieio-done-customizing ((proj ede-project))
- "Call this when a user finishes customizing PROJ."
- (let ((ov eieio-ede-old-variables)
- (nv (oref proj local-variables)))
- (setq eieio-ede-old-variables nil)
- (while ov
- (if (not (assoc (car (car ov)) nv))
- (save-excursion
- (mapc (lambda (b)
- (set-buffer b)
- (kill-local-variable (car (car ov))))
- (ede-project-buffers proj))))
- (setq ov (cdr ov)))
- (mapc (lambda (b) (ede-set-project-variables proj b))
- (ede-project-buffers proj))))
-
-(defmethod eieio-done-customizing ((target ede-target))
- "Call this when a user finishes customizing TARGET."
- nil)
-
-(defmethod ede-commit-project ((proj ede-project))
- "Commit any change to PROJ to its file."
- nil
- )
-
-
-;;; EDE project placeholder methods
-;;
-(defmethod ede-project-force-load ((this ede-project-placeholder))
- "Make sure the placeholder THIS is replaced with the real thing.
-Return the new object created in its place."
- this
- )
-
;;; EDE project target baseline methods.
;;
@@ -1342,9 +787,9 @@ Return the new object created in its place."
;; methods based on those below.
(defmethod project-interactive-select-target ((this ede-project-placeholder) prompt)
- ; checkdoc-params: (prompt)
+ ; checkdoc-params: (prompt)
"Make sure placeholder THIS is replaced with the real thing, and pass through."
- (project-interactive-select-target (ede-project-force-load this) prompt))
+ (project-interactive-select-target this prompt))
(defmethod project-interactive-select-target ((this ede-project) prompt)
"Interactively query for a target that exists in project THIS.
@@ -1353,9 +798,9 @@ Argument PROMPT is the prompt to use when querying the user for a target."
(cdr (assoc (completing-read prompt ob nil t) ob))))
(defmethod project-add-file ((this ede-project-placeholder) file)
- ; checkdoc-params: (file)
+ ; checkdoc-params: (file)
"Make sure placeholder THIS is replaced with the real thing, and pass through."
- (project-add-file (ede-project-force-load this) file))
+ (project-add-file this file))
(defmethod project-add-file ((ot ede-target) file)
"Add the current buffer into project project target OT.
@@ -1412,132 +857,6 @@ Argument COMMAND is the command to use for compiling the target."
(defmethod project-rescan ((this ede-project))
"Rescan the EDE proj project THIS."
(error "Rescanning a project is not supported by %s" (object-name this)))
-
-;;; Default methods for EDE classes
-;;
-;; These are methods which you might want to override, but there is
-;; no need to in most situations because they are either a) simple, or
-;; b) cosmetic.
-
-(defmethod ede-name ((this ede-target))
- "Return the name of THIS target."
- (oref this name))
-
-(defmethod ede-target-name ((this ede-target))
- "Return the name of THIS target, suitable for make or debug style commands."
- (oref this name))
-
-(defmethod ede-name ((this ede-project))
- "Return a short-name for THIS project file.
-Do this by extracting the lowest directory name."
- (oref this name))
-
-(defmethod ede-description ((this ede-project))
- "Return a description suitable for the minibuffer about THIS."
- (format "Project %s: %d subprojects, %d targets."
- (ede-name this) (length (oref this subproj))
- (length (oref this targets))))
-
-(defmethod ede-description ((this ede-target))
- "Return a description suitable for the minibuffer about THIS."
- (format "Target %s: with %d source files."
- (ede-name this) (length (oref this source))))
-
-(defmethod ede-want-file-p ((this ede-target) file)
- "Return non-nil if THIS target wants FILE."
- ;; By default, all targets reference the source object, and let it decide.
- (let ((src (ede-target-sourcecode this)))
- (while (and src (not (ede-want-file-p (car src) file)))
- (setq src (cdr src)))
- src))
-
-(defmethod ede-want-file-source-p ((this ede-target) file)
- "Return non-nil if THIS target wants FILE."
- ;; By default, all targets reference the source object, and let it decide.
- (let ((src (ede-target-sourcecode this)))
- (while (and src (not (ede-want-file-source-p (car src) file)))
- (setq src (cdr src)))
- src))
-
-(defun ede-header-file ()
- "Return the header file for the current buffer.
-Not all buffers need headers, so return nil if no applicable."
- (if ede-object
- (ede-buffer-header-file ede-object (current-buffer))
- nil))
-
-(defmethod ede-buffer-header-file ((this ede-project) buffer)
- "Return nil, projects don't have header files."
- nil)
-
-(defmethod ede-buffer-header-file ((this ede-target) buffer)
- "There are no default header files in EDE.
-Do a quick check to see if there is a Header tag in this buffer."
- (with-current-buffer buffer
- (if (re-search-forward "::Header:: \\([a-zA-Z0-9.]+\\)" nil t)
- (buffer-substring-no-properties (match-beginning 1)
- (match-end 1))
- (let ((src (ede-target-sourcecode this))
- (found nil))
- (while (and src (not found))
- (setq found (ede-buffer-header-file (car src) (buffer-file-name))
- src (cdr src)))
- found))))
-
-(defun ede-documentation-files ()
- "Return the documentation files for the current buffer.
-Not all buffers need documentations, so return nil if no applicable.
-Some projects may have multiple documentation files, so return a list."
- (if ede-object
- (ede-buffer-documentation-files ede-object (current-buffer))
- nil))
-
-(defmethod ede-buffer-documentation-files ((this ede-project) buffer)
- "Return all documentation in project THIS based on BUFFER."
- ;; Find the info node.
- (ede-documentation this))
-
-(defmethod ede-buffer-documentation-files ((this ede-target) buffer)
- "Check for some documentation files for THIS.
-Also do a quick check to see if there is a Documentation tag in this BUFFER."
- (with-current-buffer buffer
- (if (re-search-forward "::Documentation:: \\([a-zA-Z0-9.]+\\)" nil t)
- (buffer-substring-no-properties (match-beginning 1)
- (match-end 1))
- ;; Check the master project
- (let ((cp (ede-toplevel)))
- (ede-buffer-documentation-files cp (current-buffer))))))
-
-(defmethod ede-documentation ((this ede-project))
- "Return a list of files that provide documentation.
-Documentation is not for object THIS, but is provided by THIS for other
-files in the project."
- (let ((targ (oref this targets))
- (proj (oref this subproj))
- (found nil))
- (while targ
- (setq found (append (ede-documentation (car targ)) found)
- targ (cdr targ)))
- (while proj
- (setq found (append (ede-documentation (car proj)) found)
- proj (cdr proj)))
- found))
-
-(defmethod ede-documentation ((this ede-target))
- "Return a list of files that provide documentation.
-Documentation is not for object THIS, but is provided by THIS for other
-files in the project."
- nil)
-
-(defun ede-html-documentation-files ()
- "Return a list of HTML documentation files associated with this project."
- (ede-html-documentation (ede-toplevel))
- )
-
-(defmethod ede-html-documentation ((this ede-project))
- "Return a list of HTML files provided by project THIS."
-
- )
(defun ede-ecb-project-paths ()
"Return a list of all paths for all active EDE projects.
@@ -1549,24 +868,8 @@ This functions is meant for use with ECB."
d)
p (cdr p)))
d))
-
-;;; EDE project-autoload methods
-;;
-(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."
- (let* ((d (file-name-as-directory dir))
- (root (ede-project-root-directory this d))
- (pf (oref this proj-file))
- (f (cond ((stringp pf)
- (expand-file-name pf (or root d)))
- ((and (symbolp pf) (fboundp pf))
- (funcall pf (or root d)))))
- )
- (when (and f (file-exists-p f))
- f)))
-
-;;; EDE basic functions
+
+;;; PROJECT LOADING/TRACKING
;;
(defun ede-add-project-to-global-list (proj)
"Add the project PROJ to the master list of projects.
@@ -1602,7 +905,7 @@ Optional ROOTRETURN will return the root project for DIR."
(if p (ede-load-project-file p)
nil)
;; recomment as we go
- ;nil
+ ;;nil
))
;; Do nothing if we are buiding an EDE project already
(ede-constructing
@@ -1611,7 +914,7 @@ Optional ROOTRETURN will return the root project for DIR."
(t
(setq toppath (ede-toplevel-project path))
;; We found the top-most directory. Check to see if we already
- ;; have an object defining it's project.
+ ;; have an object defining its project.
(setq pfc (ede-directory-project-p toppath t))
;; See if it's been loaded before
@@ -1619,7 +922,7 @@ Optional ROOTRETURN will return the root project for DIR."
ede-projects))
(if (not o)
;; If not, get it now.
- (let ((ede-constructing t))
+ (let ((ede-constructing pfc))
(setq o (funcall (oref pfc load-type) toppath))
(when (not o)
(error "Project type error: :load-type failed to create a project"))
@@ -1648,9 +951,14 @@ Optional ROOTRETURN will return the root project for DIR."
(delete (oref found file) ede-project-cache-files)))
found)))))
+;;; PROJECT ASSOCIATIONS
+;;
+;; Moving between relative projects. Associating between buffers and
+;; projects.
+
(defun ede-parent-project (&optional obj)
"Return the project belonging to the parent directory.
-Returns nil if there is no previous directory.
+Return nil if there is no previous directory.
Optional argument OBJ is an object to find the parent of."
(let* ((proj (or obj ede-object-project)) ;; Current project.
(root (if obj (ede-project-root obj)
@@ -1700,17 +1008,38 @@ If optional DIR is provided, get the project for DIR instead."
;; Return what we found.
ans))
-(defun ede-buffer-object (&optional buffer)
+(defun ede-buffer-object (&optional buffer projsym)
"Return the target object for BUFFER.
-This function clears cached values and recalculates."
+This function clears cached values and recalculates.
+Optional PROJSYM is a symbol, which will be set to the project
+that contains the target that becomes buffer's object."
(save-excursion
(if (not buffer) (setq buffer (current-buffer)))
(set-buffer buffer)
(setq ede-object nil)
- (let ((po (ede-current-project)))
- (if po (setq ede-object (ede-find-target po buffer))))
- (if (= (length ede-object) 1)
- (setq ede-object (car ede-object)))
+ (let* ((localpo (ede-current-project))
+ (po localpo)
+ (top (ede-toplevel po)))
+ (if po (setq ede-object (ede-find-target po buffer)))
+ ;; If we get nothing, go with the backup plan of slowly
+ ;; looping upward
+ (while (and (not ede-object) (not (eq po top)))
+ (setq po (ede-parent-project po))
+ (if po (setq ede-object (ede-find-target po buffer))))
+ ;; Filter down to 1 project if there are dups.
+ (if (= (length ede-object) 1)
+ (setq ede-object (car ede-object)))
+ ;; Track the project, if needed.
+ (when (and projsym (symbolp projsym))
+ (if ede-object
+ ;; If we found a target, then PO is the
+ ;; project to use.
+ (set projsym po)
+ ;; If there is no ede-object, then the projsym
+ ;; is whichever part of the project is most local.
+ (set projsym localpo))
+ ))
+ ;; Return our findings.
ede-object))
(defmethod ede-target-in-project-p ((proj ede-project) target)
@@ -1737,14 +1066,6 @@ could become slow in time."
projs (cdr projs)))
ans))
-(defun ede-maybe-checkout (&optional buffer)
- "Check BUFFER out of VC if necessary."
- (save-excursion
- (if buffer (set-buffer buffer))
- (if (and buffer-read-only vc-mode
- (y-or-n-p "Checkout Makefile.am from VC? "))
- (vc-toggle-read-only))))
-
(defmethod ede-find-target ((proj ede-project) buffer)
"Fetch the target in PROJ belonging to BUFFER or nil."
(with-current-buffer buffer
@@ -1785,7 +1106,7 @@ This includes buffers controlled by a specific target of PROJECT."
(pl nil))
(while bl
(with-current-buffer (car bl)
- (if (and ede-object (eq (ede-current-project) project))
+ (if (ede-buffer-belongs-to-project-p)
(setq pl (cons (car bl) pl))))
(setq bl (cdr bl)))
pl))
@@ -1856,6 +1177,16 @@ See also `ede-map-subprojects'."
Return the first non-nil value returned by PROC."
(eval (cons 'or (ede-map-targets this proc))))
+;;; VC Handling
+;;
+(defun ede-maybe-checkout (&optional buffer)
+ "Check BUFFER out of VC if necessary."
+ (save-excursion
+ (if buffer (set-buffer buffer))
+ (if (and buffer-read-only vc-mode
+ (y-or-n-p "Checkout Makefile.am from VC? "))
+ (vc-toggle-read-only))))
+
;;; Some language specific methods.
;;
@@ -1912,7 +1243,7 @@ Return the first non-nil value returned by PROC."
(with-current-buffer buffer
(dolist (v (oref project local-variables))
(make-local-variable (car v))
- ;; set it's value here?
+ ;; set its value here?
(set (car v) (cdr v)))))
(defun ede-set (variable value &optional proj)
@@ -1935,60 +1266,6 @@ is the project to use, instead of `ede-current-project'."
"Commit change to local variables in PROJ."
nil)
-
-;;; Accessors for more complex types where oref is inappropriate.
-;;
-(defmethod ede-target-sourcecode ((this ede-target))
- "Return the sourcecode objects which THIS permits."
- (let ((sc (oref this sourcetype))
- (rs nil))
- (while (and (listp sc) sc)
- (setq rs (cons (symbol-value (car sc)) rs)
- sc (cdr sc)))
- rs))
-
-
-;;; Debugging.
-
-(defun ede-adebug-project ()
- "Run adebug against the current EDE project.
-Display the results as a debug list."
- (interactive)
- (require 'data-debug)
- (when (ede-current-project)
- (data-debug-new-buffer "*Analyzer ADEBUG*")
- (data-debug-insert-object-slots (ede-current-project) "")
- ))
-
-(defun ede-adebug-project-parent ()
- "Run adebug against the current EDE parent project.
-Display the results as a debug list."
- (interactive)
- (require 'data-debug)
- (when (ede-parent-project)
- (data-debug-new-buffer "*Analyzer ADEBUG*")
- (data-debug-insert-object-slots (ede-parent-project) "")
- ))
-
-(defun ede-adebug-project-root ()
- "Run adebug against the current EDE parent project.
-Display the results as a debug list."
- (interactive)
- (require 'data-debug)
- (when (ede-toplevel)
- (data-debug-new-buffer "*Analyzer ADEBUG*")
- (data-debug-insert-object-slots (ede-toplevel) "")
- ))
-
-;;; Hooks & Autoloads
-;;
-;; These let us watch various activities, and respond appropriately.
-
-;; (add-hook 'edebug-setup-hook
-;; (lambda ()
-;; (def-edebug-spec ede-with-projectfile
-;; (form def-body))))
-
(provide 'ede)
;; Include this last because it depends on ede.