Skip to content

Commit

Permalink
large output makes Emacs freeze, lp:1253907
Browse files Browse the repository at this point in the history
fixed

`py-fast-process', new commands suitable for large output

Repeated calculations by comint-mode are considered
responsible - bug only showed up in this special case.

Solution uses `process-send-string'; comes with a
couple of new commands prefixed "py-fast-"

If new option `py-fast-process-p' is `t', result arrives in
py-output-buffer, which is not in comint-mode

####

Rewrite - as slicing in new function demanded several changes

  Python code now might be processed by an
  - interactive Python shell (DEFAULT)
  - non-interactive Python (`py-fast-process-p', if large output)

  Both processes might run in
  - session, i.e. start from possible previous state (DEFAULT)
  - dedicated, run in separate process
  • Loading branch information
andreas-roehler committed Mar 17, 2014
1 parent 583b29e commit 264ecbb
Show file tree
Hide file tree
Showing 17 changed files with 400 additions and 435 deletions.
23 changes: 23 additions & 0 deletions NEWS
Expand Up @@ -4,6 +4,19 @@ Python Mode News
New in version 6.1.4
---------------------

Support for large output

new commands py-fast-process, py-fast-...
Fixes: large output makes Emacs freeze, lp:1253907

Python code now might be processed by an
- interactive Python shell (DEFAULT)
- non-interactive Python (`py-fast-process-p', if large output)

Both processes might run in
- session, i.e. start from possible previous state (DEFAULT)
- dedicated, run in separate process

- new indent feature/behavior, lp:1280982
If an empty line was dedented deliberatly, this is
honored by next lines indent
Expand All @@ -18,6 +31,11 @@ Calls to IPython are to customizable now via

New commands

- py-kill-shell-unconditional
With optional argument SHELL, otherwise kill default
(I)Python shell.

Receives a buffer-name as optional argument"
- py-info-lookup-symbol ()
Calls `info-lookup-symbol'. Sends help if stuff is missing.

Expand All @@ -36,6 +54,11 @@ New commands
- py-kill-buffer-unconditional
Kill buffer unconditional; kill also any buffer-process.

Booleans
- py-fast-process-p
If `t', stuff is executed through `py-fast-...'-
commands, suitable for large output. Result arrives
in py-output-buffer, which is not in comint-mode

New in version 6.1.3
---------------------
Expand Down
17 changes: 9 additions & 8 deletions README
Expand Up @@ -51,17 +51,18 @@ Install a local shell by evaluating

;;;;;;;;;

When code is executed from current buffer, either

- python-mode-v5-behavior, a quite simple and effective way.
Setting `python-mode-v5-behavior-p' to `t' makes it the default.
Python code might be processed by an

- if a buffer-file exists and buffer is unchanged, it's file is executed as is.
- interactive Python shell (DEFAULT)
- non-interactive Python (`py-fast-process-p', if large output)

- in all other cases a temporary file is created.
Setback: in case of error, returned error code points
here, i.e. indicated error-line-numbers are not that of
orginal buffer.
Both processes might run in
- session, i.e. start from possible previous state (DEFAULT)
- dedicated, (`py-dedicated-process-p') run in separate process

There is also
- python-mode-v5-behavior

;;;;;;;;;
To enable code auto-completion:
Expand Down
1 change: 1 addition & 0 deletions ToDo.org
@@ -1,3 +1,4 @@
* TODO py-max-help-buffer-p
* TODO py-beginning-of-elif
* TODO py-execute-python-mode-v5 returns position, now result
use orig
Expand Down
31 changes: 31 additions & 0 deletions devel/python-mode-utils.el
Expand Up @@ -194,6 +194,37 @@
;;; python-components-exec-forms.el ends here\n ")
(emacs-lisp-mode))

(defun write-fast-execute-forms (&optional command)
"Write `py-process-block...' etc. "
(interactive)
(let ((py-bounds-command-names (if command (list command) py-execute-forms-names)))
(set-buffer (get-buffer-create "python-components-fast-forms.el"))
(erase-buffer)
(switch-to-buffer (current-buffer))
(insert ";;; python-components-fast-forms.el --- Execute forms at point\n")
(insert arkopf)
(insert ";;; Process forms fast\n\n")
(dolist (ele py-bounds-command-names)
(insert (concat "(defun py-execute-" ele "-fast ()"))
(insert (concat "
\"Process " ele " at point by a Python interpreter.
Suitable for large output, doesn't mess up interactive shell.
Result arrives in `py-output-buffer', which is not in
comint-mode\"\n"))
(insert (concat " (interactive)
(let ((py-fast-process-p t)
(beg (prog1
(or (py-beginning-of-" ele "-p)
(save-excursion
(py-beginning-of-" ele ")))))
(end (save-excursion
(py-end-of-" ele"))))
(py-execute-region beg end)))\n\n"))))
(insert "(provide 'python-components-fast-forms)
;;; python-components-fast-forms.el ends here\n ")
(emacs-lisp-mode))

(defun write-options-dokumentation-subform (pyo)
(cond ((string-match "dedicated" pyo)
(insert "\n\nUses a dedicated shell.")))
Expand Down
122 changes: 1 addition & 121 deletions python-components-edit.el
Expand Up @@ -84,9 +84,7 @@ With optional \\[universal-argument] an indent with length `py-indent-offset' is
(forward-line 1)
(beginning-of-line)
(delete-region (point) (progn (skip-chars-forward " \t\r\n\f") (point)))
(indent-to (py-compute-indentation))))))
;; (exchange-point-and-mark)
)
(indent-to (py-compute-indentation)))))))

