emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] master 2d467a0: Fix hideshow integration.


From: Fabián Ezequiel Gallina
Subject: [Emacs-diffs] master 2d467a0: Fix hideshow integration.
Date: Sat, 07 Feb 2015 19:43:58 +0000

branch: master
commit 2d467a0ff0cd446ec0d83044a0be819cbf874cdf
Author: Fabián Ezequiel Gallina <address@hidden>
Commit: Fabián Ezequiel Gallina <address@hidden>

    Fix hideshow integration.
    
    Fixes: debbugs:19761
    
    * lisp/progmodes/python.el
    (python-hideshow-forward-sexp-function): New function based on
    Carlos Pita <address@hidden> patch.
    (python-mode): Make `hs-special-modes-alist` use it and initialize
    the end regexp with the empty string to avoid skipping parens.
    
    * test/automated/python-tests.el
    (python-tests-visible-string): New function.
    (python-parens-electric-indent-1)
    (python-triple-quote-pairing): Fix indentation, move require calls.
    (python-hideshow-hide-levels-1)
    (python-hideshow-hide-levels-2): New tests.
---
 lisp/ChangeLog                 |   10 ++
 lisp/progmodes/python.el       |   26 ++++-
 test/ChangeLog                 |    9 ++
 test/automated/python-tests.el |  198 +++++++++++++++++++++++++++++++---------
 4 files changed, 193 insertions(+), 50 deletions(-)

diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index a02f964..655ae57 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,5 +1,15 @@
 2015-02-07  Fabián Ezequiel Gallina  <address@hidden>
 
+       Fix hideshow integration.  (Bug#19761)
+
+       * progmodes/python.el
+       (python-hideshow-forward-sexp-function): New function based on
+       Carlos Pita <address@hidden> patch.
+       (python-mode): Make `hs-special-modes-alist` use it and initialize
+       the end regexp with the empty string to avoid skipping parens.
+
+2015-02-07  Fabián Ezequiel Gallina  <address@hidden>
+
        * progmodes/python.el (python-check-custom-command): Do not use
        defvar-local for compat with Emacs<24.3.
 
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index de25118..3399429 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -3958,6 +3958,17 @@ Interactively, prompt for symbol."
   (message (python-eldoc--get-doc-at-point symbol)))
 
 
+;;; Hideshow
+
+(defun python-hideshow-forward-sexp-function (arg)
+  "Python specific `forward-sexp' function for `hs-minor-mode'.
+Argument ARG is ignored."
+  arg  ; Shut up, byte compiler.
+  (python-nav-end-of-defun)
+  (unless (python-info-current-line-empty-p)
+    (backward-char)))
+
+
 ;;; Imenu
 
 (defvar python-imenu-format-item-label-function
@@ -4693,11 +4704,16 @@ Arguments START and END narrow the buffer region to 
work on."
     (add-function :before-until (local 'eldoc-documentation-function)
                   #'python-eldoc-function))
 
-  (add-to-list 'hs-special-modes-alist
-               `(python-mode "^\\s-*\\(?:def\\|class\\)\\>" nil "#"
-                             ,(lambda (_arg)
-                                (python-nav-end-of-defun))
-                             nil))
+  (add-to-list
+   'hs-special-modes-alist
+   `(python-mode
+     "\\s-*\\(?:def\\|class\\)\\>"
+     ;; Use the empty string as end regexp so it doesn't default to
+     ;; "\\s)".  This way parens at end of defun are properly hidden.
+     ""
+     "#"
+     python-hideshow-forward-sexp-function
+     nil))
 
   (set (make-local-variable 'outline-regexp)
        (python-rx (* space) block-start))
diff --git a/test/ChangeLog b/test/ChangeLog
index e0d4eeb..b1e2151 100644
--- a/test/ChangeLog
+++ b/test/ChangeLog
@@ -1,3 +1,12 @@
+2015-02-07  Fabián Ezequiel Gallina  <address@hidden>
+
+       * automated/python-tests.el
+       (python-tests-visible-string): New function.
+       (python-parens-electric-indent-1)
+       (python-triple-quote-pairing): Fix indentation, move require calls.
+       (python-hideshow-hide-levels-1)
+       (python-hideshow-hide-levels-2): New tests.
+
 2015-02-07  Dmitry Gutov  <address@hidden>
 
        * automated/vc-tests.el (vc-test--working-revision): Fix
diff --git a/test/automated/python-tests.el b/test/automated/python-tests.el
index 672b05c..e5fcda9 100644
--- a/test/automated/python-tests.el
+++ b/test/automated/python-tests.el
@@ -24,6 +24,11 @@
 (require 'ert)
 (require 'python)
 
+;; Dependencies for testing:
+(require 'electric)
+(require 'hideshow)
+
+
 (defmacro python-tests-with-temp-buffer (contents &rest body)
   "Create a `python-mode' enabled temp buffer with CONTENTS.
 BODY is code to be executed within the temp buffer.  Point is
@@ -104,6 +109,28 @@ STRING, it is skipped so the next STRING occurrence is 
selected."
          (call-interactively 'self-insert-command)))
      chars)))
 
+(defun python-tests-visible-string (&optional min max)
+  "Return the buffer string excluding invisible overlays.
+Argument MIN and MAX delimit the region to be returned and
+default to `point-min' and `point-max' respectively."
+  (let* ((min (or min (point-min)))
+         (max (or max (point-max)))
+         (buffer (current-buffer))
+         (buffer-contents (buffer-substring-no-properties min max))
+         (overlays
+          (sort (overlays-in min max)
+                (lambda (a b)
+                  (let ((overlay-end-a (overlay-end a))
+                        (overlay-end-b (overlay-end b)))
+                    (> overlay-end-a overlay-end-b))))))
+    (with-temp-buffer
+      (insert buffer-contents)
+      (dolist (overlay overlays)
+        (if (overlay-get overlay 'invisible)
+            (delete-region (overlay-start overlay)
+                           (overlay-end overlay))))
+      (buffer-substring-no-properties (point-min) (point-max)))))
+
 
 ;;; Tests for your tests, so you can test while you test.
 
@@ -4358,12 +4385,11 @@ def foo(a, b, c):
 ;;; 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
@@ -4375,66 +4401,148 @@ urlpatterns = patterns('',
     url(r'^$', views.index
 )
 "
-            (electric-indent-mode 1)
-            (python-tests-look-at "views.index")
-            (end-of-line)
+           (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))
+           ;; 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))
+           ;; 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))
+           ;; 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))
+           ;; 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))
+           ;; 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))))
+           ;; 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)))
-            (python-tests-self-insert ?\")
-            (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"
-            (python-tests-self-insert (list ?\" ?\" ?\"))
-            (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)))
-            (python-tests-self-insert ?\")
-            (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)))))
 
