]> git.eshelyaron.com Git - emacs.git/commitdiff
Implemented Skeletons after GNU/Emacs python.el
authorFabián Ezequiel Gallina <fgallina@cuca>
Thu, 17 May 2012 03:03:05 +0000 (00:03 -0300)
committerFabián Ezequiel Gallina <fgallina@gnu.org>
Thu, 17 May 2012 03:03:05 +0000 (00:03 -0300)
6 basic skeletons are defined: class, def, for, if, try and while.

While these skeletons are strongly based on GNU/Emacs' current
python.el a better definition macro, a generic template for
try/except/finally/else blocks and a cool menu display is included.

lisp/progmodes/python.el

index 49b351cc17cd1dbfa5924f2ffe5f97c82702c6f6..fa00faf150247c87c6b7ec70ce353bc3f3cb504c 100644 (file)
 ;; the shell completion in background so you should run
 ;; `python-shell-send-buffer' from time to time to get better results.
 
+;; Skeletons: 6 skeletons are provided for simple inserting of class,
+;; def, for, if, try and while.  These skeletons are integrated with
+;; dabbrev.  If you have `dabbrev-mode' activated and
+;; `python-skeleton-autoinsert' is set to t, then whenever you type
+;; the name of any of those defined and hit SPC, they will be
+;; automatically expanded.
+
 ;; FFAP: You can find the filename for a given module when using ffap
 ;; out of the box.  This feature needs an inferior python shell
 ;; running.
 
 ;; Review code and cleanup
 
-;; (Perhaps) some skeletons (I never use them because of yasnippet)
-
 ;;; Code:
 
 (require 'comint)
     (define-key map "\C-c<" 'python-indent-shift-left)
     (define-key map "\C-c>" 'python-indent-shift-right)
     (define-key map ":" 'python-indent-electric-colon)
+    ;; Skeletons
+    (define-key map "\C-c\C-tc" 'python-skeleton-class)
+    (define-key map "\C-c\C-td" 'python-skeleton-def)
+    (define-key map "\C-c\C-tf" 'python-skeleton-for)
+    (define-key map "\C-c\C-ti" 'python-skeleton-if)
+    (define-key map "\C-c\C-tt" 'python-skeleton-try)
+    (define-key map "\C-c\C-tw" 'python-skeleton-while)
     ;; Shell interaction
     (define-key map "\C-c\C-s" 'python-shell-send-string)
     (define-key map "\C-c\C-r" 'python-shell-send-region)
        ["End of def/class" end-of-defun
         :help "Go to end of definition around point"]
         "-"
+       ("Skeletons")
+        "-"
        ["Start interpreter" run-python
         :help "Run inferior Python process in a separate buffer"]
        ["Switch to shell" python-shell-switch-to-shell
@@ -1491,6 +1505,138 @@ Optional argument JUSTIFY defines if the paragraph should be justified."
      (t t))))
 
 \f
+;;; Skeletons
+
+(defcustom python-skeleton-autoinsert nil
+  "Non-nil means template skeletons will be automagically inserted.
+This happens when pressing \"if<SPACE>\", for example, to prompt for
+the if condition."
+  :type 'boolean
+  :group 'python)
+
+(defvar python-skeleton-available '()
+  "Internal list of available skeletons.")
+(make-variable-buffer-local 'inferior-python-mode-current-file)
+
+(define-abbrev-table 'python-mode-abbrev-table ()
+  "Abbrev table for Python mode."
+  :case-fixed t
+  ;; Allow / inside abbrevs.
+  :regexp "\\(?:^\\|[^/]\\)\\<\\([[:word:]/]+\\)\\W*"
+  ;; Only expand in code.
+  :enable-function (lambda ()
+                     (message "ppss %s" (not (nth 8 (syntax-ppss))))
+                     (message "autoinsert %s" python-skeleton-autoinsert)
+                     (and
+                      (not (nth 8 (syntax-ppss)))
+                      python-skeleton-autoinsert)))
+
+(defmacro python-skeleton-define (name doc &rest skel)
+  "Define a `python-mode' skeleton using NAME DOC and SKEL.
+The skeleton will be bound to python-skeleton-NAME and will
+be added to `python-mode-abbrev-table'."
+  (let* ((name (symbol-name name))
+        (function-name (intern (concat "python-skeleton-" name))))
+    (define-abbrev python-mode-abbrev-table name "" function-name)
+    (setq python-skeleton-available
+          (cons function-name python-skeleton-available))
+    `(define-skeleton ,function-name
+       ,(or doc
+            (format "Insert %s statement." name))
+       ,@skel)))
+
+(put 'python-skeleton-define 'lisp-indent-function 2)
+
+(defmacro python-define-auxiliary-skeleton (name doc &optional &rest skel)
+  "Define a `python-mode' auxiliary skeleton using NAME DOC and SKEL.
+The skeleton will be bound to python-skeleton-NAME."
+  (let* ((name (symbol-name name))
+        (function-name (intern (concat "python-skeleton--" name)))
+         (msg (format
+               "Add '%s' clause? " name)))
+    (when (not skel)
+      (setq skel
+            `(< ,(format "%s:" name) \n \n
+                > _ \n)))
+    `(define-skeleton ,function-name
+       ,(or doc
+            (format "Auxiliary skeleton for %s statement." name))
+       nil
+       (unless (y-or-n-p ,msg)
+         (signal 'quit t))
+       ,@skel)))
+(put 'python-define-auxiliary-skeleton 'lisp-indent-function 2)
+
+(python-define-auxiliary-skeleton else nil)
+
+(python-define-auxiliary-skeleton except nil)
+
+(python-define-auxiliary-skeleton finally nil)
+
+(python-skeleton-define if nil
+  "Condition: "
+  "if " str ":" \n
+  _ \n
+  ("other condition, %s: "
+   <
+   "elif " str ":" \n
+   > _ \n nil)
+  '(python-skeleton--else) | ^)
+
+(python-skeleton-define while nil
+  "Condition: "
+  "while " str ":" \n
+  > _ \n
+  '(python-skeleton--else) | ^)
+
+(python-skeleton-define for nil
+  "Iteration spec: "
+  "for " str ":" \n
+  > _ \n
+  '(python-skeleton--else) | ^)
+
+(python-skeleton-define try nil
+  nil
+  "try:" \n
+  > _ \n
+  ("Exception, %s: "
+   <
+   "except " str ":" \n
+   > _ \n nil)
+  resume:
+  '(python-skeleton--except)
+  '(python-skeleton--else)
+  '(python-skeleton--finally) | ^)
+
+(python-skeleton-define def nil
+  "Function name: "
+  "def " str " ("  ("Parameter, %s: "
+                    (unless (equal ?\( (char-before)) ", ")
+                    str) "):" \n
+  "\"\"\"" - "\"\"\"" \n
+  > _ \n)
+
+(python-skeleton-define class nil
+  "Class name: "
+  "class " str " (" ("Inheritance, %s: "
+                    (unless (equal ?\( (char-before)) ", ")
+                    str)
+  & ")" | -2
+  ":" \n
+  "\"\"\"" - "\"\"\"" \n
+  > _ \n)
+
+(defun python-skeleton-add-menu-items ()
+  "Add menu items to Python->Skeletons menu."
+  (let ((skeletons (sort python-skeleton-available 'string<))
+        (items))
+    (dolist (skeleton skeletons)
+      (easy-menu-add-item
+       nil '("Python" "Skeletons")
+       `[,(format
+           "Insert %s" (caddr (split-string (symbol-name skeleton) "-")))
+         ,skeleton t]))))
+\f
 ;;; FFAP
 
 (defvar python-ffap-setup-code
@@ -1822,6 +1968,12 @@ not inside a defun."
   (set (make-local-variable 'add-log-current-defun-function)
        #'python-info-current-defun)
 
+  (set (make-local-variable 'skeleton-further-elements)
+       '((abbrev-mode nil)
+         (< '(backward-delete-char-untabify (min python-indent-offset
+                                                (current-column))))
+        (^ '(- (1+ (current-indentation))))))
+
   (set (make-local-variable 'eldoc-documentation-function)
        #'python-eldoc-function)
 
@@ -1838,6 +1990,8 @@ not inside a defun."
            "`outline-level' function for Python mode."
            (1+ (/ (current-indentation) python-indent-offset))))
 
+  (python-skeleton-add-menu-items)
+
   (when python-indent-guess-indent-offset
     (python-indent-guess-indent-offset)))