1
;;; ipython-integration.el - work-sheet integrating ipython.el
3
;; ipython.el added support for IPython to python-mode.el: Copyright (C) 2002, 2003, 2004, 2005 Alexander Schmolck
4
;; Author: Alexander Schmolck
5
;; Keywords: ipython python languages oop
6
;; URL: http://ipython.org
7
;; Compatibility: Emacs21, XEmacs21
8
;; FIXME: #$@! INPUT RING
10
;; Integration started from ipython-version "0.11"
14
;; Uses Ipython will be set as the python interpreter, see URL above.
16
;; defines the command `ipython-to-doctest', which
17
;; can be used to convert bits of a ipython session into something that can be
20
;; For ipython sessions autocompletion with <tab>
21
;; is also enabled (experimental feature!). Please also note that all the
22
;; terminal functions in py-shell are handled by emacs's comint, **not** by
23
;; (i)python, so importing readline etc. will have 0 effect.
25
;; To start an interactive ipython session run `py-shell' with ``M-x py-shell``
26
;; (or the default keybinding ``C-c C-!``).
29
;; You can customize the arguments passed to the IPython instance at startup by
30
;; setting the ``py-python-command-args`` variable. For example, to start
31
;; always in ``pylab`` mode with hardcoded light-background colors, you can
34
;; (setq py-python-command-args '("-pylab" "--colors" "LightBG"))
37
;; NOTE: This mode is currently somewhat alpha and although I hope that it
38
;; will work fine for most cases, doing certain things (like the
39
;; autocompletion and a decent scheme to switch between python interpreters)
40
;; properly will also require changes to ipython that will likely have to wait
41
;; for a larger rewrite scheduled some time in the future.
44
;; Hints for effective usage
45
;; -------------------------
47
;; - IMO the best feature by far of the ipython/emacs combo is how much easier
48
;; it makes it to find and fix bugs thanks to the ``%pdb on or %debug``/
49
;; pdbtrack combo. Try it: first in the ipython to shell do ``%pdb on`` then
50
;; do something that will raise an exception (FIXME nice example), or type
51
;; ``%debug`` after the exception has been raised. YOu'll be amazed at how
52
;; easy it is to inspect the live objects in each stack frames and to jump to
53
;; the corresponding sourcecode locations as you walk up and down the stack
54
;; trace (even without ``%pdb on`` you can always use ``C-c -``
55
;; (`py-up-exception') to jump to the corresponding source code locations).
58
;; - This is not really specific to ipython, but for more convenient history
59
;; access you might want to add something like the following to *the beggining*
60
;; of your ``.emacs`` (if you want behavior that's more similar to stand-alone
61
;; ipython, you can change ``meta p`` etc. for ``control p``)::
64
;; (define-key comint-mode-map [(meta p)]
65
;; 'comint-previous-matching-input-from-input)
66
;; (define-key comint-mode-map [(meta n)]
67
;; 'comint-next-matching-input-from-input)
68
;; (define-key comint-mode-map [(control meta n)]
69
;; 'comint-next-input)
70
;; (define-key comint-mode-map [(control meta p)]
71
;; 'comint-previous-input)
74
;; - Be aware that if you customize py-python-command previously, this value
75
;; will override what ipython.el does (because loading the customization
76
;; variables comes later).
79
;; Please send comments and feedback to the ipython-list
80
;; (<ipython-user@scipy.org>) where I (a.s.) or someone else will try to
81
;; answer them (it helps if you specify your emacs version, OS etc;
82
;; familiarity with <http://www.catb.org/~esr/faqs/smart-questions.html> might
83
;; speed up things further).
87
;; [1] If you don't know what `load-path' is, C-h v load-path will tell
88
;; you; if required you can also add a new directory. So assuming that
89
;; ipython.el resides in ~/el/, put this in your emacs:
92
;; (add-to-list 'load-path "~/el")
93
;; (setq ipython-command "/some-path/ipython")
100
;; - do autocompletion properly
101
;; - implement a proper switching between python interpreters
106
;; (py-shell "-c print 'FOOBAR'")
110
;; (let ((py-python-command-args (append py-python-command-args
111
;; '("-c" "print 'FOOBAR'"))))
114
;; seem to print anything as they should
116
;; - look into init priority issues with `py-python-command' (if it's set
122
(require 'executable)
123
(require 'ansi-color)
125
;; XXX load python-mode, so that we can screw around with its variables
126
;; this has the disadvantage that python-mode is loaded even if no
127
;; python-file is ever edited etc. but it means that `py-shell' works
128
;; without loading a python-file first. Obviously screwing around with
129
;; python-mode's variables like this is a mess, but well.
130
(require 'python-mode)
131
;; turn on ansi colors for ipython and activate completion
132
;; (defun ipython-shell-hook ()
133
;; ;; the following is to synchronize dir-changes
134
;; (make-local-variable 'shell-dirstack)
135
;; (setq shell-dirstack nil)
136
;; (make-local-variable 'shell-last-dir)
137
;; (setq shell-last-dir nil)
138
;; (make-local-variable 'shell-dirtrackp)
139
;; (setq shell-dirtrackp t)
140
;; (add-hook 'comint-input-filter-functions 'shell-directory-tracker nil t)
142
;; (ansi-color-for-comint-mode-on)
143
;; (define-key py-shell-map [tab] 'ipython-complete)
144
;; ;; Add this so that tab-completion works both in X11 frames and inside
145
;; ;; terminals (such as when emacs is called with -nw).
146
;; (define-key py-shell-map "\t" 'ipython-complete)
147
;; ;;XXX this is really just a cheap hack, it only completes symbols in the
148
;; ;;interactive session -- useful nonetheless.
149
;; (define-key py-mode-map [(meta tab)] 'ipython-complete)
152
;; (add-hook 'py-shell-hook 'ipython-shell-hook)
153
;; Regular expression that describes tracebacks for IPython in context and
156
;;Adapt python-mode settings for ipython.
157
;; (this works for %xmode 'verbose' or 'context')
159
;; XXX putative regexps for syntax errors; unfortunately the
160
;; current python-mode traceback-line-re scheme is too primitive,
161
;; so it's either matching syntax errors, *or* everything else
162
;; (XXX: should ask Fernando for a change)
163
;;"^ File \"\\(.*?\\)\", line \\([0-9]+\\).*\n.*\n.*\nSyntaxError:"
164
;;^ File \"\\(.*?\\)\", line \\([0-9]+\\)"
166
(setq py-traceback-line-re
167
"\\(^[^\t >].+?\\.py\\).*\n +[0-9]+[^\00]*?\n-+> \\([0-9]+\\)+")
169
;; Recognize the ipython pdb, whose prompt is 'ipdb>' or 'ipydb>'
171
(setq py-pdbtrack-input-prompt "\n[(<]*[Ii]?[Pp]y?db[>)]+ ")
172
(setq pydb-pydbtrack-input-prompt "\n[(]*ipydb[>)]+ ")
174
(setq py-shell-input-prompt-1-regexp "^In \\[[0-9]+\\]: *"
175
py-shell-input-prompt-2-regexp "^ [.][.][.]+: *")
176
;; select a suitable color-scheme
177
(unless (member "--colors" py-python-command-args)
178
(setq py-python-command-args
179
(nconc py-python-command-args
182
((eq frame-background-mode 'dark)
184
((eq frame-background-mode 'light)
186
(t ; default (backg-mode isn't always set by XEmacs)
188
(unless (equal ipython-backup-of-py-python-command py-python-command)
189
(setq ipython-backup-of-py-python-command py-python-command))
190
(setq py-python-command ipython-command)
192
;; MODIFY py-shell so that it loads the editing history
193
(defadvice py-shell (around py-shell-with-history)
194
"Add persistent command-history support (in
195
$PYTHONHISTORY (or \"~/.ipython/history\", if we use IPython)). Also, if
196
`py-shell-initial-switch-buffers' is nil, it only switches to *Python* if that
197
buffer already exists."
198
(if (comint-check-proc "*Python*")
200
(setq comint-input-ring-file-name
201
(if (string-equal py-python-command ipython-command)
202
(concat (or (getenv "IPYTHONDIR") "~/.ipython") "/history")
203
(or (getenv "PYTHONHISTORY") "~/.python-history.py")))
204
(comint-read-input-ring t)
205
(let ((buf (current-buffer)))
207
(unless py-shell-initial-switch-buffers
208
(switch-to-buffer-other-window buf)))))
209
(ad-activate 'py-shell)
211
(defun ipython-to-doctest (start end)
212
"Transform a cut-and-pasted bit from an IPython session into something that
213
looks like it came from a normal interactive python session, so that it can
214
be used in doctests. Example:
218
In [2]: sys.stdout.write 'Hi!\n'
219
------> sys.stdout.write ('Hi!\n')
228
>>> sys.stdout.write ('Hi!\n')
235
;(message (format "###DEBUG s:%de:%d" start end))
238
;; replace ``In [3]: bla`` with ``>>> bla`` and
239
;; ``... : bla`` with ``... bla``
241
(while (re-search-forward ipython-de-input-prompt-regexp end t)
242
;(message "finding 1")
243
(cond ((match-string 3) ;continued
244
(replace-match "... \\3" t nil))
246
(replace-match ">>> \\1\\2" t nil))))
249
(while (re-search-forward ipython-de-output-prompt-regexp end t)
250
(replace-match "" t nil)))))
252
(defvar ipython-completion-command-string
253
"print(';'.join(get_ipython().Completer.all_completions('%s'))) #PYTHON-MODE SILENT\n"
254
"The string send to ipython to query for all possible completions")
256
;; xemacs doesn't have `comint-preoutput-filter-functions' so we'll try the
257
;; following wonderful hack to work around this case
258
(if (featurep 'xemacs)
260
(defun ipython-complete ()
261
"Try to complete the python symbol before point. Only knows about the stuff
262
in the current *Python* session."
264
(let* ((ugly-return nil)
266
(python-process (or (get-buffer-process (current-buffer))
267
;XXX hack for .py buffers
268
(get-process py-which-bufname)))
269
;; XXX currently we go backwards to find the beginning of an
270
;; expression part; a more powerful approach in the future might be
271
;; to let ipython have the complete line, so that context can be used
272
;; to do things like filename completion etc.
273
(beg (save-excursion (skip-chars-backward "a-z0-9A-Z_." (point-at-bol))
276
(pattern (buffer-substring-no-properties beg end))
278
(completion-table nil)
280
(comint-output-filter-functions
281
(append comint-output-filter-functions
282
'(ansi-color-filter-apply
284
;(message (format "DEBUG filtering: %s" string))
285
(setq ugly-return (concat ugly-return string))
286
(delete-region comint-last-output-start
287
(process-mark (get-buffer-process (current-buffer)))))))))
288
;(message (format "#DEBUG pattern: '%s'" pattern))
289
(process-send-string python-process
290
(format ipython-completion-command-string pattern))
291
(accept-process-output python-process)
293
;(message (format "DEBUG return: %s" ugly-return))
295
(split-string (substring ugly-return 0 (position ?\n ugly-return)) sep))
296
(setq completion-table (loop for str in completions
297
collect (list str nil)))
298
(setq completion (try-completion pattern completion-table))
299
(cond ((eq completion t))
301
(message "Can't find completion for \"%s\"" pattern)
303
((not (string= pattern completion))
304
(delete-region beg end)
307
(message "Making completion list...")
308
(with-output-to-temp-buffer "*Python Completions*"
309
(display-completion-list (all-completions pattern completion-table)))
310
(message "Making completion list...%s" "done")))))
312
(defun ipython-complete ()
313
"Try to complete the python symbol before point. Only knows about the stuff
314
in the current *Python* session."
316
(let* ((ugly-return nil)
318
(python-process (or (get-buffer-process (current-buffer))
319
;XXX hack for .py buffers
320
(get-process py-which-bufname)))
321
;; XXX currently we go backwards to find the beginning of an
322
;; expression part; a more powerful approach in the future might be
323
;; to let ipython have the complete line, so that context can be used
324
;; to do things like filename completion etc.
325
(beg (save-excursion (skip-chars-backward "a-z0-9A-Z_./" (point-at-bol))
328
(pattern (buffer-substring-no-properties beg end))
330
(completion-table nil)
332
(comint-preoutput-filter-functions
333
(append comint-preoutput-filter-functions
334
'(ansi-color-filter-apply
336
(setq ugly-return (concat ugly-return string))
338
(process-send-string python-process
339
(format ipython-completion-command-string pattern))
340
(accept-process-output python-process)
342
(split-string (substring ugly-return 0 (position ?\n ugly-return)) sep))
343
;(message (format "DEBUG completions: %S" completions))
344
(setq completion-table (loop for str in completions
345
collect (list str nil)))
346
(setq completion (try-completion pattern completion-table))
347
(cond ((eq completion t))
349
(message "Can't find completion for \"%s\"" pattern)
351
((not (string= pattern completion))
352
(delete-region beg end)
355
(message "Making completion list...")
356
(with-output-to-temp-buffer "*IPython Completions*"
357
(display-completion-list (all-completions pattern completion-table)))
358
(message "Making completion list...%s" "done")))))
361
;;; autoindent support: patch sent in by Jin Liu <m.liu.jin@gmail.com>,
362
;;; originally written by doxgen@newsmth.net
363
;;; Minor modifications by fperez for xemacs compatibility.
365
(defvar ipython-autoindent t
366
"If non-nil, enable autoindent for IPython shell through python-mode.")
368
(defvar ipython-indenting-buffer-name "*IPython Indentation Calculation*"
369
"Temporary buffer for indenting multiline statement.")
371
(defun ipython-get-indenting-buffer ()
372
"Return a temporary buffer set in python-mode. Create one if necessary."
373
(let ((buf (get-buffer-create ipython-indenting-buffer-name)))
375
(unless (eq major-mode 'python-mode)
379
(defvar ipython-indentation-string nil
380
"Indentation for the next line in a multiline statement.")
382
(defun ipython-send-and-indent ()
383
"Send the current line to IPython, and calculate the indentation for
386
(if ipython-autoindent
387
(let ((line (buffer-substring (point-at-bol) (point)))
392
(if (looking-at py-shell-input-prompt-1-regexp)
393
(setq after-prompt1 t)
394
(setq after-prompt2 (looking-at py-shell-input-prompt-2-regexp)))
395
(with-current-buffer (ipython-get-indenting-buffer)
398
(when (or after-prompt1 after-prompt2)
399
(delete-region (point-at-bol) (point))
401
(newline-and-indent))))))
402
;; send input line to ipython interpreter
405
(defun ipython-indentation-hook (string)
406
"Insert indentation string if py-shell-input-prompt-2-regexp
407
matches last process output."
408
(let* ((start-marker (or comint-last-output-start
410
(end-marker (process-mark (get-buffer-process (current-buffer))))
411
(text (ansi-color-filter-apply (buffer-substring start-marker end-marker))))
412
;; XXX if `text' matches both pattern, it MUST be the last prompt-2
413
(when (and (string-match py-shell-input-prompt-2-regexp text)
414
(not (string-match "\n$" text)))
415
(with-current-buffer (ipython-get-indenting-buffer)
416
(setq ipython-indentation-string
417
(buffer-substring (point-at-bol) (point))))
418
(goto-char end-marker)
419
(insert ipython-indentation-string)
420
(setq ipython-indentation-string nil))))
422
(add-hook 'py-shell-hook
424
(add-hook 'comint-output-filter-functions
425
'ipython-indentation-hook)))
427
(define-key py-shell-map (kbd "RET") 'ipython-send-and-indent)
428
;;; / end autoindent support