[IPython-user] autoindentation problem in emacs
Liu Jin
m.liu.jin at gmail.com
Sun Mar 26 23:11:02 CST 2006
>>>>> SK <skokot at o2.pl> writes:
> Now autoindent works. The only problem is that when new prompt
> comes, the indentation remains as in the example below.
> In [3]: for i in range(2):
> ...: for j in range(1):
> ...: print i, j
> ...:
> 0 0
> 1 0 | cursor comes here
> v
> In [4]: x = 5
I've also noticed that. Here's the problematic part:
(defun ipython-newline-and-indent ()
(interactive)
(if ipython-autoindent
...
(comint-send-input)
(insert indention))
I should really check if current line begins with " ...:"
(i.e. py-shell-input-prompt-2-regexp) before inserting
whitespaces. But the tricky part is, after the comint-send-input call
(which sends current line to ipython), the response is yet to come.
So here's another attempt. It uses comint-output-filter. I have a gut
feeling that this is unreliable, but it seems to work so far...
<elisp code below>
(defvar ipython-autoindent t
"If non-nil, enable autoindent for IPython shell through python-mode.")
(defvar ipython-indenting-buffer-name "*IPython Indentation Calculation*"
"Temporary buffer for indenting multiline statement.")
(defun ipython-get-indenting-buffer ()
"Return a temporary buffer set in python-mode. Create one if necessary."
(let ((buf (get-buffer-create ipython-indenting-buffer-name)))
(set-buffer buf)
(unless (eq major-mode 'python-mode)
(python-mode))
buf))
(defvar ipython-indentation-string nil
"Indentation for the next line in a multiline statement.")
(defun ipython-newline-and-indent ()
"Send the current line to IPython, and calculate the indentation for the next line."
(interactive)
(if ipython-autoindent
(let ((line (buffer-substring (line-beginning-position) (point)))
(after-prompt1)
(after-prompt2))
(save-excursion
(comint-bol t)
(if (looking-at py-shell-input-prompt-1-regexp)
(setq after-prompt1 t)
(setq after-prompt2 (looking-at py-shell-input-prompt-2-regexp)))
(set-buffer (ipython-get-indenting-buffer))
(when after-prompt1
(erase-buffer))
(when (or after-prompt1 after-prompt2)
(delete-region (line-beginning-position) (point))
(insert line)
(newline-and-indent)
(setq ipython-indentation-string
(buffer-substring (line-beginning-position) (point)))))))
(comint-send-input))
(defun ipython-indentation-hook (str)
"Insert indentation string if py-shell-input-prompt-2-regexp
matches last process output."
(or (= (length str) 0)
(eq ipython-indentation-string nil)
(progn
(when (string-match
py-shell-input-prompt-2-regexp
(buffer-substring comint-last-output-start
(process-mark (get-buffer-process
(current-buffer)))))
(insert ipython-indentation-string))
(setq ipython-indentation-string nil))))
(add-hook 'py-shell-hook
(lambda ()
(add-hook 'comint-output-filter-functions
'ipython-indentation-hook)))
(define-key py-shell-map (kbd "RET") 'ipython-newline-and-indent)
More information about the IPython-user
mailing list