(defun py--indent-line-intern (need cui py-indent-offset col &optional beg end region)
(if py-tab-indent
Expand Down Expand Up @@ -125,8 +123,6 @@ With optional \\[universal-argument] an indent with length `py-indent-offset' is
(t
(if (and py-tab-shifts-region-p region)
(progn
;; (when (eq (point) (region-end))
;; (exchange-point-and-mark))
(while (< (current-indentation) need)
(py-shift-region-right 1)))
(beginning-of-line)
Expand Down Expand Up @@ -416,111 +412,6 @@ downwards from beginning of block followed by a statement. Otherwise default-val
(when (interactive-p) (message "%s" py-indent-offset))
py-indent-offset)))

;; (defun py-guess-indent-offset (&optional global orig origline)
;; "Guess a value for, and change, `py-indent-offset'.
;;
;; By default, make a buffer-local copy of `py-indent-offset' with the
;; new value.
;; With optional argument GLOBAL change the global value of `py-indent-offset'.
;;
;; Returns `py-indent-offset'"
;; (interactive "P")
;; (save-excursion
;; (let* ((orig (or orig (point)))
;; (origline (or origline (py-count-lines)))
;; last down done firstindent secondindent
;; (count 0)
;; guessed)
;; (back-to-indentation)
;; (when (looking-at py-block-closing-keywords-re)
;; (setq count (1+ count)))
;; (skip-chars-backward " \t\r\n\f")
;; (back-to-indentation)
;; (when (looking-at py-block-closing-keywords-re)
;; (setq count (1+ count)))
;; (when (< 0 count)
;; (while (and (< 0 count)(re-search-backward py-block-re nil t 1)
;; (or
;; (nth 8 (parse-partial-sexp (point-min) (point)))
;; (progn (setq count (1- count)) t))))
;; (setq firstindent (current-indentation)))
;; (unless firstindent
;; (setq firstindent
;; (cond ((and (py-beginning-of-statement-p) (looking-at py-extended-block-or-clause-re))
;; (current-indentation))
;; ((and (py-beginning-of-statement-p)(looking-at py-block-closing-keywords-re))
;; (while (and (re-search-backward py-extended-block-or-clause-re nil t 1)(nth 8 (syntax-ppss))))
;; ;; (py-beginning-of-statement)
;; (when (py-beginning-of-statement-p) (current-indentation)))
;; ((and (py-beginning-of-statement)(looking-at py-extended-block-or-clause-re))
;; (current-indentation))
;; (t (while (and (setq last (py-beginning-of-statement))(not (looking-at py-extended-block-or-clause-re))))
;; (if last
;; (progn
;; (setq last (point))
;; (setq down t)
;; (current-indentation))
;; (if (and (goto-char orig)
;; (py-end-of-statement)
;; (py-end-of-statement)
;; (py-beginning-of-statement)
;; (looking-at py-extended-block-or-clause-re))
;;
;; (prog1
;; (current-indentation)
;; (setq last (point))
;; (goto-char orig))
;; (while (and (setq last (py-down-statement))(not (looking-at py-extended-block-or-clause-re)))
;; (if last
;; (progn (setq last (point))
;; (setq down t)
;; (current-column))
;; ;; if nothing suitable around, us default
;; (setq done t)
;; (default-value 'py-indent-offset)))))))))
;; (setq secondindent
;; (unless done
;; (if (and firstindent (numberp firstindent))
;; ;; let's look if inside a clause
;; (cond ((and
;; ;; (goto-char orig)
;; (not (eobp))(py-end-of-statement)(py-end-of-statement)(setq last (point))
;; (save-excursion (< firstindent (progn (py-beginning-of-statement)(current-indentation))))
;; (py-end-of-statement-p))
;; (py-beginning-of-statement) (current-indentation))
;; (t (if (progn (setq orig (point)) (while (and (py-beginning-of-statement)(>= firstindent (current-indentation)) (setq last (point)) (not (looking-at py-extended-block-or-clause-re)))) last)
;; (current-indentation)
;; (goto-char orig)
;; (while (and (not (eobp))(py-end-of-statement)(setq last (point))
;; (save-excursion (or (>= firstindent (progn (py-beginning-of-statement)(current-indentation)))(eq last (line-beginning-position))))
;; (py-end-of-statement-p)))
;; (when last (py-beginning-of-statement) (current-indentation))))))))
;; (unless (or done secondindent)
;; (setq secondindent
;; (when (and (py-end-of-statement)
;; (py-end-of-statement)
;; (py-beginning-of-statement))
;; (current-indentation))))
;; (when (and secondindent (numberp secondindent) (numberp firstindent))
;; (when (eq 0 (abs (- secondindent firstindent)))
;; (when (if (py-beginning-of-statement) (< (current-indentation) secondindent))
;; (setq secondindent (current-indentation))))
;; (setq guessed
;; (abs (- secondindent firstindent)))
;; (when (and (eq 0 guessed)(not (eq 0 secondindent)))
;; (setq guessed secondindent)))
;; (if (and guessed (py-guessed-sanity-check guessed))
;; (setq py-indent-offset guessed)
;; (setq py-indent-offset (default-value 'py-indent-offset)))
;; (funcall (if global 'kill-local-variable 'make-local-variable)
;; 'py-indent-offset)
;; (when (and py-verbose-p (interactive-p))
;; (message "%s value of py-indent-offset: %d"
;; (if global "Global" "Local")
;; py-indent-offset))
;; py-indent-offset))
;; )

(defun py-comment-indent-function ()
"Python version of `comment-indent-function'."
;; This is required when filladapt is turned off. Without it, when
Expand Down Expand Up @@ -556,17 +447,6 @@ The defun visible is the one that contains point or follows point. "
(when (and py-verbose-p (interactive-p)) (message "%s" erg))
erg))

