From ab422c4d6899b1442cb6954c1829c1fb656b006c Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Tue, 1 Jan 2013 09:11:05 +0000 Subject: Update copyright notices for 2013. --- lisp/emacs-lisp/lisp.el | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lisp/emacs-lisp/lisp.el') diff --git a/lisp/emacs-lisp/lisp.el b/lisp/emacs-lisp/lisp.el index bcb7fab026b..22fb6ad1809 100644 --- a/lisp/emacs-lisp/lisp.el +++ b/lisp/emacs-lisp/lisp.el @@ -1,6 +1,7 @@ ;;; lisp.el --- Lisp editing commands for Emacs -;; Copyright (C) 1985-1986, 1994, 2000-2012 Free Software Foundation, Inc. +;; Copyright (C) 1985-1986, 1994, 2000-2013 Free Software Foundation, +;; Inc. ;; Maintainer: FSF ;; Keywords: lisp, languages -- cgit v1.2.3 From dd8791e96feb4915c895a4879deee67e672e0a7f Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Wed, 17 Apr 2013 16:52:02 -0400 Subject: * lisp/emacs-lisp/lisp.el (lisp-completion-at-point): Provide specialized completion tables when completing error conditions and `declare' arguments. (lisp-complete-symbol, field-complete): Mark as obsolete. (check-parens): Unmatched parens are user errors. * lisp/minibuffer.el (minibuffer-completion-contents): Mark as obsolete. --- etc/NEWS | 6 +++- lisp/ChangeLog | 25 +++++++++++----- lisp/emacs-lisp/lisp.el | 80 +++++++++++++++++++++++++++++++++---------------- lisp/minibuffer.el | 3 +- 4 files changed, 78 insertions(+), 36 deletions(-) (limited to 'lisp/emacs-lisp/lisp.el') diff --git a/etc/NEWS b/etc/NEWS index 0830a7be469..5bf0cb302ff 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -323,7 +323,11 @@ file using `set-file-extended-attributes'. * Lisp Changes in Emacs 24.4 -** `dont-compile' is declared obsolete. +** Obsoleted functions: +*** `dont-compile' +*** `lisp-complete-symbol' +*** `field-complete' +*** `minibuffer-completion-contents' ** `get-upcase-table' is obsoleted by the new `case-table-get-table'. diff --git a/lisp/ChangeLog b/lisp/ChangeLog index ffa0c840554..4ace42afa09 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,13 +1,22 @@ +2013-04-17 Stefan Monnier + + * emacs-lisp/lisp.el (lisp-completion-at-point): Provide specialized + completion tables when completing error conditions and + `declare' arguments. + (lisp-complete-symbol, field-complete): Mark as obsolete. + (check-parens): Unmatched parens are user errors. + * minibuffer.el (minibuffer-completion-contents): Mark as obsolete. + 2013-04-17 Michal Nazarewicz - * textmodes/flyspell.el (flyspell-check-pre-word-p): Return nil if - command changed buffer (ie. `flyspell-pre-buffer' is not current - buffer), which prevents making decisions based on invalid value of - `flyspell-pre-point' in the wrong buffer. Most notably, this used to - cause an error when `flyspell-pre-point' was nil after switching - buffers - (flyspell-post-command-hook): No longer needs to change buffers when - checking pre-word. While at it remove unnecessary progn. + * textmodes/flyspell.el (flyspell-check-pre-word-p): Return nil if + command changed buffer (ie. `flyspell-pre-buffer' is not current + buffer), which prevents making decisions based on invalid value of + `flyspell-pre-point' in the wrong buffer. Most notably, this used to + cause an error when `flyspell-pre-point' was nil after switching + buffers. + (flyspell-post-command-hook): No longer needs to change buffers when + checking pre-word. While at it remove unnecessary progn. 2013-04-17 Nicolas Richard (tiny change) diff --git a/lisp/emacs-lisp/lisp.el b/lisp/emacs-lisp/lisp.el index 22fb6ad1809..f301a1875ed 100644 --- a/lisp/emacs-lisp/lisp.el +++ b/lisp/emacs-lisp/lisp.el @@ -46,6 +46,12 @@ This affects `insert-parentheses' and `insert-pair'." :group 'lisp) (defvar forward-sexp-function nil + ;; FIXME: + ;; - for some uses, we may want a "sexp-only" version, which only + ;; jumps over a well-formed sexp, rather than some dwimish thing + ;; like jumping from an "else" back up to its "if". + ;; - for up-list, we could use the "sexp-only" behavior as well + ;; to treat the dwimish halfsexp as a form of "up-list" step. "If non-nil, `forward-sexp' delegates to this function. Should take the same arguments and behave similarly to `forward-sexp'.") @@ -618,9 +624,10 @@ character." ;; "Unbalanced parentheses", but those may not be so ;; accurate/helpful, e.g. quotes may actually be ;; mismatched. - (error "Unmatched bracket or quote")))) + (user-error "Unmatched bracket or quote")))) (defun field-complete (table &optional predicate) + (declare (obsolete completion-in-region "24.4")) (let ((minibuffer-completion-table table) (minibuffer-completion-predicate predicate) ;; This made sense for lisp-complete-symbol, but for @@ -645,6 +652,7 @@ considered. If the symbol starts just after an open-parenthesis, only symbols with function definitions are considered. Otherwise, all symbols with function definitions, values or properties are considered." + (declare (obsolete completion-at-point "24.4")) (interactive) (let* ((data (lisp-completion-at-point predicate)) (plist (nthcdr 3 data))) @@ -666,25 +674,6 @@ considered." (skip-syntax-forward "'") (point)) (scan-error pos))) - (predicate - (or predicate - (save-excursion - (goto-char beg) - (if (not (eq (char-before) ?\()) - (lambda (sym) ;why not just nil ? -sm - (or (boundp sym) (fboundp sym) - (symbol-plist sym))) - ;; Looks like a funcall position. Let's double check. - (if (condition-case nil - (progn (up-list -2) (forward-char 1) - (eq (char-after) ?\()) - (error nil)) - ;; If the first element of the parent list is an open - ;; paren we are probably not in a funcall position. - ;; Maybe a `let' varlist or something. - nil - ;; Else, we assume that a function name is expected. - 'fboundp))))) (end (unless (or (eq beg (point-max)) (member (char-syntax (char-after beg)) '(?\" ?\( ?\)))) @@ -694,12 +683,51 @@ considered." (forward-sexp 1) (when (>= (point) pos) (point))) - (scan-error pos))))) + (scan-error pos)))) + (funpos (eq (char-before beg) ?\()) ;t if in function position. + (table-etc + (if (not funpos) + ;; FIXME: We could look at the first element of the list and + ;; use it to provide a more specific completion table in some + ;; cases. E.g. filter out keywords that are not understood by + ;; the macro/function being called. + (list nil obarray ;Could be anything. + :annotation-function + (lambda (str) (if (fboundp (intern-soft str)) " "))) + ;; Looks like a funcall position. Let's double check. + (save-excursion + (goto-char (1- beg)) + (let ((parent + (condition-case nil + (progn (up-list -1) (forward-char 1) + (let ((c (char-after))) + (if (eq c ?\() ?\( + (if (memq (char-syntax c) '(?w ?_)) + (read (current-buffer)))))) + (error nil)))) + (pcase parent + ;; FIXME: Rather than hardcode special cases here, + ;; we should use something like a symbol-property. + (`declare + (list t (mapcar (lambda (x) (symbol-name (car x))) + (delete-dups + (append + macro-declarations-alist + defun-declarations-alist))))) + ((or `condition-case `condition-case-unless-debug) + (list t obarray + :predicate (lambda (sym) (get sym 'error-conditions)))) + (_ (list nil obarray #'fboundp)))))))) (when end - (list beg end obarray - :predicate predicate - :annotation-function - (unless (eq predicate 'fboundp) - (lambda (str) (if (fboundp (intern-soft str)) " ")))))))) + (let ((tail (if (null (car table-etc)) + (cdr table-etc) + (cons + (if (memq (char-syntax (char-after end)) + '(?\s ?>)) + (cadr table-etc) + (apply-partially 'completion-table-with-terminator + " " (cadr table-etc))) + (cddr table-etc))))) + `(,beg ,end ,@tail)))))) ;;; lisp.el ends here diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index 06ac7a91bea..64e816cef38 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el @@ -638,7 +638,8 @@ If ARGS are provided, then pass MESSAGE through `format'." (defun minibuffer-completion-contents () "Return the user input in a minibuffer before point as a string. -That is what completion commands operate on." +That used to be what completion commands operate on." + (declare (obsolete minibuffer-contents "24.4")) (buffer-substring (field-beginning) (point))) (defun delete-minibuffer-contents () -- cgit v1.2.3 From c902337068f52666425b7647e5aa43c621146e56 Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Fri, 24 May 2013 23:00:13 -0400 Subject: * lisp/emacs-lisp/lisp.el (lisp-completion-at-point): Don't use error-completion on the first 2 args of condition-case. Fixes: debbugs:14446 --- lisp/ChangeLog | 5 +++++ lisp/emacs-lisp/lisp.el | 6 +++++- 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'lisp/emacs-lisp/lisp.el') diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 055a552073d..57625ef4dbe 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,8 @@ +2013-05-25 Stefan Monnier + + * emacs-lisp/lisp.el (lisp-completion-at-point): Don't use + error-completion on the first 2 args of condition-case (bug#14446). + 2013-05-25 Leo Liu * comint.el (comint-previous-matching-input): Do not flood the diff --git a/lisp/emacs-lisp/lisp.el b/lisp/emacs-lisp/lisp.el index f301a1875ed..ce8f45e9730 100644 --- a/lisp/emacs-lisp/lisp.el +++ b/lisp/emacs-lisp/lisp.el @@ -714,7 +714,11 @@ considered." (append macro-declarations-alist defun-declarations-alist))))) - ((or `condition-case `condition-case-unless-debug) + ((and (or `condition-case `condition-case-unless-debug) + (guard (save-excursion + (ignore-errors + (forward-sexp 2) + (< (point) beg))))) (list t obarray :predicate (lambda (sym) (get sym 'error-conditions)))) (_ (list nil obarray #'fboundp)))))))) -- cgit v1.2.3 From df76dacbd1f6830c96cf63053efe776d40c0e84d Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Fri, 24 May 2013 23:08:04 -0400 Subject: * lisp/emacs-lisp/lisp.el (lisp-completion-at-point): Don't burp at EOB. Fixes: debbugs:14446 --- lisp/ChangeLog | 1 + lisp/emacs-lisp/lisp.el | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'lisp/emacs-lisp/lisp.el') diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 57625ef4dbe..efa6f06cbb1 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -2,6 +2,7 @@ * emacs-lisp/lisp.el (lisp-completion-at-point): Don't use error-completion on the first 2 args of condition-case (bug#14446). + Don't burp at EOB. 2013-05-25 Leo Liu diff --git a/lisp/emacs-lisp/lisp.el b/lisp/emacs-lisp/lisp.el index ce8f45e9730..b221d2f823d 100644 --- a/lisp/emacs-lisp/lisp.el +++ b/lisp/emacs-lisp/lisp.el @@ -726,7 +726,7 @@ considered." (let ((tail (if (null (car table-etc)) (cdr table-etc) (cons - (if (memq (char-syntax (char-after end)) + (if (memq (char-syntax (or (char-after end) ?\s)) '(?\s ?>)) (cadr table-etc) (apply-partially 'completion-table-with-terminator -- cgit v1.2.3 From bbcc4d97447a8a138c65bc94f800c0165f556610 Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Mon, 3 Jun 2013 11:40:35 -0400 Subject: * lisp.el: Provide completion of locally bound variables in Elisp. * lisp/emacs-lisp/lisp.el: Use lexical-binding. (lisp--local-variables-1, lisp--local-variables): New functions. (lisp--local-variables-completion-table): New var. (lisp-completion-at-point): Use it to provide completion of let-bound vars. --- lisp/ChangeLog | 5 +++ lisp/emacs-lisp/lisp.el | 104 ++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 101 insertions(+), 8 deletions(-) (limited to 'lisp/emacs-lisp/lisp.el') diff --git a/lisp/ChangeLog b/lisp/ChangeLog index ac3dbcf906b..29c912933c8 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,5 +1,10 @@ 2013-06-03 Stefan Monnier + * emacs-lisp/lisp.el: Use lexical-binding. + (lisp--local-variables-1, lisp--local-variables): New functions. + (lisp--local-variables-completion-table): New var. + (lisp-completion-at-point): Use it to provide completion of let-bound vars. + * emacs-lisp/lisp-mode.el (eval-sexp-add-defvars): Expand macros eagerly (bug#14422). diff --git a/lisp/emacs-lisp/lisp.el b/lisp/emacs-lisp/lisp.el index b221d2f823d..a31bef2391d 100644 --- a/lisp/emacs-lisp/lisp.el +++ b/lisp/emacs-lisp/lisp.el @@ -1,4 +1,4 @@ -;;; lisp.el --- Lisp editing commands for Emacs +;;; lisp.el --- Lisp editing commands for Emacs -*- lexical-binding:t -*- ;; Copyright (C) 1985-1986, 1994, 2000-2013 Free Software Foundation, ;; Inc. @@ -262,9 +262,9 @@ is called as a function to find the defun's beginning." ;; convention, fallback on the old implementation. (wrong-number-of-arguments (if (> arg 0) - (dotimes (i arg) + (dotimes (_ arg) (funcall beginning-of-defun-function)) - (dotimes (i (- arg)) + (dotimes (_ (- arg)) (funcall end-of-defun-function)))))) ((or defun-prompt-regexp open-paren-in-column-0-is-defun-start) @@ -442,7 +442,7 @@ it marks the next defun after the ones already marked." (beginning-of-defun)) (re-search-backward "^\n" (- (point) 1) t))))) -(defun narrow-to-defun (&optional arg) +(defun narrow-to-defun (&optional _arg) "Make text outside current defun invisible. The defun visible is the one that contains point or follows point. Optional ARG is ignored." @@ -662,10 +662,96 @@ considered." (completion-in-region (nth 0 data) (nth 1 data) (nth 2 data) (plist-get plist :predicate)))))) - -(defun lisp-completion-at-point (&optional predicate) +(defun lisp--local-variables-1 (vars sexp) + "Return the vars locally bound around the witness, or nil if not found." + (let (res) + (while + (unless + (setq res + (pcase sexp + (`(,(or `let `let*) ,bindings) + (let ((vars vars)) + (when (eq 'let* (car sexp)) + (dolist (binding (cdr (reverse bindings))) + (push (or (car-safe binding) binding) vars))) + (lisp--local-variables-1 + vars (car (cdr-safe (car (last bindings))))))) + (`(,(or `let `let*) ,bindings . ,body) + (let ((vars vars)) + (dolist (binding bindings) + (push (or (car-safe binding) binding) vars)) + (lisp--local-variables-1 vars (car (last body))))) + (`(lambda ,_) (setq sexp nil)) + (`(lambda ,args . ,body) + (lisp--local-variables-1 + (append args vars) (car (last body)))) + (`(condition-case ,_ ,e) (lisp--local-variables-1 vars e)) + (`(condition-case ,v ,_ . ,catches) + (lisp--local-variables-1 + (cons v vars) (cdr (car (last catches))))) + (`(,_ . ,_) + (lisp--local-variables-1 vars (car (last sexp)))) + (`lisp--witness--lisp (or vars '(nil))) + (_ nil))) + (setq sexp (ignore-errors (butlast sexp))))) + res)) + +(defun lisp--local-variables () + "Return a list of locally let-bound variables at point." + (save-excursion + (skip-syntax-backward "w_") + (let* ((ppss (syntax-ppss)) + (txt (buffer-substring-no-properties (or (car (nth 9 ppss)) (point)) + (or (nth 8 ppss) (point)))) + (closer ())) + (dolist (p (nth 9 ppss)) + (push (cdr (syntax-after p)) closer)) + (setq closer (apply #'string closer)) + (let* ((sexp (car (read-from-string + (concat txt "lisp--witness--lisp" closer)))) + (macroexpand-advice (lambda (expander form &rest args) + (condition-case nil + (apply expander form args) + (error form)))) + (sexp + (unwind-protect + (progn + (advice-add 'macroexpand :around macroexpand-advice) + (macroexpand-all sexp)) + (advice-remove 'macroexpand macroexpand-advice))) + (vars (lisp--local-variables-1 nil sexp))) + (delq nil + (mapcar (lambda (var) + (and (symbolp var) + (not (string-match (symbol-name var) "\\`[&_]")) + ;; Eliminate uninterned vars. + (intern-soft var) + var)) + vars)))))) + +(defvar lisp--local-variables-completion-table + ;; Use `defvar' rather than `defconst' since defconst would purecopy this + ;; value, which would doubly fail: it would fail because purecopy can't + ;; handle the recursive bytecode object, and it would fail because it would + ;; move `lastpos' and `lastvars' to pure space where they'd be immutable! + (let ((lastpos nil) (lastvars nil)) + (letrec ((hookfun (lambda () + (setq lastpos nil) + (remove-hook 'post-command-hook hookfun)))) + (completion-table-dynamic + (lambda (_string) + (save-excursion + (skip-syntax-backward "_w") + (let ((newpos (cons (point) (current-buffer)))) + (unless (equal lastpos newpos) + (add-hook 'post-command-hook hookfun) + (setq lastpos newpos) + (setq lastvars + (mapcar #'symbol-name (lisp--local-variables)))))) + lastvars))))) + +(defun lisp-completion-at-point (&optional _predicate) "Function used for `completion-at-point-functions' in `emacs-lisp-mode'." - ;; FIXME: the `end' could be after point? (with-syntax-table emacs-lisp-mode-syntax-table (let* ((pos (point)) (beg (condition-case nil @@ -691,7 +777,9 @@ considered." ;; use it to provide a more specific completion table in some ;; cases. E.g. filter out keywords that are not understood by ;; the macro/function being called. - (list nil obarray ;Could be anything. + (list nil (completion-table-in-turn + lisp--local-variables-completion-table + obarray) ;Could be anything. :annotation-function (lambda (str) (if (fboundp (intern-soft str)) " "))) ;; Looks like a funcall position. Let's double check. -- cgit v1.2.3