Function: python-shell-completion-at-point

python-shell-completion-at-point is a byte-compiled function defined in python.el.gz.

Signature

(python-shell-completion-at-point &optional PROCESS)

Documentation

Function for completion-at-point-functions in inferior-python-mode.

Optional argument PROCESS forces completions to be retrieved using that one instead of current buffer's process.

Aliases

python-shell-completion-complete-at-point (obsolete since 25.1)

Source Code

;; Defined in /usr/src/emacs/lisp/progmodes/python.el.gz
(defun python-shell-completion-at-point (&optional process)
  "Function for `completion-at-point-functions' in `inferior-python-mode'.
Optional argument PROCESS forces completions to be retrieved
using that one instead of current buffer's process."
  (setq process (or process (get-buffer-process (current-buffer))))
  (unless process
    (user-error "No active python inferior process"))
  (let* ((is-shell-buffer (derived-mode-p 'inferior-python-mode))
         (line-start (if is-shell-buffer
                         ;; Working on a shell buffer: use prompt end.
                         (cdr (python-util-comint-last-prompt))
                       (line-beginning-position)))
         (no-delims
          (and (not (if is-shell-buffer
                        (eq 'font-lock-comment-face
                            (get-text-property (1- (point)) 'face))
                      (python-syntax-context 'comment)))
               (with-current-buffer (process-buffer process)
                 (if python-shell-completion-native-enable
                     (string= python-shell-readline-completer-delims "")
                   (or (string-match-p "ipython[23]?\\'" python-shell-interpreter)
                       (equal python-shell-readline-completer-delims ""))))))
         (start
          (if (< (point) line-start)
              (point)
            (save-excursion
              (if (or no-delims
                      (not (re-search-backward
                            (python-rx
                             (or whitespace open-paren close-paren
                                 string-delimiter simple-operator))
                            line-start
                            t 1)))
                  line-start
                (forward-char (length (match-string-no-properties 0)))
                (point)))))
         (end (point))
         (prompt-boundaries
          (with-current-buffer (process-buffer process)
            (python-util-comint-last-prompt)))
         (prompt
          (with-current-buffer (process-buffer process)
            (when prompt-boundaries
              (buffer-substring-no-properties
               (car prompt-boundaries) (cdr prompt-boundaries)))))
         (completion-fn
          (with-current-buffer (process-buffer process)
            (cond ((or (null prompt)
                       (and is-shell-buffer
                            (< (point) (cdr prompt-boundaries)))
                       (and (not is-shell-buffer)
                            (string-match-p
                             python-shell-prompt-pdb-regexp prompt)))
                   #'ignore)
                  ((or (not python-shell-completion-native-enable)
                       ;; Even if native completion is enabled, for
                       ;; pdb interaction always use the fallback
                       ;; mechanism since the completer is changed.
                       ;; Also, since pdb interaction is single-line
                       ;; based, this is enough.
                       (string-match-p python-shell-prompt-pdb-regexp prompt))
                   (if (or (equal python-shell--block-prompt prompt)
                           (string-match-p
                            python-shell-prompt-block-regexp prompt))
                       ;; The non-native completion mechanism sends
                       ;; newlines to the interpreter, so we can't use
                       ;; it during a multiline statement (Bug#28051).
                       #'ignore
                     #'python-shell-completion-get-completions))
                  (t #'python-shell-completion-native-get-completions))))
         (prev-prompt (car python-shell--capf-cache))
         (re (or (cadr python-shell--capf-cache) regexp-unmatchable))
         (prefix (buffer-substring-no-properties start end))
         (prefix-offset 0)
         (extra-context (when no-delims
                          (if is-shell-buffer
                              (python-shell--extra-completion-context)
                            (python-shell-completion-extra-context))))
         (extra-offset (length extra-context)))
    (unless (zerop extra-offset)
      (setq prefix (concat extra-context prefix)))
    ;; To invalidate the cache, we check if the prompt position or the
    ;; completion prefix changed.
    (unless (and (equal prev-prompt (car prompt-boundaries))
                 (string-match re prefix)
                 (setq prefix-offset (- (length prefix) (match-end 1))))
      (setq python-shell--capf-cache
            `(,(car prompt-boundaries)
              ,(if (string-empty-p prefix)
                   regexp-unmatchable
                 (concat "\\`\\(" (regexp-quote prefix) "\\)\\(?:\\sw\\|\\s_\\)*\\'"))
              ,@(funcall completion-fn process prefix))))
    (let ((cands (cddr python-shell--capf-cache)))
      (cond
       ((stringp (car cands))
        (if no-delims
            ;; Reduce completion candidates due to long prefix.
            (if-let* ((Lp (length prefix))
                      ((string-match "\\(\\sw\\|\\s_\\)+\\'" prefix))
                      (L (match-beginning 0)))
                ;; If extra-offset is not zero:
                ;;                  start              end
                ;; o------------------o---------o-------o
                ;; |<- extra-offset ->|
                ;; |<----------- L ------------>|
                ;;                          new-start
                (list (+ start L (- extra-offset)) end
                      (mapcar (lambda (s) (substring s L)) cands))
              (list end end (mapcar (lambda (s) (substring s Lp)) cands)))
          (list start end cands)))
       ;; python-shell-completion(-native)-get-completions may produce a
       ;; list of (text start end type signature) for completion.
       ((consp (car cands))
        (list (+ start (nth 1 (car cands)) (- extra-offset))
              ;; Candidates may be cached, so the end position should
              ;; be adjusted according to current completion prefix.
              (+ start (nth 2 (car cands)) (- extra-offset) prefix-offset)
              cands
              :annotation-function
              (lambda (c) (concat " " (nth 3 (assoc c cands))))
              :company-docsig
              (lambda (c) (nth 4 (assoc c cands)))))))))