Skip to content

Instantly share code, notes, and snippets.

@dwcoates
Last active December 15, 2017 01:01
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dwcoates/22fa46b33bf1029fc60e1e9bb9e76338 to your computer and use it in GitHub Desktop.
Save dwcoates/22fa46b33bf1029fc60e1e9bb9e76338 to your computer and use it in GitHub Desktop.
Convenient function for sending python code to shell
(defvar python-shell-send-code-step-on-function nil
"If non-nil, step sending a function to the python interpreter.")
(defun python-shell-step-after-defun ()
(forward-paragraph)
;; when at last paragraph, don't step to beginning of "next" paragraph
(unless (equal (line-number-at-pos (point))
(progn (forward-paragraph) (line-number-at-pos (point))))
(backward-paragraph)
(forward-line 1)))
(defun python-shell-send-paragraph-and-step ()
"Send current paragraph of code and move point to the beginning of next paragraph."
(interactive)
(save-excursion
(let* ((beg (progn (forward-paragraph)
(backward-paragraph)
(unless (equal (line-number-at-pos) 1)
(forward-line)) (point)))
(end (progn (forward-paragraph)
(unless (equal (line-number-at-pos (point))
(line-number-at-pos (point-max)))
(forward-line -1))
(end-of-line)
(point)))
(num-lines (1+ (- (line-number-at-pos end)
(line-number-at-pos beg)))))
(python-shell-send-region beg end)
(message (concat
(format "Sent %d line%s "
num-lines
(if (equal num-lines 1) "" "s"))
(if (equal num-lines 1)
(format "(line %d)" (line-number-at-pos end))
(format "(lines %d-%d)"
(line-number-at-pos beg)
(line-number-at-pos end)))
" to Python interpreter")
(line-number-at-pos beg)
(line-number-at-pos end))))
(python-shell-step-after-defun))
(defun python-current-defun ()
"`python-info-current-defun' doesn't work when on a blank line, for some reason."
(interactive)
(save-excursion (forward-paragraph)
(backward-paragraph)
(forward-line)
(python-info-current-defun)))
(defun python-shell-send-code-and-step ()
(interactive)
;; xemacs doesn't have use-region-p
(unless (python-shell-get-process)
(run-python))
(cond ((use-region-p)
(let ((end (region-end))
(beg (region-beginning)))
(python-shell-send-region beg end)
(message "Sent region between lines %d and %d to python interpreter"
(line-number-at-pos beg)
(line-number-at-pos end))
(goto-char end)))
;; send function if in a function, else send block and iterate
((python-current-defun)
(progn
(python-shell-send-defun)
(message "Sent '%s' function to python interpreter"
(propertize (python-current-defun) 'face
'(:foreground "#66D9EF")))
(when python-shell-send-code-step-on-function
(python-nav-end-of-defun)
(forward-line -1)
(python-shell-step-after-defun))))
(t
(python-shell-send-paragraph-and-step))))
@rsuhada
Copy link

rsuhada commented Apr 3, 2017

Thanks this is so much needed!

Unfortunately I have some troubles with it...

  1. when region is selected: works great, except the mark is not cleared after eval so region selection is active
  2. without region: it seems to have problem to parse out blocks

for letter in "banana":
print letter

gives an indentation error (it evals only the first line)

index = 0
fruit = "banana"
while index < len(fruit):
print index, fruit[index]
index += 1

Yields an infinite loop - it doesn't send the last line.
I've tried blocks (paragraphs) separated by single and double empty line, without success. No empty lines within a paragraph.

Is it possible that it sends one line less then it should?

Thanks!

@dwcoates
Copy link
Author

Sorry, I totally missed this comment! This is a pretty simple script for my own purposes, and as such relies on existing facilities for parsing python code. There are a number of problems with it, such as its inability to recognize scope -- e.g., it will often misinterpret part of a function as a stand-alone block of code. There are some more precise alternatives, check this out: https://github.com/wavexx/python-x.el

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment