diff options
Diffstat (limited to 'lisp/cedet/ede/locate.el')
-rw-r--r-- | lisp/cedet/ede/locate.el | 328 |
1 files changed, 328 insertions, 0 deletions
diff --git a/lisp/cedet/ede/locate.el b/lisp/cedet/ede/locate.el new file mode 100644 index 00000000000..100618a86c6 --- /dev/null +++ b/lisp/cedet/ede/locate.el @@ -0,0 +1,328 @@ +;;; ede/locate.el --- Locate support + +;; Copyright (C) 2008, 2009 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: +;; +;; Support for various LOCATE type functions. +;; +;; A key feature of EDE is `ede-expand-filename', which allows a +;; project to expand a filename reference in one file to some actual +;; filename. +;; +;; In that way, you may #include <foo.h>, and without knowing how to +;; read a Makefile, find it in <root>/include/foo.h. +;; +;; Some projects are regular, such as the Emacs project. Some +;; projects are completely controlled by EDE, such sh the Project.ede +;; based projects. +;; +;; For other projects, haveing a "quick hack" to support these location +;; routines is handy. +;; +;; The baseclass `ede-locate-base' provides the abstract interface to +;; finding files in a project. +;; +;; New location routines will subclass `ede-locate-base'. +;; +;; How to use: +;; +;; Configure `ede-locate-setup-options' to add the types of locate +;; features you have available. EDE will then enable the correct one +;; when it is available. + +(require 'ede) +(eval-when-compile (require 'data-debug) + (require 'eieio-datadebug) + (require 'cedet-global) + (require 'cedet-idutils) + (require 'cedet-cscope)) + +(require 'locate) + +;;; Code: +(defcustom ede-locate-setup-options + '(ede-locate-base) + "List of locate objects to try out by default. +Listed in order of preference. If the first item cannot be used in +a particular project, then the next one is tried. +It is always assumed that `ede-locate-base' is at end of the list." + :group 'ede + :type '(repeat + (choice (const :tag "None" ede-locate-base) + (const :tag "locate" ede-locate-locate) + (const :tag "GNU Global" ede-locate-global) + (const :tag "ID Utils" ede-locate-idutils) + (const :tag "CScope" ede-locate-cscope))) + ) + +;;;###autoload +(defun ede-enable-locate-on-project (&optional project) + "Enable an EDE locate feature on PROJECT. +Attempt to guess which project locate style to use +based on `ede-locate-setup-options'." + (interactive) + (let* ((proj (or project (ede-toplevel))) + (root (ede-project-root-directory proj)) + (opts ede-locate-setup-options) + (ans nil)) + (while (and opts (not ans)) + (when (ede-locate-ok-in-project (car opts) root) + ;; If interactive, check with the user. + (when (or (not (interactive-p)) + (y-or-n-p (format "Set project locator to %s? " (car opts)))) + (setq ans (car opts)))) + (setq opts (cdr opts))) + ;; No match? Always create the baseclass for the hashing tool. + (when (not ans) + (when (interactive-p) + (message "Setting locator to ede-locate-base")) + (setq ans 'ede-locate-base)) + (oset proj locate-obj (make-instance ans "Loc" :root root)) + (when (interactive-p) + (message "Satting locator to %s." ans)) + )) + +;;; LOCATE BASECLASS +;; +;; The baseclass for all location style queries. +(defclass ede-locate-base () + ((root :initarg :root + :documentation + "The root of these locat searches.") + (file :documentation + "The last file search for with EDE locate.") + (lastanswer :documentation + "The last answer provided by the locator.") + (hash :documentation + "Hash table of previously found files.") + ) + "Baseclass for LOCATE feature in EDE.") + +(defmethod initialize-instance ((loc ede-locate-base) &rest fields) + "Make sure we have a hash table." + ;; Basic setup. + (call-next-method) + ;; Make sure we have a hash table. + (oset loc hash (make-hash-table :test 'equal)) + ) + +(defmethod ede-locate-ok-in-project :static ((loc ede-locate-base) + root) + "Is it ok to use this project type under ROOT." + t) + +(defmethod ede-locate-file-in-hash ((loc ede-locate-base) + filestring) + "For LOC, is the file FILESTRING in our hashtable?" + (gethash filestring (oref loc hash))) + +(defmethod ede-locate-add-file-to-hash ((loc ede-locate-base) + filestring fullfilename) + "For LOC, add FILESTR to the hash with FULLFILENAME." + (puthash filestring fullfilename (oref loc hash))) + +(defmethod ede-locate-file-in-project ((loc ede-locate-base) + filesubstring + ) + "Locate with LOC occurances of FILESUBSTRING. +Searches are done under the current root of the EDE project +that crated this ede locat object." + (let ((ans (ede-locate-file-in-project-impl loc filesubstring)) + ) + (oset loc file filesubstring) + (oset loc lastanswer ans) + ans)) + +(defmethod ede-locate-file-in-project-impl ((loc ede-locate-base) + filesubstring + ) + "Locate with LOC occurances of FILESUBSTRING. +Searches are done under the current root of the EDE project +that crated this ede locat object." + nil + ) + +;;; LOCATE +;; +;; Using the standard unix "locate" command. +;; Since locate is system wide, we need to hack the search +;; to restrict it to within just this project. + +(defclass ede-locate-locate (ede-locate-base) + () + "EDE Locator using the locate command. +Configure the Emacs `locate-program' variable to also +configure the use of EDE locate.") + +(defmethod ede-locate-ok-in-project :static ((loc ede-locate-locate) + root) + "Is it ok to use this project type under ROOT." + (or (featurep 'locate) (locate-library "locate")) + ) + +(defmethod ede-locate-file-in-project-impl ((loc ede-locate-locate) + filesubstring) + "Locate with LOC occurances of FILESUBSTRING under PROJECTROOT. +Searches are done under the current root of the EDE project +that crated this ede locat object." + ;; We want something like: + ;; /my/project/root*/filesubstring.c + (let* ((searchstr (concat (directory-file-name (oref loc root)) + "*/" filesubstring)) + (b (get-buffer-create "*LOCATE*")) + (cd default-directory) + ) + (save-excursion + (set-buffer b) + (setq default-directory cd) + (erase-buffer)) + (apply 'call-process locate-command + nil b nil + searchstr nil) + (save-excursion + (set-buffer b) + (split-string (buffer-string) "\n" t)) + ) + ) + +;;; GLOBAL +;; +(defclass ede-locate-global (ede-locate-base) + () + "EDE Locator using GNU Global. +Configure EDE's use of GNU Global through the cedet-global.el +variable `cedet-global-command'.") + +(defmethod initialize-instance ((loc ede-locate-global) + &rest slots) + "Make sure that we can use GNU Global." + (require 'cedet-global) + ;; Get ourselves initialized. + (call-next-method) + ;; Do the checks. + (cedet-gnu-global-version-check) + (let* ((default-directory (oref loc root)) + (root (cedet-gnu-global-root))) + (when (not root) + (error "Cannot use GNU Global in %s" + (oref loc root)))) + ) + +(defmethod ede-locate-ok-in-project :static ((loc ede-locate-global) + root) + "Is it ok to use this project type under ROOT." + (require 'cedet-global) + (cedet-gnu-global-version-check) + (let* ((default-directory root) + (newroot (cedet-gnu-global-root))) + newroot)) + +(defmethod ede-locate-file-in-project-impl ((loc ede-locate-global) + filesubstring) + "Locate with LOC occurances of FILESUBSTRING under PROJECTROOT. +Searches are done under the current root of the EDE project +that crated this ede locat object." + (require 'cedet-global) + (let ((default-directory (oref loc root))) + (cedet-gnu-global-expand-filename filesubstring))) + +;;; IDUTILS +;; +(defclass ede-locate-idutils (ede-locate-base) + () + "EDE Locator using IDUtils. +Configure EDE's use of IDUtils through the cedet-idutils.el +file name searching variable `cedet-idutils-file-command'.") + +(defmethod initialize-instance ((loc ede-locate-idutils) + &rest slots) + "Make sure that we can use IDUtils." + ;; Get ourselves initialized. + (call-next-method) + ;; Do the checks. + (require 'cedet-idutils) + (cedet-idutils-version-check) + (when (not (cedet-idutils-support-for-directory (oref loc root))) + (error "Cannot use IDUtils in %s" + (oref loc root))) + ) + +(defmethod ede-locate-ok-in-project :static ((loc ede-locate-idutils) + root) + "Is it ok to use this project type under ROOT." + (require 'cedet-idutils) + (cedet-idutils-version-check) + (when (cedet-idutils-support-for-directory root) + root)) + +(defmethod ede-locate-file-in-project-impl ((loc ede-locate-idutils) + filesubstring) + "Locate with LOC occurances of FILESUBSTRING under PROJECTROOT. +Searches are done under the current root of the EDE project +that crated this ede locat object." + (require 'cedet-idutils) + (let ((default-directory (oref loc root))) + (cedet-idutils-expand-filename filesubstring))) + +;;; CSCOPE +;; +(defclass ede-locate-cscope (ede-locate-base) + () + "EDE Locator using Cscope. +Configure EDE's use of Cscope through the cedet-cscope.el +file name searching variable `cedet-cscope-file-command'.") + +(defmethod initialize-instance ((loc ede-locate-cscope) + &rest slots) + "Make sure that we can use Cscope." + ;; Get ourselves initialized. + (call-next-method) + ;; Do the checks. + (cedet-cscope-version-check) + (when (not (cedet-cscope-support-for-directory (oref loc root))) + (error "Cannot use Cscope in %s" + (oref loc root))) + ) + +(defmethod ede-locate-ok-in-project :static ((loc ede-locate-cscope) + root) + "Is it ok to use this project type under ROOT." + (cedet-cscope-version-check) + (when (cedet-cscope-support-for-directory root) + root)) + +(defmethod ede-locate-file-in-project-impl ((loc ede-locate-cscope) + filesubstring) + "Locate with LOC occurances of FILESUBSTRING under PROJECTROOT. +Searches are done under the current root of the EDE project +that crated this ede locat object." + (let ((default-directory (oref loc root))) + (cedet-cscope-expand-filename filesubstring))) + +(provide 'ede/locate) + +;; Local variables: +;; generated-autoload-file: "loaddefs.el" +;; generated-autoload-feature: ede/loaddefs +;; generated-autoload-load-name: "ede/locate" +;; End: + +;;; ede/locate.el ends here |