| 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 |
| 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 |
| 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") |
| 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) |
| 421 | | モジュール名に使用できる文字以外が含まれていた場合はnilを返す |
| 422 | | return los" |
| | 297 | モジュール名に使用でき-る文字以外が含まれていた場合はnilを返す |
| | 298 | return 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 |   |