Changeset 19148 for lang/elisp

Show
Ignore:
Timestamp:
09/11/08 04:47:57 (2 months ago)
Author:
imakado
Message:

perl-completion.el version 1.0 が動作するようになってきたのでbranchにコミット

Location:
lang/elisp/perl-completion/branch/1.0
Files:
1 modified
1 copied

Legend:

Unmodified
Added
Removed
  • lang/elisp/perl-completion/branch/1.0/perl-completion.el

    r15428 r19148  
    33 
    44;; Author: Kenji.Imakado <ken.imakaado@gmail.com> 
    5 ;; Version: 0.3 
    65;; Keywords: perl 
    76 
     
    2120;; Boston, MA 02110-1301, USA. 
    2221 
     22;; Prefix: plcmp- 
     23 
    2324;;; Commentary: 
    2425;; Tested on Emacs 22 
     
    2728;; M-x customize-group RET perl-completion RET 
    2829 
     30 
     31 
     32;;builtin variables:  
     33;; (search . ((lambda (re arg1 arg2) 
     34;;                  (re-search-forward (regexp-quote re) nil t)))) 
     35 
     36 
     37 
    2938;;;code: 
    30  
    3139(require 'cl) 
     40(require 'anything) 
    3241(require 'cperl-mode) 
    3342(require 'dabbrev) 
    3443(require 'rx) 
    3544 
    36 ;;; provide 
    37 (provide 'perl-completion) 
    38  
    39 ;;; group 
    4045(defgroup perl-completion nil 
    4146  "" 
    4247  :group 'perl-completion) 
    4348 
    44 ;;; customizable variables 
    45 (defcustom plcmp-anything-candidate-number-limit 1000 
    46   "補完候補の最大表示数 
    47 `anything-candidate-number-limit'と同じ" 
    48   :type 'number 
    49   :group 'perl-completion) 
    50  
    51 (defcustom plcmp-buffer-dabbrev-expansions-number 2 
    52   "バッファ内のdabbrevを候補に入れる文字数 
    53 initial-inputのlengthがこの数値より小さいと補完を行わない 
    54 注意、0(常に補完)に設定する事も可能ですが動作が遅くなる可能性があります" 
    55   :type 'number 
    56   :group 'perl-completion) ; TODO name and doc 
    57  
    58 (defcustom plcmp-get-words-other-perl-buf-limit-number 30 
    59   "補完対象にする他のperlバッファの最大数" 
    60   :type 'number 
    61   :group 'perl-completion) 
    62  
    63 (defcustom plcmp-config-modules-filter-list 
    64   '("strict" "warning") 
    65   "補完対象に含めないモジュール名のリスト 
    66 このリストに含まれているモジュールのメソッドは補完対象にならない" 
    67   :type '(repeat (string :tag "Module name")) 
    68   :group 'perl-completion) 
    69  
    70 (defcustom plcmp-dabbrev-abbrev-char-regexp "\\sw\\|\\s_\\|[:_]" 
    71   "dabbrevの候補になるcharを決めるregexp 
    72 `dabbrev-abbrev-char-regexp'にダイナミックにバインドされて使用される" 
    73   :type 'regexp 
    74   :group 'perl-completion) 
    75  
    76 (defcustom plcmp-match-only-real-candidate nil 
    77   "この変数がnon-nilだとパターンが実際の補完候補のみにマッチするようになる 
    78 例: nil(デフォルト)の場合、パターン\"agent\"は以下の両方の補完候補にマッチする 
    79 なぜなら\"UserAgent\"の部分に\"agent\"がマッチするからである 
    80 [LWP::UserAgent] | agent 
    81 [LWP::UserAgent] | clone 
    82 non-nilの場合は\"|\"以降の文字列のみにマッチする" 
    83   :type 'boolean 
    84   :group 'perl-completion) 
    85  
    86 ;;; const 
    87 (defconst plcmp-version 0.3) 
    88 (defconst plcmp-lang (cond ((string-match "japanese" (format "%s" locale-coding-system)) 'ja) 
    89                            (t 'english))) 
    90 (defconst plcmp-perlvar-output-buf-name "*perlvar output*") 
    91 (defconst plcmp-perlfunc-output-buf-name "*perlfunc output*") 
    92 (defconst plcmp-perldoc-output-buf-name "*perldoc output*") 
    93 (defconst plcmp-perl-ident-re "[a-zA-Z_][a-zA-Z_0-9]*") 
    94 (defconst plcmp-installed-modules-buf-name "*perl installed modules*") 
    95 (defconst plcmp-display-format-variables "buffer variable") 
    96 (defconst plcmp-display-format-functions "buffer function") 
    97 (defconst plcmp-display-format-dabbrev-expansions "buffer dabbrev") 
    98 (defconst plcmp-display-format-builtin-variables "builtin variable") 
    99 (defconst plcmp-display-format-builtin-functions "builtin function") 
    100 (defconst plcmp-display-format-using-modules "using module") 
    101 (defconst plcmp-display-format-installed-modules "installed module") 
    102 (defconst plcmp-get-installed-modules-command "find `perl -e 'pop @INC; print join(q{ }, @INC);'` -name '*.pm' -type f | xargs egrep -h -o 'package [a-zA-Z0-9:]+;' | perl -nle 's/package\s+(.+);/$1/; print' | sort | uniq ") ; 
    103 (defconst plcmp-get-installed-modules-async-command 
    104   (concat plcmp-get-installed-modules-command " &")) 
    105 (defconst plcmp-builtin-functions 
     49;;; variables 
     50(defvar plcmp-version 1.0) 
     51(defvar plcmp-perl-ident-re "[a-zA-Z_][a-zA-Z_0-9]*") 
     52(defvar plcmp-sub-re (rx-to-string `(and "sub" 
     53                                        (+ space) 
     54                                        (group 
     55                                         (regexp ,plcmp-perl-ident-re))))) 
     56(defvar plcmp-perl-package-re "[a-zA-Z0-9:]+") 
     57(defvar plcmp-builtin-functions 
    10658  '("abs" "exec" "glob" "order" "seek" "symlink" "accept" "exists" "gmtime" 
    10759    "our" "seekdir" "syscall" "alarm" "exit" "goto" "pack" "select" "sysopen" 
     
    13183    "ord" "scalar" "substr")) 
    13284 
    133 (defconst plcmp-builtin-variables 
     85(defvar plcmp-builtin-variables 
    13486  '("$SIG{expr}" "%SIG" "$ENV{expr}" "%ENV" "%INC" "@_" "@INC" "@F" "ARGVOUT" 
    13587    "@ARGV" "$ARGV" "ARGV" "$^X" "$EXECUTABLE_NAME" "${^WARNING_BITS}" "$^W" 
     
    157109    "$PREMATCH" "$&" "$MATCH" "$<digits>" "$b" "$a" "$_" "$ARG")) 
    158110 
    159 ;;; face 
    160 (defface plcmp-search-match 
    161   '((t (:background "grey15" :foreground "magenta" :underline t))) 
    162   "" 
    163   :group 'perl-completion 
    164   :tag "Plcmp Search Match Face") 
    165  
    166 ;;; struct 
    167 (defstruct (plcmp-completion-data (:constructor plcmp-make-completion-data)) 
    168   (initial-input "") 
    169   state 
    170   default-action-state 
    171   persistent-action-buffer-point 
    172   using-modules 
    173   current-buffer 
    174   current-object 
    175   current-package 
    176   cache-installed-modules 
    177   cache-using-modules 
    178   other-perl-buffers 
    179   obj-instance-of-module-maybe-alist 
    180   installed-modules) 
    181  
    182 ;;; variables 
    183 (defvar plcmp-data (plcmp-make-completion-data) "strunct") 
    184 (defvar plcmp-search-match-face 'plcmp-search-match) 
    185 (defvar plcmp-overlay nil) 
    186 (defvar plcmp-metadata-matcher-re (rx bol (* (not (any "|"))) "|" space (*? not-newline))) 
    187 (defvar plcmp-metadata-matcher "") 
    188  
    189 ;;; buffer local variables 
    190 (defvar plcmp-last-using-modules nil) 
    191 (make-variable-buffer-local 'plcmp-last-using-modules) 
    192 (defvar plcmp-modules-methods-alist nil) 
    193 (make-variable-buffer-local 'plcmp-modules-methods-alist) 
    194  
    195 ;;; anything's variables 
    196 (defvar plcmp-anything-sources nil) 
    197 (defvar plcmp-anything-enable-digit-shortcuts nil ) 
    198 (defvar plcmp-anything-candidate-number-limit plcmp-anything-candidate-number-limit ) 
    199 (defvar plcmp-anything-idle-delay 0.5 ) 
    200 (defvar plcmp-anything-samewindow nil ) 
    201 (defvar plcmp-anything-source-filter nil ) 
    202 (defvar plcmp-anything-isearch-map 
    203   (let ((map (copy-keymap (current-global-map)))) 
    204     (define-key map (kbd "<return>") 'plcmp-anything-isearch-default-action) 
    205     (define-key map (kbd "C-i") 'plcmp-anything-isearch-select-action) 
    206     (define-key map (kbd "C-g") 'plcmp-anything-isearch-cancel) 
    207     (define-key map (kbd "M-s") 'plcmp-anything-isearch-again) 
    208     (define-key map (kbd "<backspace>") 'plcmp-anything-isearch-delete) 
    209     (let ((i 32)) 
    210       (while (< i 256) 
    211         (define-key map (vector i) 'plcmp-anything-isearch-printing-char) 
    212         (setq i (1+ i)))) 
    213     map)) 
    214 (defgroup plcmp-anything nil 
    215   "Open plcmp-anything." :prefix "plcmp-anything-" :group 'convenience) 
    216 (if (facep 'header-line) 
    217     (copy-face 'header-line 'plcmp-anything-header) 
    218   (defface plcmp-anything-header 
    219     '((t (:bold t :underline t))) 
    220     "Face for header lines in the plcmp-anything buffer." :group 'plcmp-anything)) 
    221 (defvar plcmp-anything-header-face 'plcmp-anything-header ) 
    222 (defface plcmp-anything-isearch-match '((t (:background "Yellow"))) 
    223   "Face for isearch in the plcmp-anything buffer." :group 'plcmp-anything) 
    224 (defvar plcmp-anything-isearch-match-face 'plcmp-anything-isearch-match ) 
    225 (defvar plcmp-anything-iswitchb-idle-delay 1 ) 
    226 (defvar plcmp-anything-iswitchb-dont-touch-iswithcb-keys nil ) 
    227 (defconst plcmp-anything-buffer "*perl-completion anything*" ) 
    228 (defvar plcmp-anything-selection-overlay nil ) 
    229 (defvar plcmp-anything-isearch-overlay nil ) 
    230 (defvar plcmp-anything-digit-overlays nil ) 
    231 (defvar plcmp-anything-candidate-cache nil ) 
    232 (defvar plcmp-anything-pattern "") 
    233 (defvar plcmp-anything-input "") 
    234 (defvar plcmp-anything-async-processes nil ) 
    235 (defvar plcmp-anything-digit-shortcut-count 0 ) 
    236 (defvar plcmp-anything-update-hook nil ) 
    237 (defvar plcmp-anything-saved-sources nil ) 
    238 (defvar plcmp-anything-saved-selection nil ) 
    239 (defvar plcmp-anything-original-source-filter nil ) 
    240  
    241 ;;; hack variables 
    242 ;; idea: http://www.emacswiki.org/cgi-bin/wiki/RubikitchAnythingConfiguration 
    243 (defvar plcmp-anything-saved-action nil 
    244   "Saved value of the currently selected action by key.") 
    245  
    246 (defvar plcmp-anything-matched-candidate-cache nil 
    247   "(name . ((pattern . (list of string)) 
    248             (pattern . (list of string)))) ") 
    249  
    250 ;;; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
    251 ;;; Utilities 
    252 ;;; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
    253  
    254 (defmacro plcmp-with-slots (struct conc-name slots &rest body) 
    255   `(symbol-macrolet ,(loop for slot in slots 
    256                            collect `(,slot (,(intern (concat (symbol-name conc-name) (symbol-name slot))) ,struct))) 
    257      ,@body)) 
    258 (def-edebug-spec plcmp-with-slots (symbolp symbolp (&rest symbolp) body)) ;TODO 
    259    
    260 (defmacro plcmp-with-completion-data-slots (struct slots &rest body) 
    261   (declare (indent 2)) 
    262   `(plcmp-with-slots ,struct plcmp-completion-data- ,slots ,@body)) 
    263 (def-edebug-spec plcmp-with-completion-data-slots (symbolp (&rest symbolp) body)) 
    264    
    265 (defmacro plcmp-with-gensyms (symbols &rest body) 
    266   (declare (indent 1)) 
    267   `(let ,(mapcar (lambda (sym) 
    268                    `(,sym (gensym))) 
    269                  symbols) 
    270      ,@body)) 
    271  
    272 (defmacro plcmp-my (var val &rest body) 
    273   (declare (indent 2)) 
    274   `(lexical-let ((,var ,val)) 
    275      ,@body)) 
    276  
    277 (put 'plcmp-acond 'lisp-indent-function 'defun) ;TODO 
    278 (defmacro plcmp-acond (&rest clauses) 
    279   (unless (null clauses) 
    280     (plcmp-with-gensyms (sym) 
    281       (plcmp-my clause (car clauses) 
    282         `(plcmp-my ,sym ,(car clause) 
    283            (if ,sym 
    284                (plcmp-my it ,sym 
    285                  ,@(cdr clause))        ;expr 
    286              (plcmp-acond ,@(cdr clauses)))))))) 
    287 (def-edebug-spec plcmp-acond cond) 
    288  
     111(defvar plcmp-cleanup-hook nil "hook run when completion command finished") 
     112 
     113;;; macros 
     114 
     115(defmacro plcmp-aif (test-form then-form &optional else-form) 
     116  "Anaphoric if. Temporary variable `it' is the result of test-form." 
     117  `(let ((it ,test-form)) 
     118     (if it ,then-form ,else-form))) 
     119(put 'plcmp-aif 'lisp-indent-function 2) 
     120 
     121 
     122(defmacro define-plcmp-command (command-name-with-no-prefix args &rest body) 
     123  (let* ((prefix "plcmp-cmd-") 
     124         (command-str (symbol-name command-name-with-no-prefix)) 
     125         (command-name (concat prefix command-str))) 
     126    `(defun* ,(intern command-name) ,args 
     127       (interactive) 
     128       (unwind-protect 
     129           (progn (plcmp-initialize-variables) 
     130                  (progn 
     131                    ,@body)) 
     132         (plcmp-cleanup))))) 
     133(put 'define-plcmp-command 'lisp-indent-function 'defun) 
     134(def-edebug-spec define-plcmp-command defun*) 
     135 
     136(defmacro plcmp-ignore-errors (&rest body) 
     137  `(condition-case e (progn ,@body) 
     138     (error (plcmp-log "Error plcmp-ignore-errors :  %s" (error-message-string e))))) 
     139(def-edebug-spec plcmp-ignore-errors ignore-errors) 
     140 
     141;;; Util functions 
    289142(defsubst plcmp-trim (s) 
    290143  "strip space and newline" 
     
    292145   "[ \t\n]*$" "" (replace-regexp-in-string "^[ \t\n]*" "" s))) 
    293146 
    294 (defun plcmp-get-preceding-string (&optional count) 
    295   "現在の位置からcount文字前方位置までの文字列を返す 
    296 例外を出さない" 
    297   (let ((count (or count 1))) 
    298     (buffer-substring-no-properties 
    299      (point) 
    300      (condition-case nil 
    301          (save-excursion (backward-char count) (point)) 
    302        (error (point)))))) 
     147(defsubst plcmp-bit-regexp-p (s) 
     148  (string-match "^[/:$@&%(),.?<>+!|^*';\"\\]+$" s)) 
    303149 
    304150(defsubst plcmp-module-p (s) 
    305   (string-match "^[a-zA-Z:_]+$" s)) 
     151  (string-match "^[a-zA-Z:]+$" s)) 
    306152 
    307153(defsubst plcmp-perl-identifier-p (s) 
    308154  (string-match (concat "^" plcmp-perl-ident-re "$") s)) 
    309155 
    310 (defun plcmp-notfound-p (s) 
     156(defsubst plcmp-notfound-p (s) 
    311157  (string-match "^Can't locate [^ \t]+ in" s)) 
    312158 
    313 (defmacro plcmp-ignore-errors (&rest body) 
    314   `(condition-case e (progn ,@body) 
    315      (error (plcmp-log "Error plcmp-ignore-errors :  %s" (error-message-string e))))) 
    316  
    317 ;; idea: anything-dabbrev-expand.el 
    318 (lexical-let ((store-times 0)) 
    319   (defun plcmp-seq-times (command-name &optional max) 
    320     (let ((max (or max -99))) 
    321       (if (eq last-command command-name) 
    322           (if (= (incf store-times) max) 
    323               (setq store-times 0) 
    324             store-times) 
    325         (setq store-times 0))))) 
     159(defsubst plcmp-tramp-p () 
     160  (when (and (featurep 'tramp) 
     161             (fboundp 'tramp-tramp-file-p)) 
     162    (tramp-tramp-file-p (plcmp-get-current-directory)))) 
     163 
     164(defsubst plcmp-insert-each-line (los) 
     165  (insert (mapconcat 'identity los "\n"))) 
     166 
     167(defun plcmp-get-current-directory () 
     168  (file-name-directory 
     169   (expand-file-name 
     170    (or (buffer-file-name) 
     171        default-directory)))) 
     172 
     173(defun plcmp-re-sort-sources (re sources) 
     174  "regexp RE にnameがマッチするsourceを先頭に並び替えたsourcesを返す" 
     175  (let ((match-source 
     176         (find-if (lambda (source) 
     177                    (let* ((source (if (listp source) source (symbol-value source))) 
     178                           (name (assoc-default 'name source 'eq))) 
     179                      (when (string-match re name) 
     180                        source))) 
     181                  sources))) 
     182    (if match-source 
     183        (cons match-source (remove match-source sources)) 
     184      sources))) 
    326185 
    327186;;; log 
     
    342201 
    343202 
    344 ;;;; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
    345 ;;;; Initialize 
    346 ;;;; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
    347  
    348 ;; idea: http://subtech.g.hatena.ne.jp/antipop/20070917/1190009355 
    349 (defun plcmp-get-installed-modules-synchronously () 
    350   (message "fetching installed modules...") 
    351   (let ((modules (split-string (shell-command-to-string plcmp-get-installed-modules-command) "\n"))) 
    352     (message "fetching installed modules done") 
    353     (remove-if (lambda (module) 
    354                  (string-match "No such file or directory$" module)) 
    355                modules))) 
    356  
    357 (defun plcmp-get-installed-modules-from-buf (buf) 
    358   (with-current-buffer buf 
    359     (let ((modules (split-string (buffer-substring-no-properties (point-min) (point-max)) "\n"))) 
     203(defvar plcmp-initial-input "") 
     204(defvar plcmp-real-initial-input "") 
     205(defun plcmp-get-initial-input () 
     206  (let ((initial-input (buffer-substring-no-properties 
     207                        (point) 
     208                        (save-excursion (skip-syntax-backward "w_") 
     209                                        (point))))) 
     210    (setq plcmp-real-initial-input initial-input) ;; `plcmp-insert' 
     211    (concat initial-input 
     212            (if (featurep 'anything-match-plugin) 
     213                " " 
     214              "")))) 
     215 
     216;;; installed modules 
     217(defvar plcmp-installed-modules nil) 
     218(defun plcmp-get-installed-modules () 
     219  (or plcmp-installed-modules 
     220      (setq plcmp-installed-modules (plcmp--installed-modules-synchronously)))) 
     221 
     222(defun plcmp--installed-modules-synchronously () 
     223  (unless (plcmp-tramp-p) 
     224    (message "fetching installed modules...") 
     225    (let* ((modules-str (shell-command-to-string 
     226                         (concat 
     227                          "find `perl -e 'pop @INC; print join(q{ }, @INC);'`" 
     228                          " -name '*.pm' -type f " 
     229                          "| xargs egrep -h -o 'package [a-zA-Z0-9:]+;' " 
     230                          "| perl -nle 's/package\s+(.+);/$1/; print' " 
     231                          "| sort " 
     232                          "| uniq "))) 
     233           (modules (split-string modules-str "\n"))) 
     234      (message "done") 
    360235      (remove-if (lambda (module) 
    361236                   (string-match "No such file or directory$" module)) 
    362237                 modules)))) 
    363  
    364 (defun plcmp-send-command-get-installed-modules () 
    365   (message "send command to get installed modules") 
    366   (save-window-excursion 
    367     (shell-command plcmp-get-installed-modules-async-command plcmp-installed-modules-buf-name)) 
    368   (with-current-buffer plcmp-installed-modules-buf-name 
    369     (setq buffer-read-only t))) 
    370  
    371 (defun plcmp-fetch-installed-modules (struct) 
    372   (plcmp-with-completion-data-slots struct 
    373       (cache-installed-modules) 
    374     (let ((buf (get-buffer plcmp-installed-modules-buf-name))) 
    375       (cond 
    376        ((null cache-installed-modules) 
    377         (if (and (buffer-live-p buf) 
    378                  (not (processp (get-buffer-process buf)))) ;finished 
    379             (setf cache-installed-modules (plcmp-get-installed-modules-from-buf buf)) 
    380           (unless (buffer-live-p buf) 
    381             (plcmp-send-command-get-installed-modules)) 
    382           (plcmp-get-installed-modules-synchronously))) 
    383        ;; return cache 
    384        (t 
    385         cache-installed-modules))))) 
    386  
    387 (defun plcmp-get-current-package () 
     238   
     239;;; current package 
     240(defvar plcmp-current-package-name "") 
     241(defun plcmp-get-current-package-name () 
    388242  "nil or string" 
    389   (let ((re (concat "^[ \t]*package\\s *" "\\([a-zA-Z:]+\\)" ".*;$")) 
    390         (limit 500)) 
     243  (let ((re (rx-to-string `(and bol 
     244                                (* space) 
     245                                "package" 
     246                                (* space) 
     247                                (group 
     248                                 (regexp ,plcmp-perl-package-re)) 
     249                                (* not-newline) 
     250                                ";")))) 
    391251    (save-excursion 
    392252      (goto-char (point-min)) 
    393       (when (re-search-forward re limit t) 
    394         (match-string-no-properties 1))))) 
    395  
     253      (when (re-search-forward re nil t) 
     254        (setq plcmp-current-package-name 
     255              (match-string-no-properties 1)))))) 
     256 
     257(defvar plcmp-using-modules nil) 
    396258(defun plcmp-get-using-modules () 
    397   (let ((re "^[ \t]*use[ \t]+\\([a-zA-Z:_]+\\)\\s *[^;\n]*;") ;todo 
    398         (ret nil)) 
     259  (let* ((re (rx-to-string `(and bol 
     260                                 (* space) 
     261                                 "use" 
     262                                 (+ space) 
     263                                 (group 
     264                                  (regexp ,plcmp-perl-package-re)) 
     265                                 (* not-newline) 
     266                                 ";")))) 
    399267    (save-excursion 
    400       (goto-char (point-min)) 
    401       (loop always (re-search-forward re nil t) 
    402             do (add-to-list 'ret (match-string-no-properties 1)))) 
    403  
    404     ;; filter plcmp-config-modules-filter-list 
    405     (setq ret (set-difference ret plcmp-config-modules-filter-list :test 'string-equal)) 
    406     (plcmp-log "get-using-modules: %S" ret) 
    407     ret)) 
    408  
    409 ;;(plcmp-sort-methods '("_asdf" "asdf" "bsd" "_bsd" "ASDF")) 
    410 ;; => ("ASDF" "asdf" "bsd" "_asdf" "_bsd") 
    411 (defun plcmp-sort-methods (los) 
    412   (loop for s in los 
    413         if (string-match (rx bol "_") s) 
    414         collect s into unders 
    415         else 
    416         collect s into methods 
    417         finally return (nconc methods unders))) 
    418  
    419 (defsubst plcmp-inspect-methods (module) 
     268      (loop initially (goto-char (point-min)) 
     269            while (re-search-forward re nil t) 
     270            collect (match-string-no-properties 1))))) 
     271 
     272;;; methods 
     273(defvar plcmp-obj-instance-of-module-maybe-alist nil) 
     274(defun plcmp-get-obj-instance-of-module-maybe-alist (using-modules) 
     275  (let* ((using-module-re (regexp-opt using-modules)) 
     276         (re (rx-to-string `(and (group "$" ;1 
     277                                  (regexp ,plcmp-perl-ident-re)) 
     278                                 (* space) 
     279                                 "=" 
     280                                 (* space) 
     281                                 (group      ;2 
     282                                  (regexp ,using-module-re)))))) 
     283    (save-excursion 
     284      (loop initially (goto-char (point-min)) 
     285            while (re-search-forward re nil t) 
     286            collect `(,(match-string-no-properties 1) . ,(match-string-no-properties 2)))))) 
     287 
     288(defsubst plcmp--make-los (str) 
     289  (with-temp-buffer 
     290    (insert str) 
     291    (loop initially (goto-char (point-min)) 
     292          while (re-search-forward plcmp-perl-ident-re nil t) 
     293          collect (match-string-no-properties 0)))) 
     294 
     295(defsubst plcmp--inspect-module-class-inspector (module-name) 
    420296  "Class::Inspectorを使用してモジュールのメソッド調べる。 
    421 モジュール名に使用できる文字以外が含まれていた場合はnilを返す 
    422 return los" 
     297モジュール名に使用でき-る文字以外が含まれていた場合はnilを返す 
     298return alist (module-name . list of methods)" 
     299  (when (plcmp-module-p module-name) 
     300    (let ((modules-str 
     301           (shell-command-to-string 
     302            (concat "perl -MClass::Inspector -e'use " 
     303                    module-name 
     304                    "; print join \"\n\"=>@{Class::Inspector->methods(" 
     305                    module-name 
     306                    ")} '")))) 
     307      (when (and (not (plcmp-notfound-p modules-str)) 
     308                 (stringp modules-str)) 
     309        (let ((modules (plcmp--make-los modules-str))) 
     310          `(,module-name . ,modules)))))) 
     311 
     312(defsubst plcmp-get-buffer-subs () 
     313  (let ((re plcmp-sub-re)) 
     314    (save-excursion 
     315      (loop initially (goto-char (point-min)) 
     316            while (re-search-forward re nil t) 
     317            collect (match-string-no-properties 1))))) 
     318 
     319(defun plcmp--inspect-module-scrape (module-name) 
     320  (when (and (stringp module-name) 
     321             (plcmp-module-p module-name)) 
     322    (let* ((path (shell-command-to-string (concat "perldoc -l " 
     323                                                  module-name))) 
     324           (path (plcmp-trim path))) 
     325      (when (and (stringp path) 
     326                 (file-exists-p path) 
     327                 (file-readable-p path)) 
     328        (with-temp-buffer 
     329          (insert-file-contents path) 
     330          (plcmp-get-buffer-subs)))))) 
     331 
     332(defsubst plcmp--inspect-module (module-name) 
     333  (or (plcmp--inspect-module-class-inspector module-name) 
     334      (plcmp--inspect-module-scrape module-name))) 
     335 
     336 
     337(defvar plcmp-module-methods-alist nil 
     338  "alist, (module-name . (list of methods))") 
     339(defun plcmp-get-module-methods-alist (using-modules) 
     340  (dolist (module-name using-modules) 
     341    (unless (assoc module-name plcmp-module-methods-alist) 
     342      (add-to-list 'plcmp-module-methods-alist 
     343                   (plcmp--inspect-module module-name)))) 
     344  plcmp-module-methods-alist) 
     345 
     346 
     347;; module-name -> source 
     348(defun plcmp--mk-module-source (module-name) 
     349  (plcmp-aif (assoc-default module-name plcmp-module-methods-alist) 
     350      `((name . ,(concat module-name " Methods")) 
     351        (type . plcmp-completion) 
     352        (init . (lambda () 
     353                  (with-current-buffer (anything-candidate-buffer 'global) 
     354                    (plcmp-insert-each-line ',it)))) 
     355        (candidates-in-buffer)))) 
     356 
     357 
     358;; plcmp-using-modules -> sources 
     359(defun plcmp-get-methods-completion-sources (using-modules) 
     360  (loop for module-name in using-modules 
     361        collect (plcmp--mk-module-source module-name))) 
     362 
     363 
     364;;; dabbrev 
     365(defvar plcmp-buffer-dabbrevs-re 
     366  (rx (>= 4 (or (syntax word) 
     367                (syntax symbol))))) 
     368(defsubst* plcmp-get-buffer-dabbrevs (&optional (re plcmp-buffer-dabbrevs-re)) 
     369  (save-excursion 
     370    (loop initially (goto-char (point-min)) 
     371          while (re-search-forward re nil t) 
     372          collect (match-string-no-properties 0)))) 
     373 
     374;;; current buffer words 
     375(defsubst* plcmp-get-face-words (&optional (faces '(font-lock-variable-name-face 
     376                                                    font-lock-function-name-face))) 
     377  (let ((hash (make-hash-table :test 'equal))) 
     378    (save-excursion 
     379      (loop initially (goto-char (point-min)) 
     380            for next-change = (or (next-property-change (point) (current-buffer)) 
     381                                  (point-max)) 
     382            until (eobp) 
     383            do (progn (when (plcmp-check-face faces) 
     384                        (plcmp-aif (cperl-word-at-point) 
     385                            (puthash it nil hash))) 
     386                      (goto-char next-change))) 
     387      (let ((ret)) 
     388        (maphash (lambda (k v) (push k ret)) hash) 
     389        ret)))) 
     390 
     391(defvar plcmp-current-buffer-words-alist nil 
     392  "alist, ((variable . (list of variables)) 
     393 (array . (list of arrays)) 
     394 (hash . (list of hashes)) 
     395 (functions . (list of functions)))") 
     396(add-hook 'plcmp-cleanup-hook (lambda () (setq plcmp-current-buffer-words-alist nil))) 
     397 
     398;; (with-current-buffer "Plagger.pm" 
     399;;   (plcmp-get-face-words '(font-lock-variable-name-face))) 
     400 
     401 
     402(defun plcmp-get-current-buffer-words-alist () 
     403  (or plcmp-current-buffer-words-alist 
     404      (let ((variables (plcmp-get-face-words '(font-lock-variable-name-face))) 
     405            (arrays (plcmp-get-face-words '(cperl-array-face))) 
     406            (hashes (plcmp-get-face-words '(cperl-hash-face))) 
     407            (functions (plcmp-get-buffer-subs))) 
     408        (setq plcmp-current-buffer-words-alist 
     409              `((variable . ,variables) 
     410                (array . ,arrays) 
     411                (hash . ,hashes) 
     412                (function . ,functions)))))) 
     413 
     414 
     415(defun plcmp-get-current-buffer-variables () 
     416  (let ((alist (plcmp-get-current-buffer-words-alist))) 
     417    (assoc-default 'variable alist 'eq))) 
     418 
     419(defvar plcmp-anything-source-current-buffer-variables 
     420  `((name . "buffer variables") 
     421    (type . plcmp-completion) 
     422    (init . (lambda () 
     423              (let ((words (plcmp-get-current-buffer-variables))) 
     424                (with-current-buffer (anything-candidate-buffer 'global) 
     425                  (plcmp-insert-each-line words))))) 
     426    (candidates-in-buffer))) 
     427 
     428(defun plcmp-get-current-buffer-arrays () 
     429  (let ((alist (plcmp-get-current-buffer-words-alist))) 
     430    (assoc-default 'array plcmp-current-buffer-words-alist 'eq))) 
     431 
     432(defvar plcmp-anything-source-current-buffer-arrays 
     433  `((name . "buffer arrays") 
     434    (type . plcmp-completion) 
     435    (init . (lambda () 
     436              (let ((words (plcmp-get-current-buffer-arrays))) 
     437                (with-current-buffer (anything-candidate-buffer 'global) 
     438                  (plcmp-insert-each-line words))))) 
     439    (candidates-in-buffer))) 
     440 
     441(defun plcmp-get-current-buffer-hashes () 
     442  (let ((alist (plcmp-get-current-buffer-words-alist))) 
     443    (assoc-default 'hash alist 'eq))) 
     444 
     445(defvar plcmp-anything-source-current-buffer-hashes 
     446  `((name . "buffer hashes") 
     447    (type . plcmp-completion) 
     448    (init . (lambda () 
     449              (let ((words (plcmp-get-current-buffer-hashes))) 
     450                (with-current-buffer (anything-candidate-buffer 'global) 
     451                  (plcmp-insert-each-line words))))) 
     452    (candidates-in-buffer))) 
     453 
     454(defun plcmp-get-current-buffer-functions () 
     455  (let ((alist (plcmp-get-current-buffer-words-alist))) 
     456    (assoc-default 'function alist 'eq))) 
     457 
     458(defvar plcmp-anything-source-current-buffer-functions 
     459  `((name . "buffer functions") 
     460    (type . plcmp-completion) 
     461    (init . (lambda () 
     462              (let ((words (plcmp-get-current-buffer-functions))) 
     463                (with-current-buffer (anything-candidate-buffer 'global) 
     464                  (plcmp-insert-each-line words))))) 
     465    (candidates-in-buffer))) 
     466 
     467 
     468;;; other buffer words 
     469(defvar plcmp-perl-buffer-re "\\.p[lm]$") 
     470(defun plcmp-get-other-perl-buffers-words () 
     471  (let ((perl-buffers (remove-if-not (lambda (buf) 
     472                                       (string-match plcmp-perl-buffer-re (buffer-name buf))) 
     473                                     (buffer-list)))) 
     474    (loop for buffer in perl-buffers 
     475