Changeset 14626 for lang/elisp

Show
Ignore:
Timestamp:
06/26/08 10:54:06 (5 months ago)
Author:
imakado
Message:

コードの見直し、いくつかの動作の改善、defcustom化

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

Legend:

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

    r13971 r14626  
    11;;;  -*- coding: utf-8; mode: emacs-lisp; -*- 
    2 ;;; perl-completion.el ---  
     2;;; perl-completion.el 
    33 
    44;; Author: Kenji.Imakado <ken.imakaado@gmail.com> 
    5 ;; Version: 0.2 
     5;; Version: 0.3 
    66;; Keywords: perl 
    77 
     
    2222 
    2323;;; Commentary: 
     24;; Tested on Emacs 22 
     25 
     26;; to customize 
     27;; M-x customize-group RET perl-completion RET 
     28 
     29;;;code: 
    2430 
    2531(require 'cl) 
    2632(require 'cperl-mode) 
    27  
    28  
    29 ;;; prefix: plcmp- 
     33(require 'dabbrev) 
     34(require 'rx) 
    3035 
    3136;;; provide 
    3237(provide 'perl-completion) 
    3338 
     39;;; group 
     40(defgroup perl-completion nil 
     41  "" 
     42  :group 'perl-completion) 
     43 
    3444;;; customizable variables 
    35 (defcustom plcmp-anything-candidate-number-limit 1000 "") 
    36 (defcustom plcmp-delete-duplicates-candidates-flag nil "") 
    37 (defcustom plcmp-get-words-other-perl-buf-flag t "") 
    38 (defcustom plcmp-buffer-dabbrev-expansions-number 2 "initial-input >= value then dabbrev") ; TODO name and doc 
    39 (defcustom plcmp-get-words-other-perl-buf-limit-number 30 "") 
     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を候補に入れる文字数 
     53initial-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 
    4063(defcustom plcmp-config-modules-filter-list 
    4164  '("strict" "warning") 
    42   "補完対象に含めないモジュール名のリスト") 
     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 
     82non-nilの場合は\"|\"以降の文字列のみにマッチする" 
     83  :type 'boolean 
     84  :group 'perl-completion) 
    4385 
    4486;;; const 
    45 (defconst plcmp-version 0.2) 
     87(defconst plcmp-version 0.3) 
    4688(defconst plcmp-lang (cond ((string-match "japanese" (format "%s" locale-coding-system)) 'ja) 
    4789                           (t 'english))) 
     
    58100(defconst plcmp-display-format-using-modules "using module") 
    59101(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 " &")) 
    60105(defconst plcmp-builtin-functions 
    61106  '("abs" "exec" "glob" "order" "seek" "symlink" "accept" "exists" "gmtime" 
     
    85130    "open" "rmdir" "study" "eof" "getsockname" "opendir" "s" "sub" "eval" "getsockopt" 
    86131    "ord" "scalar" "substr")) 
     132 
    87133(defconst plcmp-builtin-variables 
    88134  '("$SIG{expr}" "%SIG" "$ENV{expr}" "%ENV" "%INC" "@_" "@INC" "@F" "ARGVOUT" 
     
    111157    "$PREMATCH" "$&" "$MATCH" "$<digits>" "$b" "$a" "$_" "$ARG")) 
    112158 
     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  using-modules 
     171  current-buffer 
     172  current-object 
     173  current-package 
     174  cache-installed-modules 
     175  cache-using-modules 
     176  other-perl-buffers 
     177  obj-instance-of-module-maybe-alist 
     178  installed-modules) 
     179 
    113180;;; variables 
    114 (defvar plcmp-cache-using-modules nil) ;last 
    115 (make-variable-buffer-local 'plcmp-cache-using-modules) 
    116  
     181(defvar plcmp-data (plcmp-make-completion-data) "strunct") 
     182(defvar plcmp-search-match-face 'plcmp-search-match) 
     183(defvar plcmp-overlay nil) 
     184(defvar plcmp-metadata-matcher-re (rx bol (* (not (any "|"))) "|" space (*? not-newline))) 
     185(defvar plcmp-metadata-matcher "") 
     186 
     187;;; buffer local variables 
     188(defvar plcmp-last-using-modules nil) 
     189(make-variable-buffer-local 'plcmp-last-using-modules) 
    117190(defvar plcmp-modules-methods-alist nil) 
    118191(make-variable-buffer-local 'plcmp-modules-methods-alist) 
    119192 
    120 (defvar plcmp-cache-installed-modules nil) 
    121 (defvar 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 ") 
    122 (defvar plcmp-get-installed-modules-async-command 
    123   (concat plcmp-get-installed-modules-command " &")) 
     193;;; anything's variables 
     194(defvar plcmp-anything-sources nil) 
     195(defvar plcmp-anything-enable-digit-shortcuts nil ) 
     196(defvar plcmp-anything-candidate-number-limit plcmp-anything-candidate-number-limit ) 
     197(defvar plcmp-anything-idle-delay 0.5 ) 
     198(defvar plcmp-anything-samewindow nil ) 
     199(defvar plcmp-anything-source-filter nil ) 
     200(defvar plcmp-anything-isearch-map 
     201  (let ((map (copy-keymap (current-global-map)))) 
     202    (define-key map (kbd "<return>") 'plcmp-anything-isearch-default-action) 
     203    (define-key map (kbd "C-i") 'plcmp-anything-isearch-select-action) 
     204    (define-key map (kbd "C-g") 'plcmp-anything-isearch-cancel) 
     205    (define-key map (kbd "M-s") 'plcmp-anything-isearch-again) 
     206    (define-key map (kbd "<backspace>") 'plcmp-anything-isearch-delete) 
     207    (let ((i 32)) 
     208      (while (< i 256) 
     209        (define-key map (vector i) 'plcmp-anything-isearch-printing-char) 
     210        (setq i (1+ i)))) 
     211    map)) 
     212(defgroup plcmp-anything nil 
     213  "Open plcmp-anything." :prefix "plcmp-anything-" :group 'convenience) 
     214(if (facep 'header-line) 
     215    (copy-face 'header-line 'plcmp-anything-header) 
     216  (defface plcmp-anything-header 
     217    '((t (:bold t :underline t))) 
     218    "Face for header lines in the plcmp-anything buffer." :group 'plcmp-anything)) 
     219(defvar plcmp-anything-header-face 'plcmp-anything-header ) 
     220(defface plcmp-anything-isearch-match '((t (:background "Yellow"))) 
     221  "Face for isearch in the plcmp-anything buffer." :group 'plcmp-anything) 
     222(defvar plcmp-anything-isearch-match-face 'plcmp-anything-isearch-match ) 
     223(defvar plcmp-anything-iswitchb-idle-delay 1 ) 
     224(defvar plcmp-anything-iswitchb-dont-touch-iswithcb-keys nil ) 
     225(defconst plcmp-anything-buffer "*perl-completion anything*" ) 
     226(defvar plcmp-anything-selection-overlay nil ) 
     227(defvar plcmp-anything-isearch-overlay nil ) 
     228(defvar plcmp-anything-digit-overlays nil ) 
     229(defvar plcmp-anything-candidate-cache nil ) 
     230(defvar plcmp-anything-pattern "") 
     231(defvar plcmp-anything-input "") 
     232(defvar plcmp-anything-async-processes nil ) 
     233(defvar plcmp-anything-digit-shortcut-count 0 ) 
     234(defvar plcmp-anything-update-hook nil ) 
     235(defvar plcmp-anything-saved-sources nil ) 
     236(defvar plcmp-anything-saved-selection nil ) 
     237(defvar plcmp-anything-original-source-filter nil ) 
     238 
     239;;; hack variables 
     240;; idea: http://www.emacswiki.org/cgi-bin/wiki/RubikitchAnythingConfiguration 
     241(defvar plcmp-anything-saved-action nil 
     242  "Saved value of the currently selected action by key.") 
     243 
     244(defvar plcmp-anything-matched-candidate-cache nil 
     245  "(name . ((pattern . (list of string)) 
     246            (pattern . (list of string)))) ") 
     247 
    124248;;; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
    125 ;;; Modules 
     249;;; Utilities 
    126250;;; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
     251 
     252(defmacro plcmp-with-slots (struct conc-name slots &rest body) 
     253  `(symbol-macrolet ,(loop for slot in slots 
     254                           collect `(,slot (,(intern (concat (symbol-name conc-name) (symbol-name slot))) ,struct))) 
     255     ,@body)) 
     256(def-edebug-spec plcmp-with-slots (symbolp symbolp (&rest symbolp) body)) ;TODO 
     257   
     258(defmacro plcmp-with-completion-data-slots (struct slots &rest body) 
     259  (declare (indent 2)) 
     260  `(plcmp-with-slots ,struct plcmp-completion-data- ,slots ,@body)) 
     261(def-edebug-spec plcmp-with-completion-data-slots (symbolp (&rest symbolp) body)) 
     262   
     263(defmacro plcmp-with-gensyms (symbols &rest body) 
     264  (declare (indent 1)) 
     265  `(let ,(mapcar (lambda (sym) 
     266                   `(,sym (gensym))) 
     267                 symbols) 
     268     ,@body)) 
     269 
     270(defmacro plcmp-my (var val &rest body) 
     271  (declare (indent 2)) 
     272  `(lexical-let ((,var ,val)) 
     273     ,@body)) 
     274 
     275(put 'plcmp-acond 'lisp-indent-function 'defun) ;TODO 
     276(defmacro plcmp-acond (&rest clauses) 
     277  (unless (null clauses) 
     278    (plcmp-with-gensyms (sym) 
     279      (plcmp-my clause (car clauses) 
     280        `(plcmp-my ,sym ,(car clause) 
     281           (if ,sym 
     282               (plcmp-my it ,sym 
     283                 ,@(cdr clause))        ;expr 
     284             (plcmp-acond ,@(cdr clauses)))))))) 
     285(def-edebug-spec plcmp-acond cond) 
     286 
     287(defsubst plcmp-trim (s) 
     288  "strip space and newline" 
     289  (replace-regexp-in-string 
     290   "[ \t\n]*$" "" (replace-regexp-in-string "^[ \t\n]*" "" s))) 
     291 
     292(defun plcmp-get-preceding-string (&optional count) 
     293  "現在の位置からcount文字前方位置までの文字列を返す 
     294例外を出さない" 
     295  (let ((count (or count 1))) 
     296    (buffer-substring-no-properties 
     297     (point) 
     298     (condition-case nil 
     299         (save-excursion (backward-char count) (point)) 
     300       (error (point)))))) 
     301 
     302(defsubst plcmp-module-p (s) 
     303  (string-match "^[a-zA-Z:_]+$" s)) 
     304 
     305(defsubst plcmp-perl-identifier-p (s) 
     306  (string-match (concat "^" plcmp-perl-ident-re "$") s)) 
     307 
     308(defun plcmp-notfound-p (s) 
     309  (string-match "^Can't locate [^ \t]+ in" s)) 
     310 
     311(defmacro plcmp-ignore-errors (&rest body) 
     312  `(condition-case e (progn ,@body) 
     313     (error (plcmp-log "Error plcmp-ignore-errors :  %s" (error-message-string e))))) 
     314 
     315;;; log 
     316(defvar plcmp-debug nil) 
     317(defvar plcmp-log-buf-name "*plcmp debug*") 
     318(defun plcmp-log-buf () 
     319  (get-buffer-create plcmp-log-buf-name)) 
     320(defun plcmp-log (&rest messages) 
     321  (ignore-errors 
     322    (let* ((str (or (ignore-errors (apply 'format messages)) 
     323                    (prin1-to-string messages))) 
     324           (strn (concat str "\n"))) 
     325      (when plcmp-debug 
     326        (with-current-buffer (plcmp-log-buf) 
     327          (goto-char (point-max)) 
     328          (insert strn))) 
     329      str))) 
     330 
     331 
     332;;;; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
     333;;;; Initialize 
     334;;;; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
     335 
     336;; idea: http://subtech.g.hatena.ne.jp/antipop/20070917/1190009355 
     337(defun plcmp-get-installed-modules-synchronously () 
     338  (message "fetching installed modules...") 
     339  (let ((modules (split-string (shell-command-to-string plcmp-get-installed-modules-command) "\n"))) 
     340    (message "fetching installed modules done") 
     341    (remove-if (lambda (module) 
     342                 (string-match "No such file or directory$" module)) 
     343               modules))) 
     344 
     345(defun plcmp-get-installed-modules-from-buf (buf) 
     346  (with-current-buffer buf 
     347    (let ((modules (split-string (buffer-substring-no-properties (point-min) (point-max)) "\n"))) 
     348      (remove-if (lambda (module) 
     349                   (string-match "No such file or directory$" module)) 
     350                 modules)))) 
     351 
     352(defun plcmp-send-command-get-installed-modules () 
     353  (message "send command to get installed modules") 
     354  (save-window-excursion 
     355    (shell-command plcmp-get-installed-modules-async-command plcmp-installed-modules-buf-name)) 
     356  (with-current-buffer plcmp-installed-modules-buf-name 
     357    (setq buffer-read-only t))) 
     358 
     359(defun plcmp-fetch-installed-modules (struct) 
     360  (plcmp-with-completion-data-slots struct 
     361      (cache-installed-modules) 
     362    (let ((buf (get-buffer plcmp-installed-modules-buf-name))) 
     363      (cond 
     364       ((null cache-installed-modules) 
     365        (if (and (buffer-live-p buf) 
     366                 (not (processp (get-buffer-process buf)))) ;finished 
     367            (setf cache-installed-modules (plcmp-get-installed-modules-from-buf buf)) 
     368          (unless (buffer-live-p buf) 
     369            (plcmp-send-command-get-installed-modules)) 
     370          (plcmp-get-installed-modules-synchronously))) 
     371       ;; return cache 
     372       (t 
     373        cache-installed-modules))))) 
     374 
     375(defun plcmp-get-current-package () 
     376  "nil or string" 
     377  (let ((re (concat "^[ \t]*package\\s *" "\\([a-zA-Z:]+\\)" ".*;$")) 
     378        (limit 500)) 
     379    (save-excursion 
     380      (goto-char (point-min)) 
     381      (when (re-search-forward re limit t) 
     382        (match-string-no-properties 1))))) 
     383 
    127384(defun plcmp-get-using-modules () 
    128   (let ((re "^[ \t]*use[ \t]+\\([a-zA-Z:_]+\\)\\s *[^;\n]*;");todo 
     385  (let ((re "^[ \t]*use[ \t]+\\([a-zA-Z:_]+\\)\\s *[^;\n]*;") ;todo 
    129386        (ret nil)) 
    130387    (save-excursion 
     
    138395    ret)) 
    139396 
    140 (defun plcmp-clear-cache-using-modules () 
    141   (interactive) 
    142   (setq plcmp-cache-using-modules nil)) 
    143  
    144  
    145 (defun plcmp-modules-filter (mods) 
    146   (let ((ret nil) ) 
    147     (dolist (filter-mod plcmp-config-modules-filter-list ret) 
    148       (setq ret (delete filter-mod mods))))) 
    149  
    150  
    151 (defun plcmp-get-modules-methods-alist (using-modules) 
    152   (let ((ret nil)) 
    153     (cond 
    154      ((and (equal using-modules plcmp-cache-using-modules) 
    155            (not (null plcmp-modules-methods-alist))) 
    156       (setq ret plcmp-modules-methods-alist)) 
    157      ((null plcmp-modules-methods-alist) 
    158       (dolist (mod using-modules) 
    159         (message "getting methods of %s ..." mod) 
    160         (push `(,mod . ,(plcmp-get-methods mod)) plcmp-modules-methods-alist) 
    161         (message "getting methods of %s done" mod)) 
    162       (setq ret plcmp-modules-methods-alist)) 
    163      (t 
    164       (let ((new-mods (delete-dups 
    165                        (set-difference using-modules plcmp-cache-using-modules :test 'string-equal))) 
    166             (removed-mods (delete-dups 
    167                            (set-difference plcmp-cache-using-modules using-modules :test 'string-equal)))) 
    168         (plcmp-log "new-mods: %S\nremoved-mods: %S" new-mods removed-mods) 
    169         ;; add new 
    170         (when new-mods 
    171           (dolist (mod new-mods) 
    172             (message "getting methods of %s ..." mod) 
    173             (push `(,mod . ,(plcmp-get-methods mod)) plcmp-modules-methods-alist) 
    174             (message "getting methods of %s done" mod))) 
    175         ;; remove 
    176         (when removed-mods 
    177           (dolist (mod removed-mods) 
    178             (setq plcmp-modules-methods-alist 
    179                   (remove (assoc mod plcmp-modules-methods-alist) plcmp-modules-methods-alist)))) 
    180         (setq ret plcmp-modules-methods-alist)))) 
    181     ;; set last 
    182     (setq plcmp-cache-using-modules using-modules) 
    183     ret 
    184     )) 
    185  
    186 (defun plcmp-clear-cache-modules-methods-alist () 
    187   (setq plcmp-modules-methods-alist nil)) 
    188  
    189 (defun plcmp-get-methods (module) 
     397;;(plcmp-sort-methods '("_asdf" "asdf" "bsd" "_bsd" "ASDF")) 
     398;; => ("ASDF" "asdf" "bsd" "_asdf" "_bsd") 
     399(defun plcmp-sort-methods (los) 
     400  (loop for s in los 
     401        if (string-match (rx bol "_") s) 
     402        collect s into unders 
     403        else 
     404        collect s into methods 
     405        finally return (nconc methods unders 
     406                        ;; (sort methods 'string<) 
     407                        ;;                               (sort unders 'string<) 
     408                              ))) 
     409 
     410(defsubst plcmp-inspect-methods (module) 
    190411  "Class::Inspectorを使用してモジュールのメソッド調べる。 
    191412モジュール名に使用できる文字以外が含まれていた場合はnilを返す 
     
    195416      (error "invild modulename")) 
    196417    (let ((mods (shell-command-to-string 
    197                  (concat 
    198                   "perl" " -MClass::Inspector" " -e" "'use " module "; print join \"\n\"=>@{Class::Inspector->methods(" module ")} '" )))) 
     418                 (concat "perl -MClass::Inspector -e'use " module "; print join \"\n\"=>@{Class::Inspector->methods(" module ")} '")))) 
    199419      (cond 
    200420       ((plcmp-notfound-p mods) 
    201421        (error "cant locate %s" module)) 
    202422       (t 
    203         (split-string mods "\n")))))) 
    204  
    205 (defsubst plcmp-get-modules-re () 
    206   (regexp-opt plcmp-using-modules t)) 
    207  
    208 ;; example 
    209 ;; my $cpan = Parse::CPAN::Authors->new( $authors_file ); 
    210 ;; => var = "$cpan", mod = Parse::CPAN::Authors 
    211 (defun plcmp-get-obj-instance-of-module-maybe-alist () 
    212   (let* ((re (plcmp-get-modules-re)) 
    213          (re (concat "\\(\\$[A-Za-z_][A-Za-z_0-9]*\\)\\s *=\\s *" re)) ;perliden + usingmodule 
    214          (ret nil)) 
     423        (plcmp-sort-methods (split-string mods "\n"))))))) 
     424 
     425(defun plcmp-get-modules-methods (modules) 
     426  "return alist" 
     427  (let ((ret nil)) 
     428    (dolist (mod modules ret) 
     429      (message "getting methods of %s ..." mod) 
     430      (push `(,mod . ,(plcmp-inspect-methods mod)) ret) 
     431      (message "getting methods of %s done" mod)))) 
     432 
     433;; TODO 
     434(defun plcmp-get-modules-methods-alist (struct) 
     435  (plcmp-with-completion-data-slots struct 
     436      (using-modules current-buffer) 
     437    ;;`plcmp-modules-methods-alist' and `plcmp-last-using-modules' are buffer local variables 
     438    (with-current-buffer current-buffer 
     439      (let ((ret nil)) 
     440        (cond 
     441         ((and (equal using-modules plcmp-last-using-modules) 
     442               (not (null plcmp-modules-methods-alist))) 
     443          (setq ret plcmp-modules-methods-alist)) 
     444         ;; cache not ready 
     445         ((null plcmp-modules-methods-alist) 
     446          (setf ret 
     447                (setf plcmp-modules-methods-alist 
     448                      (plcmp-get-modules-methods using-modules)))) 
     449         (t 
     450          (let ((new-mods (delete-dups (set-difference using-modules plcmp-last-using-modules :test 'string-equal))) 
     451                (removed-mods (delete-dups (set-difference plcmp-last-using-modules using-modules :test 'string-equal)))) 
     452            (plcmp-log "new-mods: %S\nremoved-mods: %S" new-mods removed-mods) 
     453            ;; add new 
     454            (when new-mods 
     455              (setq plcmp-modules-methods-alist 
     456                    (append plcmp-modules-methods-alist 
     457                            (plcmp-get-modules-methods new-mods)))) 
     458            ;; remove 
     459            (when removed-mods 
     460              (setq plcmp-modules-methods-alist 
     461                    (remove-if (lambda (mod) (assoc mod plcmp-modules-methods-alist)) removed-mods))) 
     462            (setq ret plcmp-modules-methods-alist)))) 
     463        ;; set last 
     464        (setq plcmp-last-using-modules using-modules) 
     465        ret 
     466        )))) 
     467 
     468(defun plcmp-get-obj-instance-of-module-maybe-alist (struct) 
     469  (plcmp-with-completion-data-slots struct 
     470      (using-modules) 
     471    (let* ((re (regexp-opt using-modules t)) 
     472           (re (concat "\\(\\$" plcmp-perl-ident-re "\\)\\s *=\\s *" re)) ;perliden + usingmodule 
     473           (ret nil)) 
     474      (save-excursion 
     475        (goto-char (point-min)) 
     476        (loop always (re-search-forward re nil t) 
     477              do (let ((var (match-string-no-properties 1)) 
     478                       (mod (match-string-no-properties 2))) 
     479                   (add-to-list 'ret `(,var . ,mod))))) 
     480      ret))) 
     481 
     482(defun plcmp-get-other-perl-buffers (struct) 
     483  (plcmp-with-completion-data-slots struct 
     484      (current-buffer) 
     485    (remove current-buffer 
     486            (remove-if-not (lambda (buf) 
     487                             (string-match "\\.p[lm]$" (buffer-name buf))) 
     488                           (buffer-list))))) 
     489 
     490(defun plcmp-initialize (struct) 
     491  (plcmp-with-completion-data-slots struct 
     492      (using-modules installed-modules current-package 
     493                     current-buffer obj-instance-of-module-maybe-alist 
     494                     current-object other-perl-buffers) 
     495    ;; initialize slots 
     496    (setf installed-modules (plcmp-fetch-installed-modules struct) 
     497          current-buffer (current-buffer) 
     498          current-package (plcmp-get-current-package) 
     499          using-modules (plcmp-get-using-modules) 
     500          plcmp-modules-methods-alist (plcmp-get-modules-methods-alist struct) ;buffer local variable 
     501          obj-instance-of-module-maybe-alist (plcmp-get-obj-instance-of-module-maybe-alist struct) 
     502          other-perl-buffers (plcmp-get-other-perl-buffers struct) 
     503          current-object "") 
     504 
     505    ;; initialize variable 
     506    (setq plcmp-metadata-matcher 
     507          (if plcmp-match-only-real-candidate 
     508              plcmp-metadata-matcher-re 
     509            "")) 
     510 
     511    ;; get context 
     512    (plcmp-get-context struct))) 
     513 
     514(defun plcmp-method-p () 
     515  (let ((s (plcmp-get-preceding-string 2))) 
     516    (string-equal s "->"))) 
     517 
     518(defun plcmp-get-context (struct) 
     519  (plcmp-with-completion-data-slots struct 
     520      (initial-input state current-object) 
    215521    (save-excursion 
    216       (goto-char (point-min)) 
    217       (loop always (re-search-forward re nil t)             
    218             do (let ((var (match-string-no-properties 1)) 
    219                      (mod (match-string-no-properties 2))) 
    220                  (add-to-list 'ret `(,var . ,mod))))) 
    221       ret)) 
    222  
    223  
    224 ;; idea: http://subtech.g.hatena.ne.jp/antipop/20070917/1190009355 
    225 (defun plcmp-send-command-get-installed-modules () 
    226   (save-window-excursion 
    227     (shell-command plcmp-get-installed-modules-async-command plcmp-installed-modules-buf-name)) 
    228   (with-current-buffer plcmp-installed-modules-buf-name 
    229     (setq buffer-read-only t))) 
    230  
    231 (defun plcmp-get-installed-modules () 
    232   (let ((buf (get-buffer plcmp-installed-modules-buf-name))) 
    233     (cond 
    234      ((null plcmp-cache-installed-modules) 
    235       (cond 
    236        ;; コマンドの結果のバッファがある場合 
    237        ((buffer-live-p buf) 
    238         (with-current-buffer buf 
    239           (let* ((modules (split-string (buffer-substring-no-properties (point-min) (point-max)) "\n")) 
    240                  (modules (remove-if (lambda (module) 
    241                                        (string-match "No such file or directory$" module)) 
    242                                      modules))) 
    243             ;; when process finished 
    244             (unless (processp (get-buffer-process plcmp-installed-modules-buf-name)) 
    245               (setq plcmp-cache-installed-modules modules)) 
    246             modules))) 
    247        ;; 事前にコマンドが走っていない場合はその場で同期的に習得する 
    248        (t 
    249         (let* ((modules (split-string (shell-command-to-string plcmp-get-installed-modules-command) "\n")) 
    250                (modules (remove-if (lambda (module) 
    251                                      (string-match "No such file or directory$" module)) 
    252                                    modules))) 
    253           (plcmp-send-command-get-installed-modules))))) 
    254      ;; return cache 
    255      (t 
    256       plcmp-cache-installed-modules)))) 
    257  
    258 (defun plcmp-clear-cache-installed-modules () 
    259   (ignore-errors 
    260    (setq plcmp-cache-installed-modules nil) 
    261     (let ((process (get-buffer-process plcmp-installed-modules-buf-name))) 
    262       (when (processp process) 
    263         (kill-process (process-name process))) 
    264       (plcmp-send-command-get-installed-modules)))) 
    265  
    266 (defun plcmp-get-current-package () 
    267   (let ((re (concat "^[ \t]*package" "\\([a-zA-Z:]+\\)" "\\s *[^;\n]*;")) 
    268         (limit 500) 
    269         (ret nil)) 
    270     (save-excursion 
    271       (goto-char (point-min)) 
    272       (loop always (re-search-forward re limit t) 
    273             do (add-to-list 'ret (match-string-no-properties 1)))) 
    274     (plcmp-log "get-current-package: %S" ret) 
    275     ret)) 
    276  
    277  
    278 ;;; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
    279 ;;; Smart dabbrev 
    280 ;;; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
    281  
    282 (defsubst plcmp-check-face (facename) 
    283   "preceding-charの位置のフェイスを調べる(前の文字)" 
    284   (let ((face (get-text-property (if (bobp) (point) (- (point) 1)) 'face))) 
    285     ;;(plcmp-log "check-face-at-point: %s" face) 
    286     (cond 
    287      ((listp face) 
    288       (memq facename face)) 
    289      (t 
    290       (eq facename face))))) 
    291  
    292 (defsubst plcmp-check-face-at-point-p (facename) 
    293   (let ((face (get-text-property (point) 'face))) 
    294     ;;(plcmp-log "check-face-at-point: %s" face) 
    295     (cond 
    296      ((listp face) 
    297       (memq facename face)) 
    298      (t 
    299       (eq facename face))))) 
    300  
    301 (defsubst plcmp-bit-regep-p (s) 
    302   (string-match "^[/$@%(),.?<>+!|^*';\"\\]+$" s)) 
     522      (let* ((start (point)) 
     523             (start-input (progn (skip-syntax-backward "w_") ;move point 
     524                                 (buffer-substring-no-properties (point) start))) 
     525             (obj-str (buffer-substring-no-properties 
     526                       (or (ignore-errors (save-excursion (forward-char -2) (point))) 
     527                           (point)) 
     528                       (save-excursion (or (ignore-errors (backward-sexp) 
     529                                                          (point)) 
     530                                           (point)))))) 
     531        (cond 
     532         ;; $self->`!!' 
     533         ((and (plcmp-method-p)         ; TODO 
     534               (string-match "^\\(\\$self\\|__PACKAGE__\\)$" obj-str)) 
     535          (setf initial-input start-input 
     536                state 'setf 
     537                current-object obj-str)) 
     538         ;; methods 
     539         ;; Foo->`!!' 
     540         ((plcmp-method-p) 
     541          (setf initial-input start-input 
     542                state 'methods 
     543                current-object obj-str)) 
     544         ;; $foo`!!' 
     545         ((string-match "[$@%&]" (plcmp-get-preceding-string 1)) 
     546          (save-excursion 
     547            (forward-char -1) 
     548            (setf initial-input (buffer-substring-no-properties start (point)) 
     549                  state 'globals))) 
     550         ;; installed-modules 
     551         ;; use Foo::Ba`!!' 
     552         ((string-match "^\\s *use\\s *" (buffer-substring-no-properties (point-at-bol) (point))) 
     553          (setf initial-input start-input 
     554                state 'installed-modules)) 
     555         ;; globals 
     556         ((or (bolp) 
     557              (string-match "[ \t]" (plcmp-get-preceding-string 1))) 
     558          (setf initial-input start-input 
     559                state 'globals)) 
     560         ;; otherwise 
     561         (t 
     562          (setf initial-input start-input 
     563                state 'globals)) 
     564         ))))) 
     565 
     566;;;; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
     567;;;; Candidates 
     568;;;; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
     569(defsubst plcmp-build-display-candidate (metadata str) 
     570  (concat "[" metadata "]" " | " str)) 
     571 
     572(defsubst plcmp-get-real-candidate (display-candidate) 
     573  "return string" 
     574  (if (string-match (concat "^\\[[^\]\n]*\\] | " 
     575                            "\\(.*\\)") 
     576                    display-candidate) 
     577      (match-string 1 display-candidate) 
     578    display-candidate)) 
     579 
     580(defsubst plcmp-get-metadate-candidate (display-candidate) 
     581  "return string" 
     582  (if (string-match "^\\[\\([^\]\n]*\\)\\] | " display-candidate) 
     583      (match-string 1 display-candidate) 
     584    "")) 
     585 
     586(defun plcmp-get-modulename-candidate (struct display-candidate) 
     587  (let ((metadata (plcmp-get-metadate-candidate display-candidate))) 
     588    (plcmp-acond 
     589      ((plcmp-get-module-and-method-by-candidate struct display-candidate) 
     590       (multiple-value-bind (module method) it ;when bind, IT must be list of string '(module method) 
     591         module)) 
     592      (t 
     593       (plcmp-get-real-candidate display-candidate))))) 
     594 
     595(defsubst plcmp-start-initial-input-p (initial-input candidate) 
     596  (let ((re (concat "^" (regexp-quote initial-input)))) 
     597    (string-match re candidate))) 
     598 
     599(defsubst plcmp-f