From: Fabián Ezequiel Gallina Date: Thu, 17 May 2012 03:03:05 +0000 (-0300) Subject: Implemented Skeletons after GNU/Emacs python.el X-Git-Tag: emacs-24.2.90~1199^2~594 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=e2803784cfbd622a60874f3a1d20a0e0decd7161;p=emacs.git Implemented Skeletons after GNU/Emacs python.el 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. --- diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index 49b351cc17c..fa00faf1502 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el @@ -68,6 +68,13 @@ ;; 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. @@ -110,8 +117,6 @@ ;; Review code and cleanup -;; (Perhaps) some skeletons (I never use them because of yasnippet) - ;;; Code: (require 'comint) @@ -145,6 +150,13 @@ (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) @@ -176,6 +188,8 @@ ["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)))) +;;; Skeletons + +(defcustom python-skeleton-autoinsert nil + "Non-nil means template skeletons will be automagically inserted. +This happens when pressing \"if\", 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])))) + ;;; 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)))