+(defvar completion-in-region-functions nil
+ "Wrapper hook around `completion-in-region'.
+The functions on this special hook are called with 5 arguments:
+ NEXT-FUN START END COLLECTION PREDICATE.
+NEXT-FUN is a function of four arguments (START END COLLECTION PREDICATE)
+that performs the default operation. The other four arguments are like
+the ones passed to `completion-in-region'. The functions on this hook
+are expected to perform completion on START..END using COLLECTION
+and PREDICATE, either by calling NEXT-FUN or by doing it themselves.")
+
+(defun completion-in-region (start end collection &optional predicate)
+ "Complete the text between START and END using COLLECTION.
+Return nil if there is no valid completion, else t.
+Point needs to be somewhere between START and END."
+ (assert (<= start (point)) (<= (point) end))
+ ;; FIXME: undisplay the *Completions* buffer once the completion is done.
+ (with-wrapper-hook
+ completion-in-region-functions (start end collection predicate)
+ (let ((minibuffer-completion-table collection)
+ (minibuffer-completion-predicate predicate)
+ (ol (make-overlay start end nil nil t)))
+ (overlay-put ol 'field 'completion)
+ (unwind-protect
+ (call-interactively 'minibuffer-complete)
+ (delete-overlay ol)))))
+
+(defvar completion-at-point-functions nil
+ "Special hook to find the completion table for the thing at point.
+It is called without any argument and should return either nil,
+or a function of no argument to perform completion (discouraged),
+or a list of the form (START END COLLECTION &rest PROPS) where
+ START and END delimit the entity to complete and should include point,
+ COLLECTION is the completion table to use to complete it, and
+ PROPS is a property list for additional information.
+Currently supported properties are:
+ `:predicate' a predicate that completion candidates need to satisfy.
+ `:annotation-function' the value to use for `completion-annotate-function'.")
+
+(defun completion-at-point ()
+ "Complete the thing at point according to local mode.
+This runs the hook `completion-at-point-functions' until a member returns
+non-nil."
+ (interactive)
+ (let ((res (run-hook-with-args-until-success
+ 'completion-at-point-functions)))
+ (cond
+ ((functionp res) (funcall res))
+ (res
+ (let* ((plist (nthcdr 3 res))
+ (start (nth 0 res))
+ (end (nth 1 res))
+ (completion-annotate-function
+ (or (plist-get plist :annotation-function)
+ completion-annotate-function)))
+ (completion-in-region start end (nth 2 res)
+ (plist-get plist :predicate)))))))
+