;; (defun py-beginning-of-paragraph ()
;; "Go to beginning of paragraph.
;;
;; Consider a string starting at current indentation as beginning too "
;; (interactive)
;; (let* ((pps (syntax-ppss))
;; (erg (and (nth 3 pps)(nth 8 pps))))
;; (if (and erg (progn (back-to-indentation) (looking-at "\"\"\"\\|'''\\|\"\\|'")))
;; erg
;; (backward-paragraph))))

;; (defalias 'py-end-of-paragraph 'forward-paragraph)
(defun py-end-of-paragraph ()
(interactive)
Expand Down
83 changes: 12 additions & 71 deletions python-components-exec-forms.el
@@ -1,5 +1,6 @@
;;; python-components-exec-forms.el --- Execute forms at point

;; Copyright (C) 2011-2014 Andreas Roehler
;; Author: Andreas Roehler <andreas.roehler@online.de>
;; Keywords: languages, convenience

Expand All @@ -21,116 +22,56 @@
;;; Code:

;;; Execute forms at point

(defun py-execute-statement ()
"Send statement at point to a Python interpreter. "
(interactive)
(let ((beg (prog1
(or (py-beginning-of-statement-p)
(save-excursion
(py-beginning-of-statement)))))
(end (save-excursion
(py-end-of-statement))))
(py-execute-region beg end)))
(py-execute-prepare "statement"))

