Changeset 29455

Show
Ignore:
Timestamp:
02/03/09 03:53:34 (4 years ago)
Author:
imakado
Message:

TAGS

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • lang/elisp/php-completion/trunk/php-completion.el

    r29355 r29455  
    6868(require 'browse-url) 
    6969(require 'url-util) 
     70(require 'etags) 
    7071 
    7172(require 'anything) 
     
    314315       :callback (lambda () 
    315316                   (kill-buffer buf-name)))))) 
     317 
     318;;; Etags 
     319;; Struct phpcmp-tag 
     320;; tag-file: TAGSファイルのパス 
     321 
     322;; path: fileのfullpath 
     323 
     324;; classes: 
     325;; (("classname" . ("method" "method1" "method2")) 
     326;;  ("classname1" . ("method" "method1" "method2"))) 
     327;; のような構造の association list 
     328 
     329;; functions: 関数のリスト 
     330 
     331;; variables: 変数のリスト 
     332(defstruct (phpcmp-tag 
     333            (:constructor phpcmp-make-tag 
     334                          (&key tag-file path relative-path  classes functions variables)) 
     335            (:type list)) 
     336  tag-file path relative-path classes functions variables) 
     337 
     338(defstruct (phpcmp-class 
     339            (:constructor phpcmp-make-class 
     340                          (&key name parent methods variables)) 
     341            (:type list)) 
     342  name parent methods variables) 
     343 
     344;; this function is copied from anything-etags.el 
     345(defvar phpcmp-etags-tag-file-name "TAGS") 
     346(defvar phpcmp-etags-tag-file-search-limit 10) 
     347(defun phpcmp-etags-find-tag-file () 
     348  "Return tags file. 
     349If file is not found, return nil" 
     350  (let ((file-exists? (lambda (dir) 
     351                        (let ((tag-path (concat dir phpcmp-etags-tag-file-name))) 
     352                          (and (stringp tag-path) 
     353                               (file-exists-p tag-path) 
     354                               (file-readable-p tag-path))))) 
     355        (current-dir (phpcmp-get-current-directory))) 
     356    (ignore-errors 
     357      (loop with count = 0 
     358            until (funcall file-exists? current-dir) 
     359            ;; Return nil if outside the value of 
     360            ;; `phpcmp-etags-tag-file-search-limit'. 
     361            if (= count phpcmp-etags-tag-file-search-limit) 
     362            do (return nil) 
     363            ;; Or search upper directories. 
     364            else 
     365            do (progn (incf count) 
     366                      (setq current-dir (expand-file-name (concat current-dir "../")))) 
     367            finally return (concat current-dir phpcmp-etags-tag-file-name))))) 
     368 
     369(defun phpcmp-etags-get-tags () 
     370  "Return list of struct `phpcmp-tag'" 
     371  (let ((tag-file (phpcmp-etags-find-tag-file))) 
     372    (when tag-file 
     373      (with-temp-buffer 
     374        (insert-file-contents tag-file) 
     375        (phpcmp-etags-parse-tags-buffer tag-file) 
     376        )))) 
     377 
     378;; This monster regexp matches an etags tag line. 
     379;;   \1 is the string to match; 
     380;;   \2 is not interesting; 
     381;;   \3 is the guessed tag name; XXX guess should be better eg DEFUN 
     382;;   \4 is not interesting; 
     383;;   \5 is the explicitly-specified tag name. 
     384;;   \6 is the line to start searching at; 
     385;;   \7 is the char to start searching at. 
     386(defvar phpcmp-etags-parse-tags-file-regexp 
     387  (rx bol 
     388      (group                                             ;1 
     389       (regexp "\\([^\177]+[^-a-zA-Z0-9_+*$:\177]+\\)?") ;2 
     390       (regexp "\\([-a-zA-Z0-9_+*$?:]+\\)")              ;3 
     391       (regexp "[^-a-zA-Z0-9_+*$?:\177]*")) 
     392      "\177" 
     393      (regexp "\\(\\([^\n\001]+\\)\001\\)?") ;4, 5 
     394 
     395      (regexp "\\([0-9]+\\)?")               ;6 
     396      "," 
     397      (regexp "\\([0-9]+\\)?")               ;7 
     398      "\n" 
     399      )) 
     400 
     401(defun phpcmp-etags-split-each-file (s) 
     402  (split-string s "\14[ \n]+")) 
     403 
     404(defun phpcmp-etags-parse-tags-buffer (tag-file) 
     405  (let ((each-file-tag-strings 
     406         (delete "" (split-string (buffer-string) "\14[ \n]+")))) 
     407    (loop for s in each-file-tag-strings 
     408          collect (phpcmp-deftag s tag-file)))) 
     409 
     410(defun phpcmp-deftag (tag-string tag-file) 
     411  (with-temp-buffer 
     412    (insert tag-string) 
     413    (goto-char (point-min)) 
     414    ;; Return struct `phpcmp-tag' 
     415    (phpcmp-deftag-parse tag-file))) 
     416 
     417(defun phpcmp-deftag-parse (tag-file) 
     418  (let ((relative-file-path (phpcmp-deftag-parse-file-info))) 
     419    (let (path relative-path classes functions variables) 
     420      (while (not (eobp)) 
     421        (cond 
     422         ((looking-at (rx bol (* space) "class")) 
     423          (push (phpcmp-deftag-parse-class) classes)) 
     424         ((looking-at phpcmp-etags-parse-tags-file-regexp) 
     425          (push (match-string 5) functions) 
     426          (forward-line)) 
     427         (t 
     428          (forward-line)))) 
     429      (phpcmp-make-tag 
     430       :tag-file tag-file 
     431       :path (concat (file-name-directory tag-file) 
     432                     relative-file-path) 
     433       :classes classes 
     434       :functions functions 
     435       :variables variables)))) 
     436 
     437(defun phpcmp-deftag-parse-file-info () 
     438  (when (looking-at (rx bol (group (+ (not (any ",")))) "," (? (* digit)) "\n")) 
     439    (let* ((relative-file-path (match-string 1))) 
     440      (prog1 relative-file-path 
     441        (forward-line))))) 
     442 
     443(defun phpcmp-deftag-parse-class () 
     444  (let ((class-str (phpcmp-take-same-indent-string)) 
     445        name parent methods variables) 
     446    (with-temp-buffer 
     447      (insert class-str) 
     448      (goto-char (point-min)) 
     449      (while (not (eobp)) 
     450        (cond 
     451         ((looking-at (rx bol (* space) "class" (? (*? not-newline) "extends" (+ space) (group (+ (any alpha "_")))))) 
     452          (let ((parent-class (match-string 1))) 
     453            (when parent-class 
     454              (setq parent parent-class))) 
     455          (when (looking-at phpcmp-etags-parse-tags-file-regexp) 
     456            (let ((class-name (match-string 5))) 
     457              (setq name class-name))) 
     458          (forward-line)) 
     459         ((looking-at (rx bol (* space) (? (or "public" "private")) (* space) "function")) 
     460          (when (looking-at phpcmp-etags-parse-tags-file-regexp) 
     461            (let ((function (match-string 5))) 
     462              (push function methods))) 
     463          (forward-line)) 
     464         ((looking-at (rx bol (* space) "$" (+ (any alnum "_")) (* space) "=")) 
     465          (when (looking-at phpcmp-etags-parse-tags-file-regexp) 
     466            (let ((variable (match-string 5))) 
     467              (push variable variables))) 
     468          (forward-line)) 
     469         (t 
     470          (forward-line))))) 
     471    (phpcmp-make-class 
     472     :name name 
     473     :parent parent 
     474     :methods methods 
     475     :variables variables))) 
     476 
     477(defun phpcmp-take-same-indent-string () 
     478  "move point" 
     479  (let ((cur-indent (current-indentation)) 
     480        (cur-point (point))) 
     481    (forward-line) 
     482    (buffer-substring-no-properties 
     483     cur-point 
     484     (loop while (and 
     485                  (not 
     486                   (>= cur-indent 
     487                       (current-indentation))) 
     488                  (not (eobp))) 
     489           do (forward-line) 
     490           finally return (point))))) 
    316491 
    317492 
     
    65496724  (phpcmp-async-set-functions)) 
    65506725 
     6726 
     6727 
     6728;;; Test 
     6729(defmacro phpcmp-with-string-buffer (s &rest body) 
     6730  `(with-temp-buffer 
     6731     (insert ,s) 
     6732     (goto-char (point-min)) 
     6733     (when (re-search-forward (rx "`!!'") nil t) 
     6734       (replace-match "")) 
     6735     (progn 
     6736       ,@body))) 
     6737 
     6738(dont-compile 
     6739  (when (fboundp 'expectations) 
     6740    (expectations 
     6741      (desc "phpcmp-take-same-indent-string") 
     6742      (expect "class AdminController extends Zend_Controller_ActionAdminController22,556 
     6743  public function init()init35,1051 
     6744" 
     6745        (phpcmp-with-string-buffer  
     6746       "`!!'class AdminController extends Zend_Controller_ActionAdminController22,556 
     6747  public function init()init35,1051 
     6748function" 
     6749       (phpcmp-take-same-indent-string))) 
     6750 
     6751       
     6752      ))) 
     6753 
     6754 
     6755 
    65516756(provide 'php-completion)