aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThierry Volpiatto2014-09-04 10:49:56 -0400
committerStefan Monnier2014-09-04 10:49:56 -0400
commite77bcfa34d3dfd0efb6ffb40e4035374e22143fc (patch)
treeedbf705069b7b6797c0280c9d1aea445128cf5ec
parentbaff67fcd5d64af9d218204111d2566ae408c967 (diff)
downloademacs-e77bcfa34d3dfd0efb6ffb40e4035374e22143fc.tar.gz
emacs-e77bcfa34d3dfd0efb6ffb40e4035374e22143fc.zip
* lisp/emacs-lisp/eldoc.el (eldoc-highlight-function-argument): Handle the
case where we're currently providing part of the &rest arg after some &key args, as in define-ibuffer-op. Fixes: debbugs:18048
-rw-r--r--lisp/ChangeLog6
-rw-r--r--lisp/emacs-lisp/eldoc.el72
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 @@
12014-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
12014-09-03 Stefan Monnier <monnier@iro.umontreal.ca> 72014-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.
371In the absence of INDEX, just call `eldoc-docstring-format-sym-doc'." 371In 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