+
+;;; Hideshow support
+
+(ert-deftest python-hideshow-hide-levels-1 ()
+  "Should hide all methods when called after class start."
+  (let ((enabled hs-minor-mode))
+    (unwind-protect
+        (progn
+          (python-tests-with-temp-buffer
+           "
+class SomeClass:
+
+    def __init__(self, arg, kwarg=1):
+        self.arg = arg
+        self.kwarg = kwarg
+
+    def filter(self, nums):
+        def fn(item):
+            return item in [self.arg, self.kwarg]
+        return filter(fn, nums)
+
+    def __str__(self):
+        return '%s-%s' % (self.arg, self.kwarg)
+"
+           (hs-minor-mode 1)
+           (python-tests-look-at "class SomeClass:")
+           (forward-line)
+           (hs-hide-level 1)
+           (should
+            (string=
+             (python-tests-visible-string)
+             "
+class SomeClass:
+
+    def __init__(self, arg, kwarg=1):
+    def filter(self, nums):
+    def __str__(self):"))))
+      (or enabled (hs-minor-mode -1)))))
+
+(ert-deftest python-hideshow-hide-levels-2 ()
+  "Should hide nested methods and parens at end of defun."
+  (let ((enabled hs-minor-mode))
+    (unwind-protect
+        (progn
+          (python-tests-with-temp-buffer
+           "
+class SomeClass:
+
+    def __init__(self, arg, kwarg=1):
+        self.arg = arg
+        self.kwarg = kwarg
+
+    def filter(self, nums):
+        def fn(item):
+            return item in [self.arg, self.kwarg]
+        return filter(fn, nums)
+
+    def __str__(self):
+        return '%s-%s' % (self.arg, self.kwarg)
+"
+           (hs-minor-mode 1)
+           (python-tests-look-at "def fn(item):")
+           (hs-hide-block)
+           (should
+            (string=
+             (python-tests-visible-string)
+             "
+class SomeClass:
+
+    def __init__(self, arg, kwarg=1):
+        self.arg = arg
+        self.kwarg = kwarg
+
+    def filter(self, nums):
+        def fn(item):
+        return filter(fn, nums)
+
+    def __str__(self):
+        return '%s-%s' % (self.arg, self.kwarg)
+"))))
+      (or enabled (hs-minor-mode -1)))))
+
+
 
 (provide 'python-tests)
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]