- Timestamp:
- 09/13/08 03:07:59 (4 months ago)
- Files:
-
- 1 modified
Legend:
- Unmodified
- Added
- Removed
-
lang/elisp/perl-completion/branch/1.0/perl-completion.el
r19179 r19252 35 35 36 36 37 ;; TODO: 38 ;; set-perl5lib 39 37 40 38 41 ;;;code: 39 42 (require 'cl) 40 (require 'anything) 43 (require 'anything) ; perl-completion.el uses `anything-aif' macro. 41 44 (require 'cperl-mode) 42 45 (require 'dabbrev) … … 49 52 ;;; variables 50 53 (defvar plcmp-version 1.0) 54 51 55 (defvar plcmp-perl-ident-re "[a-zA-Z_][a-zA-Z_0-9]*") 56 52 57 (defvar plcmp-sub-re (rx-to-string `(and "sub" 53 58 (+ space) 54 59 (group 55 60 (regexp ,plcmp-perl-ident-re))))) 61 56 62 (defvar plcmp-perl-package-re "[a-zA-Z0-9:]+") 63 57 64 (defvar plcmp-builtin-functions 58 65 '("abs" "exec" "glob" "order" "seek" "symlink" "accept" "exists" "gmtime" … … 109 116 "$PREMATCH" "$&" "$MATCH" "$<digits>" "$b" "$a" "$_" "$ARG")) 110 117 111 (defvar plcmp-cleanup-hook nil "hook run when completion command finished") 118 (defvar plcmp--command-cleanup-hook nil "hook run when completion command finished") 119 120 (defvar plcmp--cached-variables nil "list of cached variable. each variable is cleared by `plcmp-cmd-clear-all-caches'") 121 112 122 113 123 ;;; 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 124 (defmacro define-plcmp-command (command-name-with-no-prefix args &rest body) 123 125 (let* ((prefix "plcmp-cmd-") … … 171 173 default-directory)))) 172 174 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))) 175 ;; TODO: need test. 176 (defsubst plcmp--re-match-sources1 (regexps source) 177 (when source 178 (let ((source (if (listp source) source (symbol-value source)))) 179 (some (lambda (re) 180 (string-match re (assoc-default 'name source 'eq))) 181 regexps)))) 182 183 (defun plcmp-re-sort-sources (regexps sources) 184 (condition-case e 185 (let ((regexps (if (stringp regexps) (list regexps) regexps)) 186 (match-sources) 187 (unmatch-sources)) 188 (loop for source in sources 189 if (plcmp--re-match-sources1 regexps source) 190 collect source into match-sources 191 else 192 collect source into unmatch-sources 193 finally (return (nconc match-sources unmatch-sources)))) 194 (error sources))) 195 ;;(plcmp-re-sort-sources "variable" (plcmp-get-sources-for-complete-all)) 196 197 (defun* plcmp-collect-matches 198 (re &optional (count 0) (match-string-fn 'match-string) 199 (point-min (point-min)) (point-max (point-max))) 200 (save-excursion 201 (loop initially (goto-char point-min) 202 while (re-search-forward re point-max t) 203 collect (funcall match-string-fn count)))) 185 204 186 205 ;;; log … … 199 218 (insert strn))) 200 219 str))) 220 (defun plcmp-message (&rest args) 221 (when plcmp-debug 222 (apply 'message args))) 201 223 202 224 203 225 (defvar plcmp-initial-input "") 204 226 (defvar plcmp-real-initial-input "real initial-input if required `anything-match-plugin' initial-input is not 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 "")))) 227 (defun plcmp-get-initial-real-input-list () 228 "return list (initial-input real-initial-input)" 229 (save-excursion 230 (let ((start (point))) 231 (skip-syntax-backward "w_") 232 (let* ((preceding-string (char-to-string (preceding-char))) 233 (end (condition-case e 234 (cond 235 ((some (lambda (s) (string-equal s preceding-string)) '("$" "@" "&" "&")) 236 (backward-char) 237 (point)) 238 (t 239 (point))) 240 (error (point)))) 241 (real-initial-input 242 (buffer-substring-no-properties start end)) 243 (initial-input 244 (regexp-quote 245 (concat real-initial-input 246 (if (featurep 'anything-match-plugin) 247 " " 248 ""))))) 249 (values initial-input real-initial-input))))) 215 250 216 251 ;;; installed modules 217 252 (defvar plcmp-installed-modules nil) 253 (add-to-list 'plcmp--cached-variables 'plcmp-installed-modules) 254 218 255 (defun plcmp-get-installed-modules () 219 (or plcmp-installed-modules 220 (setq plcmp-installed-modules (plcmp--installed-modules-synchronously)))) 256 (unless (plcmp-tramp-p) 257 (or plcmp-installed-modules 258 (prog1 (plcmp--installed-modules-synchronously) 259 (plcmp--installed-modules-asynchronously))))) 221 260 222 261 (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") 235 (remove-if (lambda (module) 236 (string-match "No such file or directory$" module)) 237 modules)))) 238 262 (message "fetching installed modules...") 263 (let* ((modules-str (shell-command-to-string 264 (concat 265 "find `perl -e 'pop @INC; print join(q{ }, @INC);'`" 266 " -name '*.pm' -type f " 267 "| xargs egrep -h -o 'package [a-zA-Z0-9:]+;' " 268 "| perl -nle 's/package\s+(.+);/$1/; print' " 269 "| sort " 270 "| uniq "))) 271 (modules (split-string modules-str "\n"))) 272 (message "done") 273 (remove-if (lambda (module) 274 (string-match "No such file or directory$" module)) 275 modules))) 276 277 (defvar plcmp-installed-modules-buffer-name " *perl-completion installed modules*") 278 (defun plcmp--installed-modules-set-cache (process event) 279 (when (string-equal "finished\n" event) 280 (with-current-buffer plcmp-installed-modules-buffer-name 281 (unless (zerop (buffer-size)) 282 (setq plcmp-installed-modules (plcmp-collect-matches plcmp-perl-package-re)) 283 (plcmp-message "cached installed modules %s" plcmp-installed-modules))))) 284 285 (defun plcmp--installed-modules-asynchronously () 286 "start process, set sentinel, return process." 287 (message "fetching installed modules...") 288 (let* ((command "find") 289 (args (concat "find `perl -e 'pop @INC; print join(q{ }, @INC);'`" 290 " -name '*.pm' -type f " 291 "| xargs grep -E -h -o 'package [a-zA-Z0-9:]+;' " 292 "| perl -nle 's/package\s+(.+);/$1/; print' " 293 "| sort " 294 "| uniq ")) 295 (proc (start-process-shell-command "installed perl modules" 296 plcmp-installed-modules-buffer-name 297 command 298 args))) 299 (set-process-sentinel proc 'plcmp--installed-modules-set-cache) 300 ;; return process 301 proc)) 302 303 ;; (plcmp--installed-modules-asynchronously) 304 305 306 ;; todo: ne (length plcmp--installed-modules-synchronously) 307 (defun plcmp--installed-modules-perl () 308 (let* ((str (shell-command-to-string (concat " perl -e ' use File::Find; @dirs = grep { q{.} ne $_} @INC" 309 "; my $dir_name = $dir" 310 " ;my $mods = sub { if ( -f && /.pm$/ ) { print $File::Find::name, \"\n\"; } }; find $mods, @dirs; ' "))) 311 (files (delete-dups (delete "" (delete "." (split-string str "\n")))))) 312 (loop for file in files 313 collect (plcmp--package-name file)))) 314 315 (defun plcmp--package-name (file) 316 (let ((re (rx-to-string `(and "package" 317 (+ space) 318 (group 319 (regexp ,plcmp-perl-package-re)) 320 (* space) 321 ";" 322 )))) 323 (when (and (stringp file) 324 (file-exists-p file) 325 (file-readable-p file)) 326 (with-temp-buffer 327 (insert-file-contents file) 328 (goto-char (point-min)) 329 (when (re-search-forward re nil t) 330 (match-string-no-properties 1)))))) 331 239 332 ;;; current package 240 333 (defvar plcmp-current-package-name "") … … 257 350 (defvar plcmp-using-modules nil) 258 351 (defun plcmp-get-using-modules () 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 ";")))) 267 (save-excursion 268 (loop initially (goto-char (point-min)) 269 while (re-search-forward re nil t) 270 collect (match-string-no-properties 1))))) 352 (let ((re (rx-to-string `(and bol 353 (* space) 354 "use" 355 (+ space) 356 (group ;1 package 357 (regexp ,plcmp-perl-package-re)) 358 (* not-newline) 359 ";")))) 360 (plcmp-collect-matches re 1 'match-string-no-properties))) 271 361 272 362 ;;; methods … … 279 369 "=" 280 370 (* space) 281 (group ;2 371 (group ;2 module-name 282 372 (regexp ,using-module-re)))))) 283 373 (save-excursion … … 289 379 (with-temp-buffer 290 380 (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)))) 381 (plcmp-collect-matches plcmp-perl-ident-re))) 294 382 295 383 (defsubst plcmp--inspect-module-class-inspector (module-name) … … 311 399 312 400 (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))))) 401 (plcmp-collect-matches plcmp-sub-re 1 'match-string-no-properties)) 318 402 319 403 (defun plcmp--inspect-module-scrape (module-name) … … 338 422 "alist, (module-name . (list of methods))") 339 423 (defun plcmp-get-module-methods-alist (using-modules) 340 (dolist (module-name using-modules )424 (dolist (module-name using-modules plcmp-module-methods-alist) 341 425 (unless (assoc module-name plcmp-module-methods-alist) 342 426 (add-to-list 'plcmp-module-methods-alist 343 (plcmp--inspect-module module-name)))) 344 plcmp-module-methods-alist) 427 (plcmp--inspect-module module-name))))) 345 428 346 429 347 430 ;; module-name -> source 348 431 (defun plcmp--mk-module-source (module-name) 349 ( plcmp-aif (assoc-default module-name plcmp-module-methods-alist)432 (anything-aif (assoc-default module-name plcmp-module-methods-alist) 350 433 `((name . ,(concat module-name " Methods")) 351 434 (type . plcmp-completion) … … 366 449 (rx (>= 4 (or (syntax word) 367 450 (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)))) 451 452 (defsubst* plcmp-get-buffer-dabbrevs () 453 (plcmp-collect-matches plcmp-buffer-dabbrevs-re)) 373 454 374 455 ;;; current buffer words 456 (defsubst* plcmp--check-face (face-names &optional (point (point))) 457 (let* ((face (get-text-property point 'face)) 458 (faces (if (listp face) face (list face)))) 459 (some (lambda (face-sym) 460 (memq face-sym faces)) 461 face-names))) 462 375 463 (defsubst* plcmp-get-face-words (&optional (faces '(font-lock-variable-name-face 376 464 font-lock-function-name-face))) … … 381 469 (point-max)) 382 470 until (eobp) 383 do (progn (when (plcmp- check-face faces)384 ( plcmp-aif (cperl-word-at-point)471 do (progn (when (plcmp--check-face faces) 472 (anything-aif (cperl-word-at-point) 385 473 (puthash it nil hash))) 386 474 (goto-char next-change))) 387 475 (let ((ret)) 388 (maphash (lambda (k v) (push k ret)) hash) 476 (maphash (lambda (k v) (push k ret)) hash) ; remove-dups 389 477 ret)))) 390 478 … … 394 482 (hash . (list of hashes)) 395 483 (functions . (list of functions)))") 396 (add-hook 'plcmp- cleanup-hook (lambda () (setq plcmp-current-buffer-words-alist nil)))484 (add-hook 'plcmp--command-cleanup-hook (lambda () (setq plcmp-current-buffer-words-alist nil))) 397 485 398 486 ;; (with-current-buffer "Plagger.pm" … … 412 500 (function . ,functions)))))) 413 501 414 415 502 (defun plcmp-get-current-buffer-variables () 416 503 (let ((alist (plcmp-get-current-buffer-words-alist))) … … 477 564 478 565 479 480 (defsubst* plcmp-check-face (face-names &optional (point (point)))481 (let* ((face (get-text-property point 'face))482 (faces (if (listp face) face (list face))))483 (some (lambda (face-sym)484 (memq face-sym faces))485 face-names)))486 566 487 567 ;;; man … … 506 586 (defvar plcmp-doc-overlay nil "overlay") 507 587 (defvar plcmp-doc-current-point nil) 508 (add-hook 'plcmp- cleanup-hook588 (add-hook 'plcmp--command-cleanup-hook 509 589 (lambda () 510 590 (setq plcmp-doc-current-point nil))) 591 511 592 (defun plcmp-re-search-forward-fontify (regexp) 512 593 (when (re-search-forward regexp nil t) … … 533 614 plcmp-module-methods-alist (plcmp-get-module-methods-alist plcmp-using-modules) 534 615 plcmp-obj-instance-of-module-maybe-alist (plcmp-get-obj-instance-of-module-maybe-alist plcmp-using-modules) 535 plcmp-initial-input (plcmp-get-initial-input))) 616 ) 617 (multiple-value-setq 618 (plcmp-initial-input plcmp-real-initial-input) (plcmp-get-initial-real-input-list))) 536 619 537 620 (defun plcmp-cleanup () 538 621 (when (overlayp plcmp-doc-overlay) 539 622 (delete-overlay plcmp-doc-overlay)) 540 (run-hooks 'plcmp- cleanup-hook))623 (run-hooks 'plcmp--command-cleanup-hook)) 541 624 542 625 ;;;; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% … … 564 647 (defvar plcmp-type-man 565 648 '(plcmp-doc 566 (action . (("Show with Woman" . woman) 567 ("Insert" . insert) 649 (action . (("Show man" . 650 (lambda (candidate) 651 (plcmp-open-doc candidate 'man))) 652 ("Show man other window" . 653 (lambda (candidate) 654 (plcmp-open-doc candidate 'man 'pop-to-buffer))) 655 ("Show man other window and go" . 656 (lambda (candidate) 657 (plcmp-open-doc candidate 'man 'switch-to-buffer-other-window))) 658 ("Show man other frame and go" . 659 (lambda (candidate) 660 (plcmp-open-doc candidate 'man 'switch-to-buffer-other-frame))) 661 ("Insert man name" . insert) 568 662 ("Add command to kill-ring" . kill-new))))) 569 663 … … 581 675 582 676 ;;; perldoc 583 (defun* plcmp-open-perldoc (word &optional (type 'module) (show-fn 'switch-to-buffer)) 677 (defun plcmp-get-man-buffer (topic) 678 "like `Man-getpage-in-background' but call process synchronously. 679 return buffer or nil unless process return 0" 680 (require 'man) 681 (let* ((man-args topic) 682 (bufname (concat "*Man " man-args "*")) 683 (buffer (get-buffer bufname))) 684 (if buffer 685 buffer 686 (require 'env) 687 (message "Invoking %s %s in the background" manual-program man-args) 688 (setq buffer (generate-new-buffer bufname)) 689 (with-current-buffer buffer 690 (setq buffer-undo-list t) 691 (setq Man-original-frame (selected-frame)) 692 (setq Man-arguments man-args)) 693 (let ((process-environment (copy-sequence process-environment)) 694 ;; The following is so Awk script gets \n intact 695 ;; But don't prevent decoding of the outside. 696 (coding-system-for-write 'raw-text-unix) 697 ;; We must decode the output by a coding system that the 698 ;; system's locale suggests in multibyte mode. 699 (coding-system-for-read 700 (if default-enable-multibyte-characters 701 locale-coding-system 'raw-text-unix)) 702 ;; Avoid possible error by using a directory that always exists. 703 (default-directory 704 (if (and (file-directory-p default-directory) 705 (not (find-file-name-handler default-directory 706 'file-directory-p))) 707 default-directory 708 "/"))) 709 ;; Prevent any attempt to use display terminal fanciness. 710 (setenv "TERM" "dumb") 711 ;; In Debian Woody, at least, we get overlong lines under X 712 ;; unless COLUMNS or MANWIDTH is set. This isn't a problem on 713 ;; a tty. man(1) says: 714 ;; MANWIDTH 715 ;; If $MANWIDTH is set, its value is used as the line 716 ;; length for which manual pages should be formatted. 717 ;; If it is not set, manual pages will be formatted 718 ;; with a line length appropriate to the current ter- 719 ;; minal (using an ioctl(2) if available, the value of 720 ;; $COLUMNS, or falling back to 80 characters if nei- 721 ;; ther is available). 722 (if window-system 723 (unless (or (getenv "MANWIDTH") (getenv "COLUMNS")) 724 ;; This isn't strictly correct, since we don't know how 725 ;; the page will actually be displayed, but it seems 726 ;; reasonable. 727 (setenv "COLUMNS" (number-to-string 728 (cond 729 ((and (integerp Man-width) (> Man-width 0)) 730 Man-width) 731 (Man-width (frame-width)) 732 ((window-width))))))) 733 (setenv "GROFF_NO_SGR" "1") 734 (let ((exit-status 735 (call-process shell-file-name nil (list buffer nil) nil 736 shell-command-switch 737 (format (Man-build-man-command) man-args))) 738 (msg "")) 739 (when (and (numberp exit-status) 740 (= exit-status 0)) 741 (get-buffer bufname))))))) 742 743 (defun* plcmp-open-doc (topic &optional (type 'module) (show-fn 'switch-to-buffer)) 584 744 (require 'man) 585 745 (let ((manual-program (ecase type 586 746 (module "perldoc") 747 (man manual-program) 587 748 (function "perldoc -f") 588 749 (variable "perldoc perlvar")))) 589 (flet ((Man-notify-when-ready (man-buffer) 590 (funcall show-fn man-buffer))) 591 (Man-getpage-in-background word)))) 592 750 (let ((manbuf (plcmp-get-man-buffer topic))) 751 (when (bufferp manbuf) 752 (funcall show-fn manbuf))))) 593 753 594 754 ;;; open module file … … 602 762 603 763 (defun* plcmp-open-module-file (module-name &optional (show-buffer-fn 'switch-to-buffer)) 604 ( plcmp-aif (plcmp--find-module-file-no-select module-name)764 (anything-aif (plcmp--find-module-file-no-select module-name) 605 765 (funcall show-buffer-fn it) 606 766 (message "can't find %s" module-name))) … … 639 799 (init . (lambda () 640 800 (with-current-buffer (anything-candidate-buffer 'global) 641 (plcmp-insert-each-line plcmp-installed-modules)))) 642 (candidates-in-buffer))) 801 (plcmp-insert-each-line (plcmp-get-installed-modules))))) 802 (candidates-in-buffer) 803 )) 643 804 644 805 (defvar plcmp-anything-source-completion-buffer-dabbrevs … … 696 857 plcmp-anything-source-completion-installed-modules)) 697 858 698 (defun plcmp-get-sources- completion-all ()859 (defun plcmp-get-sources-for-complete-all () 699 860 (append 700 861 (plcmp-get-methods-completion-sources plcmp-using-modules) … … 702 863 703 864 (define-plcmp-command complete-all () 704 (anything (plcmp-get-sources- completion-all) plcmp-initial-input))865 (anything (plcmp-get-sources-for-complete-all) plcmp-initial-input)) 705 866 706 867 … … 776 937 (t 777 938 'otherwise)))))) 778 779 (defun plcmp-get-sources- completion-smart()939 ;; TODO 940 (defun plcmp-get-sources-for-smart-complete () 780 941 "return sources" 781 (let ((ctx (plcmp--get-context-symbol)))782 (case ctx 783 (otherwise (plcmp-get-sources- completion-all)))))942 (let ((ctx-sym (plcmp--get-context-symbol))) 943 (case ctx-sym 944 (otherwise (plcmp-get-sources-for-complete-all))))) 784 945 785 946 ;;; document … … 793 954 (anything '(plcmp-anything-source-menu))) 794 955 795 (defun plcmp-cmd-clear-all-cache ()956 (defun plcmp-cmd-clear-all-caches () 796 957 (interactive) 797 (ignore-errors 798 (setq plcmp-module-methods-alist nil 799 plcmp-installed-modules nil) 800 (message "cleared all caches"))) 958 (dolist (variable plcmp--cached-variables) 959 (set variable nil)) 960 (message "cleared all caches")) 801 961 802 962 (defun plcmp-cmd-show-environment () … … 839 999 (expectations 840 1000 (desc "define-plcmp-command macro expand") 841 (expect '(defun plcmp-cmd-test (arg1 arg2) (interactive) (cl-block-wrapper (catch (quote --cl-block-plcmp-cmd-test--) (plcmp-initialize-variables) (progn "test")))) 1001 (expect '(defun plcmp-cmd-test (arg1 arg2) 1002 (interactive) 1003 (cl-block-wrapper 1004 (catch (quote --cl-block-plcmp-cmd-test--) 1005 (unwind-protect 1006 (progn (plcmp-initialize-variables) 1007 (progn "body")) 1008 (plcmp-cleanup))))) 842 1009 (macroexpand-all 843 1010 '(define-plcmp-command test (arg1 arg2) 844 " test")))1011 "body"))) 845 1012 (desc "plcmp-get-face-words") 846 1013 (expect nil … … 879 1046 (expect 'plcmp-anything-source-completion-builtin-variables 880 1047 (car (plcmp-re-sort-sources "variables" plcmp-completion-all-static-sources))) 1048 1049 (desc "plcmp--get-lib-path") 1050 (expect "~/c/plagger/lib" 1051 (stub plcmp-get-current-directory => "~/c/plagger/lib/Plagger/TT/Plagger/") 1052 (plcmp--get-lib-path)) 1053 (expect "~/c/plagger/lib" 1054 (stub plcmp-get-current-directory => "~/c/plagger/
![(please configure the [header_logo] section in trac.ini)](/share/chrome/site/your_project_logo.png)