aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lisp/progmodes/python.el447
1 files changed, 445 insertions, 2 deletions
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index 39fe096309d..11662c8e46a 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -64,9 +64,10 @@
64 64
65;;; Code: 65;;; Code:
66 66
67(require 'comint)
68
67(eval-when-compile 69(eval-when-compile
68 (require 'compile) 70 (require 'compile)
69 (require 'comint)
70 (require 'hippie-exp)) 71 (require 'hippie-exp))
71 72
72(autoload 'comint-mode "comint") 73(autoload 'comint-mode "comint")
@@ -201,6 +202,7 @@ Used for syntactic keywords. N is the match number (1, 2 or 3)."
201 (define-key map "\C-c<" 'python-shift-left) 202 (define-key map "\C-c<" 'python-shift-left)
202 (define-key map "\C-c>" 'python-shift-right) 203 (define-key map "\C-c>" 'python-shift-right)
203 (define-key map "\C-c\C-k" 'python-mark-block) 204 (define-key map "\C-c\C-k" 'python-mark-block)
205 (define-key map "\C-c\C-d" 'python-pdbtrack-toggle-stack-tracking)
204 (define-key map "\C-c\C-n" 'python-next-statement) 206 (define-key map "\C-c\C-n" 'python-next-statement)
205 (define-key map "\C-c\C-p" 'python-previous-statement) 207 (define-key map "\C-c\C-p" 'python-previous-statement)
206 (define-key map "\C-c\C-u" 'python-beginning-of-block) 208 (define-key map "\C-c\C-u" 'python-beginning-of-block)
@@ -248,7 +250,7 @@ Used for syntactic keywords. N is the match number (1, 2 or 3)."
248 (vector (car elt) (cdr elt) t)) 250 (vector (car elt) (cdr elt) t))
249 python-skeletons))) ; defined later 251 python-skeletons))) ; defined later
250 "-" 252 "-"
251 ["Start interpreter" run-python 253 ["Start interpreter" python-shell
252 :help "Run `inferior' Python in separate buffer"] 254 :help "Run `inferior' Python in separate buffer"]
253 ["Import/reload file" python-load-file 255 ["Import/reload file" python-load-file
254 :help "Load into inferior Python session"] 256 :help "Load into inferior Python session"]
@@ -278,6 +280,14 @@ Used for syntactic keywords. N is the match number (1, 2 or 3)."
278;; eric has items including: (un)indent, (un)comment, restart script, 280;; eric has items including: (un)indent, (un)comment, restart script,
279;; run script, debug script; also things for profiling, unit testing. 281;; run script, debug script; also things for profiling, unit testing.
280 282
283(defvar python-shell-map
284 (let ((map (copy-keymap comint-mode-map)))
285 (define-key map [tab] 'tab-to-tab-stop)
286 (define-key map "\C-c-" 'py-up-exception)
287 (define-key map "\C-c=" 'py-down-exception)
288 map)
289 "Keymap used in *Python* shell buffers.")
290
281(defvar python-mode-syntax-table 291(defvar python-mode-syntax-table
282 (let ((table (make-syntax-table))) 292 (let ((table (make-syntax-table)))
283 ;; Give punctuation syntax to ASCII that normally has symbol 293 ;; Give punctuation syntax to ASCII that normally has symbol
@@ -442,6 +452,73 @@ statement."
442 :group 'python 452 :group 'python
443 :type 'integer) 453 :type 'integer)
444 454
455
456(defcustom python-default-interpreter 'cpython
457 "*Which Python interpreter is used by default.
458The value for this variable can be either `cpython' or `jpython'.
459
460When the value is `cpython', the variables `python-python-command' and
461`python-python-command-args' are consulted to determine the interpreter
462and arguments to use.
463
464When the value is `jpython', the variables `python-jpython-command' and
465`python-jpython-command-args' are consulted to determine the interpreter
466and arguments to use.
467
468Note that this variable is consulted only the first time that a Python
469mode buffer is visited during an Emacs session. After that, use
470\\[python-toggle-shells] to change the interpreter shell."
471 :type '(choice (const :tag "Python (a.k.a. CPython)" cpython)
472 (const :tag "JPython" jpython))
473 :group 'python)
474
475(defcustom python-python-command-args '("-i")
476 "*List of string arguments to be used when starting a Python shell."
477 :type '(repeat string)
478 :group 'python)
479
480(defcustom python-jython-command-args '("-i")
481 "*List of string arguments to be used when starting a Jython shell."
482 :type '(repeat string)
483 :group 'python
484 :tag "JPython Command Args")
485
486;; for toggling between CPython and JPython
487(defvar python-which-shell nil)
488(defvar python-which-args python-python-command-args)
489(defvar python-which-bufname "Python")
490(make-variable-buffer-local 'python-which-shell)
491(make-variable-buffer-local 'python-which-args)
492(make-variable-buffer-local 'python-which-bufname)
493
494(defcustom python-pdbtrack-do-tracking-p t
495 "*Controls whether the pdbtrack feature is enabled or not.
496When non-nil, pdbtrack is enabled in all comint-based buffers,
497e.g. shell buffers and the *Python* buffer. When using pdb to debug a
498Python program, pdbtrack notices the pdb prompt and displays the
499source file and line that the program is stopped at, much the same way
500as gud-mode does for debugging C programs with gdb."
501 :type 'boolean
502 :group 'python)
503(make-variable-buffer-local 'python-pdbtrack-do-tracking-p)
504
505;; Bind python-file-queue before installing the kill-emacs-hook.
506(defvar python-file-queue nil
507 "Queue of Python temp files awaiting execution.
508Currently-active file is at the head of the list.")
509
510(defvar python-pdbtrack-is-tracking-p nil)
511
512(defconst python-pdbtrack-stack-entry-regexp
513 "> \\([^(]+\\)(\\([0-9]+\\))[?a-zA-Z0-9_]+()"
514 "Regular expression pdbtrack uses to find a stack trace entry.")
515
516(defconst python-pdbtrack-input-prompt "\n[(<]?pdb[>)]? "
517 "Regular expression pdbtrack uses to recognize a pdb prompt.")
518
519(defconst python-pdbtrack-track-range 10000
520 "Max number of characters from end of buffer to search for stack entry.")
521
445(defun python-guess-indent () 522(defun python-guess-indent ()
446 "Guess step for indentation of current buffer. 523 "Guess step for indentation of current buffer.
447Set `python-indent' locally to the value guessed." 524Set `python-indent' locally to the value guessed."
@@ -2331,6 +2408,372 @@ Runs `jython-mode-hook' after `python-mode-hook'."
2331 :group 'python 2408 :group 'python
2332 (set (make-local-variable 'python-command) python-jython-command)) 2409 (set (make-local-variable 'python-command) python-jython-command))
2333 2410
2411
2412
2413;; pdbtrack features
2414
2415(defsubst python-point (position)
2416 "Returns the value of point at certain commonly referenced POSITIONs.
2417POSITION can be one of the following symbols:
2418
2419 bol -- beginning of line
2420 eol -- end of line
2421 bod -- beginning of def or class
2422 eod -- end of def or class
2423 bob -- beginning of buffer
2424 eob -- end of buffer
2425 boi -- back to indentation
2426 bos -- beginning of statement
2427
2428This function does not modify point or mark."
2429 (let ((here (point)))
2430 (cond
2431 ((eq position 'bol) (beginning-of-line))
2432 ((eq position 'eol) (end-of-line))
2433 ((eq position 'bod) (python-beginning-of-def-or-class))
2434 ((eq position 'eod) (python-end-of-def-or-class))
2435 ;; Kind of funny, I know, but useful for python-up-exception.
2436 ((eq position 'bob) (goto-char (point-min)))
2437 ((eq position 'eob) (goto-char (point-max)))
2438 ((eq position 'boi) (back-to-indentation))
2439 ((eq position 'bos) (python-goto-initial-line))
2440 (t (error "Unknown buffer position requested: %s" position)))
2441 (prog1
2442 (point)
2443 (goto-char here))))
2444
2445(defun python-end-of-def-or-class (&optional class count)
2446 "Move point beyond end of `def' or `class' body.
2447
2448By default, looks for an appropriate `def'. If you supply a prefix
2449arg, looks for a `class' instead. The docs below assume the `def'
2450case; just substitute `class' for `def' for the other case.
2451Programmatically, if CLASS is `either', then moves to either `class'
2452or `def'.
2453
2454When second optional argument is given programmatically, move to the
2455COUNTth end of `def'.
2456
2457If point is in a `def' statement already, this is the `def' we use.
2458
2459Else, if the `def' found by `\\[python-beginning-of-def-or-class]'
2460contains the statement you started on, that's the `def' we use.
2461
2462Otherwise, we search forward for the closest following `def', and use that.
2463
2464If a `def' can be found by these rules, point is moved to the start of
2465the line immediately following the `def' block, and the position of the
2466start of the `def' is returned.
2467
2468Else point is moved to the end of the buffer, and nil is returned.
2469
2470Note that doing this command repeatedly will take you closer to the
2471end of the buffer each time.
2472
2473To mark the current `def', see `\\[python-mark-def-or-class]'."
2474 (interactive "P") ; raw prefix arg
2475 (if (and count (/= count 1))
2476 (python-beginning-of-def-or-class (- 1 count)))
2477 (let ((start (progn (python-goto-initial-line) (point)))
2478 (which (cond ((eq class 'either) "\\(class\\|def\\)")
2479 (class "class")
2480 (t "def")))
2481 (state 'not-found))
2482 ;; move point to start of appropriate def/class
2483 (if (looking-at (concat "[ \t]*" which "\\>")) ; already on one
2484 (setq state 'at-beginning)
2485 ;; else see if python-beginning-of-def-or-class hits container
2486 (if (and (python-beginning-of-def-or-class class)
2487 (progn (python-goto-beyond-block)
2488 (> (point) start)))
2489 (setq state 'at-end)
2490 ;; else search forward
2491 (goto-char start)
2492 (if (re-search-forward (concat "^[ \t]*" which "\\>") nil 'move)
2493 (progn (setq state 'at-beginning)
2494 (beginning-of-line)))))
2495 (cond
2496 ((eq state 'at-beginning) (python-goto-beyond-block) t)
2497 ((eq state 'at-end) t)
2498 ((eq state 'not-found) nil)
2499 (t (error "Internal error in `python-end-of-def-or-class'")))))
2500
2501(defun python-beginning-of-def-or-class (&optional class count)
2502 "Move point to start of `def' or `class'.
2503
2504Searches back for the closest preceding `def'. If you supply a prefix
2505arg, looks for a `class' instead. The docs below assume the `def'
2506case; just substitute `class' for `def' for the other case.
2507Programmatically, if CLASS is `either', then moves to either `class'
2508or `def'.
2509
2510When second optional argument is given programmatically, move to the
2511COUNTth start of `def'.
2512
2513If point is in a `def' statement already, and after the `d', simply
2514moves point to the start of the statement.
2515
2516Otherwise (i.e. when point is not in a `def' statement, or at or
2517before the `d' of a `def' statement), searches for the closest
2518preceding `def' statement, and leaves point at its start. If no such
2519statement can be found, leaves point at the start of the buffer.
2520
2521Returns t iff a `def' statement is found by these rules.
2522
2523Note that doing this command repeatedly will take you closer to the
2524start of the buffer each time.
2525
2526To mark the current `def', see `\\[python-mark-def-or-class]'."
2527 (interactive "P") ; raw prefix arg
2528 (setq count (or count 1))
2529 (let ((at-or-before-p (<= (current-column) (current-indentation)))
2530 (start-of-line (goto-char (python-point 'bol)))
2531 (start-of-stmt (goto-char (python-point 'bos)))
2532 (start-re (cond ((eq class 'either) "^[ \t]*\\(class\\|def\\)\\>")
2533 (class "^[ \t]*class\\>")
2534 (t "^[ \t]*def\\>"))))
2535 ;; searching backward
2536 (if (and (< 0 count)
2537 (or (/= start-of-stmt start-of-line)
2538 (not at-or-before-p)))
2539 (end-of-line))
2540 ;; search forward
2541 (if (and (> 0 count)
2542 (zerop (current-column))
2543 (looking-at start-re))
2544 (end-of-line))
2545 (if (re-search-backward start-re nil 'move count)
2546 (goto-char (match-beginning 0)))))
2547
2548(defun python-goto-initial-line ()
2549 "Go to the initial line of the current statement.
2550Usually this is the line we're on, but if we're on the 2nd or
2551following lines of a continuation block, we need to go up to the first
2552line of the block."
2553 ;; Tricky: We want to avoid quadratic-time behavior for long
2554 ;; continued blocks, whether of the backslash or open-bracket
2555 ;; varieties, or a mix of the two. The following manages to do that
2556 ;; in the usual cases.
2557 ;;
2558 ;; Also, if we're sitting inside a triple quoted string, this will
2559 ;; drop us at the line that begins the string.
2560 (let (open-bracket-pos)
2561 (while (python-continuation-line-p)
2562 (beginning-of-line)
2563 (if (python-backslash-continuation-line-p)
2564 (while (python-backslash-continuation-line-p)
2565 (forward-line -1))
2566 ;; else zip out of nested brackets/braces/parens
2567 (while (setq open-bracket-pos (python-nesting-level))
2568 (goto-char open-bracket-pos)))))
2569 (beginning-of-line))
2570
2571(defun python-comint-output-filter-function (string)
2572 "Watch output for Python prompt and exec next file waiting in queue.
2573This function is appropriate for `comint-output-filter-functions'."
2574 ;; TBD: this should probably use split-string
2575 (when (and (or (string-equal string ">>> ")
2576 (and (>= (length string) 5)
2577 (string-equal (substring string -5) "\n>>> ")))
2578 python-file-queue)
2579 (python-safe (delete-file (car python-file-queue)))
2580 (setq python-file-queue (cdr python-file-queue))
2581 (if python-file-queue
2582 (let ((pyproc (get-buffer-process (current-buffer))))
2583 (python-execute-file pyproc (car python-file-queue))))))
2584
2585(defun python-pdbtrack-overlay-arrow (activation)
2586 "Activate or de arrow at beginning-of-line in current buffer."
2587 ;; This was derived/simplified from edebug-overlay-arrow
2588 (cond (activation
2589 (setq overlay-arrow-position (make-marker))
2590 (setq overlay-arrow-string "=>")
2591 (set-marker overlay-arrow-position
2592 (python-point 'bol) (current-buffer))
2593 (setq python-pdbtrack-is-tracking-p t))
2594 (python-pdbtrack-is-tracking-p
2595 (setq overlay-arrow-position nil)
2596 (setq python-pdbtrack-is-tracking-p nil))))
2597
2598(defun python-pdbtrack-track-stack-file (text)
2599 "Show the file indicated by the pdb stack entry line, in a separate window.
2600
2601Activity is disabled if the buffer-local variable
2602`python-pdbtrack-do-tracking-p' is nil.
2603
2604We depend on the pdb input prompt matching `python-pdbtrack-input-prompt'
2605at the beginning of the line."
2606 ;; Instead of trying to piece things together from partial text
2607 ;; (which can be almost useless depending on Emacs version), we
2608 ;; monitor to the point where we have the next pdb prompt, and then
2609 ;; check all text from comint-last-input-end to process-mark.
2610 ;;
2611 ;; KLM: It might be nice to provide an optional override, so this
2612 ;; routine could be fed debugger output strings as the text
2613 ;; argument, for deliberate application elsewhere.
2614 ;;
2615 ;; KLM: We're very conservative about clearing the overlay arrow, to
2616 ;; minimize residue. This means, for instance, that executing other
2617 ;; pdb commands wipes out the highlight.
2618 (let* ((origbuf (current-buffer))
2619 (currproc (get-buffer-process origbuf)))
2620 (if (not (and currproc python-pdbtrack-do-tracking-p))
2621 (python-pdbtrack-overlay-arrow nil)
2622 (let* (;(origdir default-directory)
2623 (procmark (process-mark currproc))
2624 (block (buffer-substring (max comint-last-input-end
2625 (- procmark
2626 python-pdbtrack-track-range))
2627 procmark))
2628 fname lineno)
2629 (if (not (string-match (concat python-pdbtrack-input-prompt "$") block))
2630 (python-pdbtrack-overlay-arrow nil)
2631 (if (not (string-match
2632 (concat ".*" python-pdbtrack-stack-entry-regexp ".*")
2633 block))
2634 (python-pdbtrack-overlay-arrow nil)
2635 (setq fname (match-string 1 block)
2636 lineno (match-string 2 block))
2637 (if (file-exists-p fname)
2638 (progn
2639 (find-file-other-window fname)
2640 (goto-line (string-to-number lineno))
2641 (message "pdbtrack: line %s, file %s" lineno fname)
2642 (python-pdbtrack-overlay-arrow t)
2643 (pop-to-buffer origbuf t) )
2644 (if (= (elt fname 0) ?\<)
2645 (message "pdbtrack: (Non-file source: '%s')" fname)
2646 (message "pdbtrack: File not found: %s" fname)))))))))
2647
2648(defun python-toggle-shells (arg)
2649 "Toggles between the CPython and JPython shells.
2650
2651With positive argument ARG (interactively \\[universal-argument]),
2652uses the CPython shell, with negative ARG uses the JPython shell, and
2653with a zero argument, toggles the shell.
2654
2655Programmatically, ARG can also be one of the symbols `cpython' or
2656`jpython', equivalent to positive arg and negative arg respectively."
2657 (interactive "P")
2658 ;; default is to toggle
2659 (if (null arg)
2660 (setq arg 0))
2661 ;; preprocess arg
2662 (cond
2663 ((equal arg 0)
2664 ;; toggle
2665 (if (string-equal python-which-bufname "Python")
2666 (setq arg -1)
2667 (setq arg 1)))
2668 ((equal arg 'cpython) (setq arg 1))
2669 ((equal arg 'jpython) (setq arg -1)))
2670 (let (msg)
2671 (cond
2672 ((< 0 arg)
2673 ;; set to CPython
2674 (setq python-which-shell python-python-command
2675 python-which-args python-python-command-args
2676 python-which-bufname "Python"
2677 msg "CPython"
2678 mode-name "Python"))
2679 ((> 0 arg)
2680 (setq python-which-shell python-jython-command
2681 python-which-args python-jython-command-args
2682 python-which-bufname "JPython"
2683 msg "JPython"
2684 mode-name "JPython")))
2685 (message "Using the %s shell" msg)))
2686
2687;;;###autoload
2688(defun python-shell (&optional argprompt)
2689 "Start an interactive Python interpreter in another window.
2690This is like Shell mode, except that Python is running in the window
2691instead of a shell. See the `Interactive Shell' and `Shell Mode'
2692sections of the Emacs manual for details, especially for the key
2693bindings active in the `*Python*' buffer.
2694
2695With optional \\[universal-argument], the user is prompted for the
2696flags to pass to the Python interpreter. This has no effect when this
2697command is used to switch to an existing process, only when a new
2698process is started. If you use this, you will probably want to ensure
2699that the current arguments are retained (they will be included in the
2700prompt). This argument is ignored when this function is called
2701programmatically, or when running in Emacs 19.34 or older.
2702
2703Note: You can toggle between using the CPython interpreter and the
2704JPython interpreter by hitting \\[python-toggle-shells]. This toggles
2705buffer local variables which control whether all your subshell
2706interactions happen to the `*JPython*' or `*Python*' buffers (the
2707latter is the name used for the CPython buffer).
2708
2709Warning: Don't use an interactive Python if you change sys.ps1 or
2710sys.ps2 from their default values, or if you're running code that
2711prints `>>> ' or `... ' at the start of a line. `python-mode' can't
2712distinguish your output from Python's output, and assumes that `>>> '
2713at the start of a line is a prompt from Python. Similarly, the Emacs
2714Shell mode code assumes that both `>>> ' and `... ' at the start of a
2715line are Python prompts. Bad things can happen if you fool either
2716mode.
2717
2718Warning: If you do any editing *in* the process buffer *while* the
2719buffer is accepting output from Python, do NOT attempt to `undo' the
2720changes. Some of the output (nowhere near the parts you changed!) may
2721be lost if you do. This appears to be an Emacs bug, an unfortunate
2722interaction between undo and process filters; the same problem exists in
2723non-Python process buffers using the default (Emacs-supplied) process
2724filter."
2725 (interactive "P")
2726 ;; Set the default shell if not already set
2727 (when (null python-which-shell)
2728 (python-toggle-shells python-default-interpreter))
2729 (let ((args python-which-args))
2730 (when (and argprompt
2731 (interactive-p)
2732 (fboundp 'split-string))
2733 ;; TBD: Perhaps force "-i" in the final list?
2734 (setq args (split-string
2735 (read-string (concat python-which-bufname
2736 " arguments: ")
2737 (concat
2738 (mapconcat 'identity python-which-args " ") " ")
2739 ))))
2740 (switch-to-buffer-other-window
2741 (apply 'make-comint python-which-bufname python-which-shell nil args))
2742 (make-local-variable 'comint-prompt-regexp)
2743 (set-process-sentinel (get-buffer-process (current-buffer)) 'python-sentinel)
2744 (setq comint-prompt-regexp "^>>> \\|^[.][.][.] \\|^(pdb) ")
2745 (add-hook 'comint-output-filter-functions
2746 'python-comint-output-filter-function nil t)
2747 ;; pdbtrack
2748 (add-hook 'comint-output-filter-functions
2749 'python-pdbtrack-track-stack-file nil t)
2750 (setq python-pdbtrack-do-tracking-p t)
2751 (set-syntax-table python-mode-syntax-table)
2752 (use-local-map python-shell-map)))
2753
2754(defun python-pdbtrack-toggle-stack-tracking (arg)
2755 (interactive "P")
2756 (if (not (get-buffer-process (current-buffer)))
2757 (error "No process associated with buffer '%s'" (current-buffer)))
2758 ;; missing or 0 is toggle, >0 turn on, <0 turn off
2759 (if (or (not arg)
2760 (zerop (setq arg (prefix-numeric-value arg))))
2761 (setq python-pdbtrack-do-tracking-p (not python-pdbtrack-do-tracking-p))
2762 (setq python-pdbtrack-do-tracking-p (> arg 0)))
2763 (message "%sabled Python's pdbtrack"
2764 (if python-pdbtrack-do-tracking-p "En" "Dis")))
2765
2766(defun turn-on-pdbtrack ()
2767 (interactive)
2768 (python-pdbtrack-toggle-stack-tracking 1))
2769
2770(defun turn-off-pdbtrack ()
2771 (interactive)
2772 (python-pdbtrack-toggle-stack-tracking 0))
2773
2774(defun python-sentinel (proc msg)
2775 (setq overlay-arrow-position nil))
2776
2334(provide 'python) 2777(provide 'python)
2335(provide 'python-21) 2778(provide 'python-21)
2336;; arch-tag: 6fce1d99-a704-4de9-ba19-c6e4912b0554 2779;; arch-tag: 6fce1d99-a704-4de9-ba19-c6e4912b0554