(defun py-execute-block ()
"Send block at point to a Python interpreter. "
(interactive)
(let ((beg (prog1
(or (py-beginning-of-block-p)
(save-excursion
(py-beginning-of-block)))))
(end (save-excursion
(py-end-of-block))))
(py-execute-region beg end)))
(py-execute-prepare "block"))

(defun py-execute-block-or-clause ()
"Send block-or-clause at point to a Python interpreter. "
(interactive)
(let ((beg (prog1
(or (py-beginning-of-block-or-clause-p)
(save-excursion
(py-beginning-of-block-or-clause)))))
(end (save-excursion
(py-end-of-block-or-clause))))
(py-execute-region beg end)))
(py-execute-prepare "block-or-clause"))

(defun py-execute-def ()
"Send def at point to a Python interpreter. "
(interactive)
(let ((beg (prog1
(or (py-beginning-of-def-p)
(save-excursion
(py-beginning-of-def)))))
(end (save-excursion
(py-end-of-def))))
(py-execute-region beg end)))
(py-execute-prepare "def"))

(defun py-execute-class ()
"Send class at point to a Python interpreter. "
(interactive)
(let ((beg (prog1
(or (py-beginning-of-class-p)
(save-excursion
(py-beginning-of-class)))))
(end (save-excursion
(py-end-of-class))))
(py-execute-region beg end)))
(py-execute-prepare "class"))

(defun py-execute-def-or-class ()
"Send def-or-class at point to a Python interpreter. "
(interactive)
(let ((beg (prog1
(or (py-beginning-of-def-or-class-p)
(save-excursion
(py-beginning-of-def-or-class)))))
(end (save-excursion
(py-end-of-def-or-class))))
(py-execute-region beg end)))
(py-execute-prepare "def-or-class"))

(defun py-execute-expression ()
"Send expression at point to a Python interpreter. "
(interactive)
(let ((beg (prog1
(or (py-beginning-of-expression-p)
(save-excursion
(py-beginning-of-expression)))))
(end (save-excursion
(py-end-of-expression))))
(py-execute-region beg end)))
(py-execute-prepare "expression"))

(defun py-execute-partial-expression ()
"Send partial-expression at point to a Python interpreter. "
(interactive)
(let ((beg (prog1
(or (py-beginning-of-partial-expression-p)
(save-excursion
(py-beginning-of-partial-expression)))))
(end (save-excursion
(py-end-of-partial-expression))))
(py-execute-region beg end)))
(py-execute-prepare "partial-expression"))

(defun py-execute-top-level ()
"Send top-level at point to a Python interpreter. "
(interactive)
(let ((beg (prog1
(or (py-beginning-of-top-level-p)
(save-excursion
(py-beginning-of-top-level)))))
(end (save-excursion
(py-end-of-top-level))))
(py-execute-region beg end)))
(py-execute-prepare "top-level"))

(defun py-execute-clause ()
"Send clause at point to a Python interpreter. "
(interactive)
(let ((beg (prog1
(or (py-beginning-of-clause-p)
(save-excursion
(py-beginning-of-clause)))))
(end (save-excursion
(py-end-of-clause))))
(py-execute-region beg end)))
(py-execute-prepare "clause"))

(provide 'python-components-exec-forms)
;;; python-components-exec-forms.el ends here

0 comments on commit 264ecbb

Please sign in to comment.