diff options
| -rw-r--r-- | lisp/ChangeLog | 6 | ||||
| -rw-r--r-- | lisp/emacs-lisp/eldoc.el | 72 |
2 files changed, 62 insertions, 16 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index d8c48287c14..78d3cf56321 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,9 @@ | |||
| 1 | 2014-09-04 Thierry Volpiatto <thierry.volpiatto@gmail.com> | ||
| 2 | |||
| 3 | * emacs-lisp/eldoc.el (eldoc-highlight-function-argument): Handle the | ||
| 4 | case where we're currently providing part of the &rest arg after some | ||
| 5 | &key args, as in define-ibuffer-op (bug#18048). | ||
| 6 | |||
| 1 | 2014-09-03 Stefan Monnier <monnier@iro.umontreal.ca> | 7 | 2014-09-03 Stefan Monnier <monnier@iro.umontreal.ca> |
| 2 | 8 | ||
| 3 | * progmodes/which-func.el (which-func-ff-hook): Obey pre-existing | 9 | * progmodes/which-func.el (which-func-ff-hook): Obey pre-existing |
diff --git a/lisp/emacs-lisp/eldoc.el b/lisp/emacs-lisp/eldoc.el index 0b8304af29f..acb1bdc32e8 100644 --- a/lisp/emacs-lisp/eldoc.el +++ b/lisp/emacs-lisp/eldoc.el | |||
| @@ -369,9 +369,16 @@ or elsewhere, return a 1-line docstring." | |||
| 369 | (defun eldoc-highlight-function-argument (sym args index) | 369 | (defun eldoc-highlight-function-argument (sym args index) |
| 370 | "Highlight argument INDEX in ARGS list for function SYM. | 370 | "Highlight argument INDEX in ARGS list for function SYM. |
| 371 | In the absence of INDEX, just call `eldoc-docstring-format-sym-doc'." | 371 | In the absence of INDEX, just call `eldoc-docstring-format-sym-doc'." |
| 372 | ;; FIXME: This should probably work on the list representation of `args' | ||
| 373 | ;; rather than its string representation. | ||
| 374 | ;; FIXME: This function is much too long, we need to split it up! | ||
| 372 | (let ((start nil) | 375 | (let ((start nil) |
| 373 | (end 0) | 376 | (end 0) |
| 374 | (argument-face 'eldoc-highlight-function-argument)) | 377 | (argument-face 'eldoc-highlight-function-argument) |
| 378 | (args-lst (mapcar (lambda (x) | ||
| 379 | (replace-regexp-in-string | ||
| 380 | "\\`[(]\\|[)]\\'" "" x)) | ||
| 381 | (split-string args)))) | ||
| 375 | ;; Find the current argument in the argument string. We need to | 382 | ;; Find the current argument in the argument string. We need to |
| 376 | ;; handle `&rest' and informal `...' properly. | 383 | ;; handle `&rest' and informal `...' properly. |
| 377 | ;; | 384 | ;; |
| @@ -385,23 +392,53 @@ In the absence of INDEX, just call `eldoc-docstring-format-sym-doc'." | |||
| 385 | ;; position in ARGS based on this current arg. | 392 | ;; position in ARGS based on this current arg. |
| 386 | (when (string-match "&key" args) | 393 | (when (string-match "&key" args) |
| 387 | (let* (case-fold-search | 394 | (let* (case-fold-search |
| 395 | key-have-value | ||
| 396 | (sym-name (symbol-name sym)) | ||
| 388 | (cur-w (current-word)) | 397 | (cur-w (current-word)) |
| 398 | (args-lst-ak (cdr (member "&key" args-lst))) | ||
| 389 | (limit (save-excursion | 399 | (limit (save-excursion |
| 390 | (when (re-search-backward (symbol-name sym) nil t) | 400 | (when (re-search-backward sym-name nil t) |
| 391 | (match-end 0)))) | 401 | (match-end 0)))) |
| 392 | (cur-a (if (string-match ":\\([^ ()]*\\)" cur-w) | 402 | (cur-a (if (and cur-w (string-match ":\\([^ ()]*\\)" cur-w)) |
| 393 | (substring cur-w 1) | 403 | (substring cur-w 1) |
| 394 | (save-excursion | 404 | (save-excursion |
| 395 | (when (re-search-backward ":\\([^ ()\n]*\\)" limit t) | 405 | (let (split) |
| 396 | (match-string 1)))))) | 406 | (when (re-search-backward ":\\([^()\n]*\\)" limit t) |
| 397 | ;; If `cur-a' is nil probably cursor is on a positional arg | 407 | (setq split (split-string (match-string 1) " " t)) |
| 398 | ;; before `&key', in this case, exit this block and determine | 408 | (prog1 (car split) |
| 399 | ;; position with `index'. | 409 | (when (cdr split) |
| 400 | (when (and cur-a | 410 | (setq key-have-value t)))))))) |
| 401 | (string-match (concat "\\_<" (upcase cur-a) "\\_>") args)) | 411 | ;; If `cur-a' is not one of `args-lst-ak' |
| 402 | (setq index nil ; Skip next block based on positional args. | 412 | ;; assume user is entering an unknow key |
| 403 | start (match-beginning 0) | 413 | ;; referenced in last position in signature. |
| 404 | end (match-end 0))))) | 414 | (other-key-arg (and (stringp cur-a) |
| 415 | args-lst-ak | ||
| 416 | (not (member (upcase cur-a) args-lst-ak)) | ||
| 417 | (upcase (car (last args-lst-ak)))))) | ||
| 418 | (unless (string= cur-w sym-name) | ||
| 419 | ;; The last keyword have already a value | ||
| 420 | ;; i.e :foo a b and cursor is at b. | ||
| 421 | ;; If signature have also `&rest' | ||
| 422 | ;; (assume it is after the `&key' section) | ||
| 423 | ;; go to the arg after `&rest'. | ||
| 424 | (if (and key-have-value | ||
| 425 | (save-excursion | ||
| 426 | (not (re-search-forward ":.*" (point-at-eol) t))) | ||
| 427 | (string-match "&rest \\([^ ()]*\\)" args)) | ||
| 428 | (setq index nil ; Skip next block based on positional args. | ||
| 429 | start (match-beginning 1) | ||
| 430 | end (match-end 1)) | ||
| 431 | ;; If `cur-a' is nil probably cursor is on a positional arg | ||
| 432 | ;; before `&key', in this case, exit this block and determine | ||
| 433 | ;; position with `index'. | ||
| 434 | (when (and cur-a ; A keyword arg (dot removed) or nil. | ||
| 435 | (or (string-match | ||
| 436 | (concat "\\_<" (upcase cur-a) "\\_>") args) | ||
| 437 | (string-match | ||
| 438 | (concat "\\_<" other-key-arg "\\_>") args))) | ||
| 439 | (setq index nil ; Skip next block based on positional args. | ||
| 440 | start (match-beginning 0) | ||
| 441 | end (match-end 0))))))) | ||
| 405 | ;; Handle now positional arguments. | 442 | ;; Handle now positional arguments. |
| 406 | (while (and index (>= index 1)) | 443 | (while (and index (>= index 1)) |
| 407 | (if (string-match "[^ ()]+" args end) | 444 | (if (string-match "[^ ()]+" args end) |
| @@ -412,12 +449,15 @@ In the absence of INDEX, just call `eldoc-docstring-format-sym-doc'." | |||
| 412 | (cond ((string= argument "&rest") | 449 | (cond ((string= argument "&rest") |
| 413 | ;; All the rest arguments are the same. | 450 | ;; All the rest arguments are the same. |
| 414 | (setq index 1)) | 451 | (setq index 1)) |
| 415 | ((string= argument "&optional")) ; Skip. | 452 | ((string= argument "&optional")) ; Skip. |
| 416 | ((string= argument "&allow-other-keys")) ; Skip. | 453 | ((string= argument "&allow-other-keys")) ; Skip. |
| 417 | ;; Back to index 0 in ARG1 ARG2 ARG2 ARG3 etc... | 454 | ;; Back to index 0 in ARG1 ARG2 ARG2 ARG3 etc... |
| 418 | ;; like in `setq'. | 455 | ;; like in `setq'. |
| 419 | ((or (string-match-p "\\.\\.\\.$" argument) | 456 | ((or (and (string-match-p "\\.\\.\\.$" argument) |
| 420 | (and (string-match-p "\\.\\.\\.)?$" args) | 457 | (string= argument (car (last args-lst)))) |
| 458 | (and (string-match-p "\\.\\.\\.$" | ||
| 459 | (substring args 1 (1- (length args)))) | ||
| 460 | (= (length (remove "..." args-lst)) 2) | ||
| 421 | (> index 1) (cl-oddp index))) | 461 | (> index 1) (cl-oddp index))) |
| 422 | (setq index 0)) | 462 | (setq index 0)) |
| 423 | (t | 463 | (t |