(py-backspace-function): New variable.

(py-electric-backspace, py-electric-delete): Support the XEmacs 20 Way
for backspace and delete mappings.  In XEmacs 19, Emacs 19, and Emacs
20, both backspace and delete keysyms are bound to
py-electric-backspace.  In XEmacs 20, backspace and delete keysyms are
bound separately, allowing the user to specify forward or backward
deletion of the delete keysym through the variable
delete-key-deletes-forward.  All this is the Right Way To Do It and
this implementation was largely ripped from CC Mode.
This commit is contained in:
Barry Warsaw 1997-11-04 19:21:50 +00:00
parent a97a3f34d6
commit 6d48c4a00b
1 changed files with 102 additions and 61 deletions

View File

@ -216,6 +216,17 @@ the Emacs bell is also rung as a warning."
:type 'boolean :type 'boolean
:group 'python) :group 'python)
(defcustom py-backspace-function 'backward-delete-char-untabify
"*Function called by `py-electric-backspace' when deleting backwards."
:type 'function
:group 'python)
(defcustom py-delete-function 'delete-char
"*Function called by `py-electric-delete' when deleting forwards."
:type 'function
:group 'python)
;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
;; NO USER DEFINABLE VARIABLES BEYOND THIS POINT ;; NO USER DEFINABLE VARIABLES BEYOND THIS POINT
@ -271,12 +282,6 @@ When non-nil, arguments are printed.")
"Queue of Python temp files awaiting execution. "Queue of Python temp files awaiting execution.
Currently-active file is at the head of the list.") Currently-active file is at the head of the list.")
(defvar py-delete-function 'backward-delete-char-untabify
"*Function called by `py-delete-char' when deleting characters.")
(defvar py-backspace-function 'backward-delete-char-untabify
"*Function called by `py-backspace-command' when deleting characters.")
;; Constants ;; Constants
@ -380,7 +385,52 @@ Currently-active file is at the head of the list.")
(if py-mode-map (if py-mode-map
nil nil
(setq py-mode-map (make-sparse-keymap)) (setq py-mode-map (make-sparse-keymap))
;; electric keys
(define-key py-mode-map ":" 'py-electric-colon)
;; indentation level modifiers
(define-key py-mode-map "\C-c\C-l" 'py-shift-region-left)
(define-key py-mode-map "\C-c\C-r" 'py-shift-region-right)
(define-key py-mode-map "\C-c<" 'py-shift-region-left)
(define-key py-mode-map "\C-c>" 'py-shift-region-right)
;; subprocess commands
(define-key py-mode-map "\C-c\C-c" 'py-execute-buffer)
(define-key py-mode-map "\C-c|" 'py-execute-region)
(define-key py-mode-map "\C-c!" 'py-shell)
;; Caution! Enter here at your own risk. We are trying to support
;; several behaviors and it gets disgusting. :-( This logic ripped
;; largely from CC Mode.
;;
;; In XEmacs 19, Emacs 19, and Emacs 20, we use this to bind
;; backwards deletion behavior to DEL, which both Delete and
;; Backspace get translated to. There's no way to separate this
;; behavior in a clean way, so deal with it! Besides, it's been
;; this way since the dawn of time.
(if (not (boundp 'delete-key-deletes-forward))
(define-key py-mode-map "\177" 'py-electric-backspace)
;; However, XEmacs 20 actually achieved enlightenment. It is
;; possible to sanely define both backward and forward deletion
;; behavior under X separately (TTYs are forever beyond hope, but
;; who cares? XEmacs 20 does the right thing with these too).
(define-key py-mode-map [delete] 'py-electric-delete)
(define-key py-mode-map [backspace] 'py-electric-backspace))
;; Miscellaneous
(define-key py-mode-map "\C-c:" 'py-guess-indent-offset)
(define-key py-mode-map "\C-c\t" 'py-indent-region)
(define-key py-mode-map "\C-c\C-n" 'py-next-statement)
(define-key py-mode-map "\C-c\C-p" 'py-previous-statement)
(define-key py-mode-map "\C-c\C-u" 'py-goto-block-up)
(define-key py-mode-map "\C-c\C-m" 'py-mark-block)
(define-key py-mode-map "\C-c#" 'py-comment-region)
(define-key py-mode-map "\C-c?" 'py-describe-mode)
(define-key py-mode-map "\C-c\C-hm" 'py-describe-mode)
(define-key py-mode-map "\e\C-a" 'beginning-of-python-def-or-class)
(define-key py-mode-map "\e\C-e" 'end-of-python-def-or-class)
(define-key py-mode-map "\e\C-h" 'mark-python-def-or-class)
;; information
(define-key py-mode-map "\C-c\C-b" 'py-submit-bug-report)
(define-key py-mode-map "\C-c\C-v" 'py-version)
;; py-newline-and-indent mappings
(define-key py-mode-map "\n" 'py-newline-and-indent)
;; shadow global bindings for newline-and-indent w/ the py- version. ;; shadow global bindings for newline-and-indent w/ the py- version.
;; BAW - this is extremely bad form, but I'm not going to change it ;; BAW - this is extremely bad form, but I'm not going to change it
;; for now. ;; for now.
@ -388,37 +438,6 @@ Currently-active file is at the head of the list.")
(define-key (define-key
py-mode-map key 'py-newline-and-indent))) py-mode-map key 'py-newline-and-indent)))
(where-is-internal 'newline-and-indent)) (where-is-internal 'newline-and-indent))
;; BAW - you could do it this way, but its not considered proper
;; major-mode form.
(mapcar (function
(lambda (x)
(define-key py-mode-map (car x) (cdr x))))
'((":" . py-electric-colon)
("\C-c\C-c" . py-execute-buffer)
("\C-c|" . py-execute-region)
("\C-c!" . py-shell)
("\177" . py-delete-char)
("\n" . py-newline-and-indent)
("\C-c:" . py-guess-indent-offset)
("\C-c\t" . py-indent-region)
("\C-c\C-l" . py-shift-region-left)
("\C-c\C-r" . py-shift-region-right)
("\C-c<" . py-shift-region-left)
("\C-c>" . py-shift-region-right)
("\C-c\C-n" . py-next-statement)
("\C-c\C-p" . py-previous-statement)
("\C-c\C-u" . py-goto-block-up)
("\C-c\C-m" . py-mark-block)
("\C-c#" . py-comment-region)
("\C-c?" . py-describe-mode)
("\C-c\C-hm" . py-describe-mode)
("\e\C-a" . beginning-of-python-def-or-class)
("\e\C-e" . end-of-python-def-or-class)
( "\e\C-h" . mark-python-def-or-class)))
;; should do all keybindings this way
(define-key py-mode-map "\C-c\C-b" 'py-submit-bug-report)
(define-key py-mode-map "\C-c\C-v" 'py-version)
) )
(defvar py-mode-syntax-table nil (defvar py-mode-syntax-table nil
@ -1048,34 +1067,33 @@ See the `\\[py-execute-region]' docs for an account of some subtleties."
(py-execute-region (point-min) (point-max) async)) (py-execute-region (point-min) (point-max) async))
;; Functions for Python style indentation ;; Electric deletion
(defun py-delete-char (count) (defun py-electric-backspace (arg)
"Reduce indentation or delete character. "Deletes preceding character or levels of indentation.
Deletion is performed by calling the function in `py-backspace-function'
If point is at the leftmost column, deletes the preceding newline.
Deletion is performed by calling the function in `py-delete-function'
with a single argument (the number of characters to delete). with a single argument (the number of characters to delete).
Else if point is at the leftmost non-blank character of a line that is If point is at the leftmost column, deletes the preceding newline.
neither a continuation line nor a non-indenting comment line, or if
point is at the end of a blank line, reduces the indentation to match
that of the line that opened the current block of code. The line that
opened the block is displayed in the echo area to help you keep track
of where you are. With numeric count, outdents that many blocks (but
not past column zero).
Else the preceding character is deleted, converting a tab to spaces if Otherwise, if point is at the leftmost non-whitespace character of a
needed so that only a single column position is deleted. Numeric line that is neither a continuation line nor a non-indenting comment
argument delets that many characters." line, or if point is at the end of a blank line, this command reduces
the indentation to match that of the line that opened the current
block of code. The line that opened the block is displayed in the
echo area to help you keep track of where you are. With numeric arg,
outdents that many blocks (but not past column zero).
Otherwise the preceding character is deleted, converting a tab to
spaces if needed so that only a single column position is deleted.
Numeric argument deletes that many preceding characters."
(interactive "*p") (interactive "*p")
(if (or (/= (current-indentation) (current-column)) (if (or (/= (current-indentation) (current-column))
(bolp) (bolp)
(py-continuation-line-p) (py-continuation-line-p)
(not py-honor-comment-indentation) (not py-honor-comment-indentation)
(looking-at "#[^ \t\n]")) ; non-indenting # (looking-at "#[^ \t\n]")) ; non-indenting #
(funcall py-delete-function count) (funcall py-backspace-function arg)
;; else indent the same as the colon line that opened the block ;; else indent the same as the colon line that opened the block
;; force non-blank so py-goto-block-up doesn't ignore it ;; force non-blank so py-goto-block-up doesn't ignore it
(insert-char ?* 1) (insert-char ?* 1)
(backward-char) (backward-char)
@ -1083,7 +1101,7 @@ argument delets that many characters."
(base-text "") ; and text of base line (base-text "") ; and text of base line
(base-found-p nil)) (base-found-p nil))
(save-excursion (save-excursion
(while (< 0 count) (while (< 0 arg)
(condition-case nil ; in case no enclosing block (condition-case nil ; in case no enclosing block
(progn (progn
(py-goto-block-up 'no-mark) (py-goto-block-up 'no-mark)
@ -1091,17 +1109,40 @@ argument delets that many characters."
base-text (py-suck-up-leading-text) base-text (py-suck-up-leading-text)
base-found-p t)) base-found-p t))
(error nil)) (error nil))
(setq count (1- count)))) (setq arg (1- arg))))
(delete-char 1) ; toss the dummy character (delete-char 1) ; toss the dummy character
(delete-horizontal-space) (delete-horizontal-space)
(indent-to base-indent) (indent-to base-indent)
(if base-found-p (if base-found-p
(message "Closes block: %s" base-text))))) (message "Closes block: %s" base-text)))))
;; required for pending-del and delsel modes
(put 'py-delete-char 'delete-selection 'supersede)
(put 'py-delete-char 'pending-delete 'supersede)
(defun py-electric-delete (arg)
"Deletes preceding or following character or levels of whitespace.
The behavior of this function depends on the variable
`delete-key-deletes-forward'. If this variable is nil (or does not
exist, as in older Emacsen), then this function behaves identical to
\\[c-electric-backspace].
If `delete-key-deletes-forward' is non-nil and is supported in your
Emacs, then deletion occurs in the forward direction, by calling the
function in `py-delete-function'."
(interactive "*p")
(if (and (boundp 'delete-key-deletes-forward)
delete-key-deletes-forward)
(funcall py-delete-function arg)
;; else
(py-electric-backspace arg)))
;; required for pending-del and delsel modes
(put 'py-electric-backspace 'delete-selection 'supersede) ;delsel
(put 'py-electric-backspace 'pending-delete 'supersede) ;pending-del
(put 'py-electric-delete 'delete-selection 'supersede) ;delsel
(put 'py-electric-delete 'pending-delete 'supersede) ;pending-del
(defun py-indent-line (&optional arg) (defun py-indent-line (&optional arg)
"Fix the indentation of the current line according to Python rules. "Fix the indentation of the current line according to Python rules.
With \\[universal-argument], ignore outdenting rules for block With \\[universal-argument], ignore outdenting rules for block