From 3acd6262d993cb445a3656808ce544cf68754f89 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Fabi=C3=A1n=20Ezequiel=20Gallina?= Date: Tue, 1 Jul 2014 00:54:11 -0300 Subject: [PATCH] * lisp/progmodes/python.el (python-indent-post-self-insert-function): Enhancements to electric indentation behavior inside parens. * test/automated/python-tests.el (python-tests-self-insert): New function. (python-triple-quote-pairing): Use it. (python-util-forward-comment-1): New test. (Bug#17658) --- lisp/ChangeLog | 6 +++ lisp/progmodes/python.el | 28 +++++++--- test/ChangeLog | 7 +++ test/automated/python-tests.el | 114 ++++++++++++++++++++++++++++++++--------- 4 files changed, 122 insertions(+), 33 deletions(-) diff --git a/lisp/ChangeLog b/lisp/ChangeLog index c01480ef857..4d186b585dd 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,9 @@ +2014-07-01 Fabián Ezequiel Gallina + + * progmodes/python.el (python-indent-post-self-insert-function): + Enhancements to electric indentation behavior inside + parens. (Bug#17658) + 2014-07-01 Stefan Monnier * ps-def.el (ps-generate-postscript-with-faces1): Don't mess with diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index f99a580b376..2301db8ecf6 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el @@ -1097,16 +1097,28 @@ the line will be re-indented automatically if needed." (when (and electric-indent-mode (eq (char-before) last-command-event)) (cond - ((and (not (bolp)) - (memq (char-after) '(?\) ?\] ?\}))) + ;; Electric indent inside parens + ((and + (not (bolp)) + (let ((paren-start (python-syntax-context 'paren))) + ;; Check that point is inside parens. + (when paren-start + (not + ;; Filter the case where input is happening in the same + ;; line where the open paren is. + (= (line-number-at-pos) + (line-number-at-pos paren-start))))) + ;; When content has been added before the closing paren or a + ;; comma has been inserted, it's ok to do the trick. + (or + (memq (char-after) '(?\) ?\] ?\})) + (eq (char-before) ?,))) (save-excursion (goto-char (line-beginning-position)) - ;; If after going to the beginning of line the point - ;; is still inside a paren it's ok to do the trick - (when (python-syntax-context 'paren) - (let ((indentation (python-indent-calculate-indentation))) - (when (< (current-indentation) indentation) - (indent-line-to indentation)))))) + (let ((indentation (python-indent-calculate-indentation))) + (when (< (current-indentation) indentation) + (indent-line-to indentation))))) + ;; Electric colon ((and (eq ?: last-command-event) (memq ?: electric-indent-chars) (not current-prefix-arg) diff --git a/test/ChangeLog b/test/ChangeLog index dea6f4a9264..f93b553f341 100644 --- a/test/ChangeLog +++ b/test/ChangeLog @@ -1,3 +1,10 @@ +2014-07-01 Fabián Ezequiel Gallina + + * automated/python-tests.el + (python-tests-self-insert): New function. + (python-triple-quote-pairing): Use it. + (python-util-forward-comment-1): New test. (Bug#17658) + 2014-06-28 Leo Liu * automated/calc-tests.el: New file and add tests for math-bignum. diff --git a/test/automated/python-tests.el b/test/automated/python-tests.el index f580e946b8f..a35242fe882 100644 --- a/test/automated/python-tests.el +++ b/test/automated/python-tests.el @@ -86,6 +86,24 @@ STRING, it is skipped so the next STRING occurrence is selected." found-point (and restore-point (goto-char starting-point))))) +(defun python-tests-self-insert (char-or-str) + "Call `self-insert-command' for chars in CHAR-OR-STR." + (let ((chars + (cond + ((characterp char-or-str) + (list char-or-str)) + ((stringp char-or-str) + (string-to-list char-or-str)) + ((not + (cl-remove-if #'characterp char-or-str)) + char-or-str) + (t (error "CHAR-OR-STR must be a char, string, or list of char"))))) + (mapc + (lambda (char) + (let ((last-command-event char)) + (call-interactively 'self-insert-command))) + chars))) + ;;; Tests for your tests, so you can test while you test. @@ -2715,9 +2733,6 @@ def foo(a, b, c): (should (string= (python-util-strip-string "\n \t \n\r ") "")) (should (string= (python-util-strip-string "") ""))) - -;;; Electricity - (ert-deftest python-util-forward-comment-1 () (python-tests-with-temp-buffer (concat @@ -2730,36 +2745,85 @@ def foo(a, b, c): (python-util-forward-comment -1) (should (= (point) (point-min))))) + +;;; Electricity + +(ert-deftest python-parens-electric-indent-1 () + (require 'electric) + (let ((eim electric-indent-mode)) + (unwind-protect + (progn + (python-tests-with-temp-buffer + " +from django.conf.urls import patterns, include, url + +from django.contrib import admin + +from myapp import views + + +urlpatterns = patterns('', + url(r'^$', views.index +) +" + (electric-indent-mode 1) + (python-tests-look-at "views.index") + (end-of-line) + + ;; Inserting commas within the same line should leave + ;; indentation unchanged. + (python-tests-self-insert ",") + (should (= (current-indentation) 4)) + + ;; As well as any other input happening within the same + ;; set of parens. + (python-tests-self-insert " name='index')") + (should (= (current-indentation) 4)) + + ;; But a comma outside it, should trigger indentation. + (python-tests-self-insert ",") + (should (= (current-indentation) 23)) + + ;; Newline indents to the first argument column + (python-tests-self-insert "\n") + (should (= (current-indentation) 23)) + + ;; All this input must not change indentation + (indent-line-to 4) + (python-tests-self-insert "url(r'^/login$', views.login)") + (should (= (current-indentation) 4)) + + ;; But this comma does + (python-tests-self-insert ",") + (should (= (current-indentation) 23)))) + (or eim (electric-indent-mode -1))))) + (ert-deftest python-triple-quote-pairing () (require 'electric) (let ((epm electric-pair-mode)) (unwind-protect (progn (python-tests-with-temp-buffer - "\"\"\n" - (or epm (electric-pair-mode 1)) - (goto-char (1- (point-max))) - (let ((last-command-event ?\")) - (call-interactively 'self-insert-command)) - (should (string= (buffer-string) - "\"\"\"\"\"\"\n")) - (should (= (point) 4))) + "\"\"\n" + (or epm (electric-pair-mode 1)) + (goto-char (1- (point-max))) + (python-tests-self-insert ?\") + (should (string= (buffer-string) + "\"\"\"\"\"\"\n")) + (should (= (point) 4))) (python-tests-with-temp-buffer - "\n" - (let ((last-command-event ?\")) - (dotimes (i 3) - (call-interactively 'self-insert-command))) - (should (string= (buffer-string) - "\"\"\"\"\"\"\n")) - (should (= (point) 4))) + "\n" + (python-tests-self-insert (list ?\" ?\" ?\")) + (should (string= (buffer-string) + "\"\"\"\"\"\"\n")) + (should (= (point) 4))) (python-tests-with-temp-buffer - "\"\n\"\"\n" - (goto-char (1- (point-max))) - (let ((last-command-event ?\")) - (call-interactively 'self-insert-command)) - (should (= (point) (1- (point-max)))) - (should (string= (buffer-string) - "\"\n\"\"\"\n")))) + "\"\n\"\"\n" + (goto-char (1- (point-max))) + (python-tests-self-insert ?\") + (should (= (point) (1- (point-max)))) + (should (string= (buffer-string) + "\"\n\"\"\"\n")))) (or epm (electric-pair-mode -1))))) -- 2.11.4.GIT