Skip to content

Instantly share code, notes, and snippets.

@kragen
Created December 5, 2013 16:48
Show Gist options
  • Save kragen/7808958 to your computer and use it in GitHub Desktop.
Save kragen/7808958 to your computer and use it in GitHub Desktop.
;; This pretty much works. A couple of remaining quibbles:
;;
;; - it’s possible for the region to not include a single Python
;; expression, in which case the code transformation will be
;; invalid.
;; - it should error out if called interactively when
;; transient-mark-mode is active and the mark is inactive, but it
;; doesn’t, because I don't know how to do that.
;; - it would be nice to highlight the other occurrences of the
;; expression, if any, and provide a key (maybe the same key?) to
;; replace them too, since most commonly you extract a local
;; variable when the same expression occurs more than once. Maybe
;; using overlays? How does highlight-regexp from hi-lock work?
;; - Inside a lambda or other binding construct (like a genex), it can
;; make invalid transformations.
(defun py-extract-variable (start end)
"Simple extract-variable refactoring for Python.
The idea is that you set the region to the expression to
extract (probably with \\[mark-sexp], whose more usual convenient
keybinding is C-M-SPC) and put the variable name before it. So
to turn something into a variable \"foo\", you go before it, type
\"foo\", \\[mark-sexp] a few times, and then
\\[py-extract-variable].
"
(interactive "r")
(save-excursion
(let ((expression (buffer-substring start end)))
(delete-region start end)
(goto-char start)
(delete-horizontal-space) ; in case there was whitespace
(let ((variable-end (point)))
(backward-sexp) ; find the beginning of the variable
(let ((variable (buffer-substring (point) variable-end)))
(python-previous-statement 0)
;; I can’t get (indent-region) and (indent-for-tab-command)
;; to work properly, so I’ll just brute-force inserting the
;; same indent.
(let ((end-of-indent (point)))
(move-beginning-of-line 1)
(let ((indent (buffer-substring (point) end-of-indent)))
(open-line 1)
(insert indent)
(insert variable)
(insert " = ")
(insert expression))))))))
(require 'python)
(define-key python-mode-map [f6] 'py-extract-variable)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment