Function: python-shell-buffer-substring

python-shell-buffer-substring is a byte-compiled function defined in python.el.gz.

Signature

(python-shell-buffer-substring START END &optional NOMAIN NO-COOKIE)

Documentation

Send buffer substring from START to END formatted for shell.

This is a wrapper over buffer-substring that takes care of different transformations for the code sent to be evaluated in the python shell:
  1. When optional argument NOMAIN is non-nil everything under an
     "if __name__ == \\='__main__\\='" block will be removed.
  2. When a subregion of the buffer is sent, it takes care of
     appending extra empty lines so tracebacks are correct.
  3. When the region sent is a substring of the current buffer, a
     coding cookie is added.
  4. When the region consists of a single statement, leading
     whitespaces will be removed. Otherwise, wraps indented
     regions under an "if True:" block so the interpreter
     evaluates them correctly.

Source Code

;; Defined in /usr/src/emacs/lisp/progmodes/python.el.gz
(defun python-shell-buffer-substring (start end &optional nomain no-cookie)
  "Send buffer substring from START to END formatted for shell.
This is a wrapper over `buffer-substring' that takes care of
different transformations for the code sent to be evaluated in
the python shell:
  1. When optional argument NOMAIN is non-nil everything under an
     \"if __name__ == \\='__main__\\='\" block will be removed.
  2. When a subregion of the buffer is sent, it takes care of
     appending extra empty lines so tracebacks are correct.
  3. When the region sent is a substring of the current buffer, a
     coding cookie is added.
  4. When the region consists of a single statement, leading
     whitespaces will be removed.  Otherwise, wraps indented
     regions under an \"if True:\" block so the interpreter
     evaluates them correctly."
  (let* ((single-p (save-excursion
                     (save-restriction
                       (narrow-to-region start end)
                       (= (progn
                            (goto-char start)
                            (python-nav-beginning-of-statement))
                          (progn
                            (goto-char end)
                            (python-nav-beginning-of-statement))))))
         (start (save-excursion
                  ;; If we're at the start of the expression, and if
                  ;; the region consists of a single statement, then
                  ;; remove leading whitespaces, else if there's just
                  ;; blank space ahead of it, then expand the region
                  ;; to include the start of the line.  This makes
                  ;; things work better with the rest of the data
                  ;; we're sending over.
                  (goto-char start)
                  (if single-p
                      (progn
                        (skip-chars-forward "[:space:]" end)
                        (point))
                    (if (string-blank-p
                         (buffer-substring (line-beginning-position) start))
                        (line-beginning-position)
                      start))))
         (substring (buffer-substring-no-properties start end))
         (starts-at-first-line-p (save-excursion
                                   (save-restriction
                                     (widen)
                                     (goto-char start)
                                     (= (line-number-at-pos) 1))))
         (encoding (python-info-encoding))
         (toplevel-p (zerop (save-excursion
                              (goto-char start)
                              (python-util-forward-comment 1)
                              (current-indentation))))
         (fillstr (cond (starts-at-first-line-p
                         nil)
                        ((not no-cookie)
                         (concat
                          (format "# -*- coding: %s -*-\n" encoding)
                          (make-string
                           ;; Subtract 2 because of the coding cookie.
                           (- (line-number-at-pos start) 2) ?\n)))
                        (t
                         (make-string (- (line-number-at-pos start) 1) ?\n)))))
    (with-temp-buffer
      (python-mode)
      (when fillstr
        (insert fillstr))
      (when (and (not single-p) (not toplevel-p))
        (forward-line -1)
        (insert "if True:\n")
        (delete-region (point) (line-end-position)))
      (insert substring)
      (when nomain
        (let* ((if-name-main-start-end
                (and nomain
                     (save-excursion
                       (when (python-nav-if-name-main)
                         (cons (point)
                               (progn (python-nav-forward-sexp-safe)
                                      ;; Include ending newline
                                      (forward-line 1)
                                      (point)))))))
               ;; Oh destructuring bind, how I miss you.
               (if-name-main-start (car if-name-main-start-end))
               (if-name-main-end (cdr if-name-main-start-end))
               (fillstr (make-string
                         (- (line-number-at-pos if-name-main-end)
                            (line-number-at-pos if-name-main-start)) ?\n)))
          (when if-name-main-start-end
            (goto-char if-name-main-start)
            (delete-region if-name-main-start if-name-main-end)
            (insert fillstr))))
      ;; Ensure there's only one coding cookie in the generated string.
      (goto-char (point-min))
      (when (looking-at-p (python-rx coding-cookie))
        (forward-line 1)
        (when (looking-at-p (python-rx coding-cookie))
          (delete-region
           (line-beginning-position) (line-end-position))))
      (buffer-substring-no-properties (point-min) (point-max)))))