##// END OF EJS Templates
Add support for autoindent inside (X)emacs.
fperez -
Show More

The requested changes are too big and content was truncated. Show full diff

1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
@@ -1,408 +1,485 b''
1 1 ;;; ipython.el --- Adds support for IPython to python-mode.el
2 2
3 3 ;; Copyright (C) 2002, 2003, 2004, 2005 Alexander Schmolck
4 4 ;; Author: Alexander Schmolck
5 5 ;; Keywords: ipython python languages oop
6 6 ;; URL: http://ipython.scipy.org
7 7 ;; Compatibility: Emacs21, XEmacs21
8 8 ;; FIXME: #$@! INPUT RING
9 (defconst ipython-version "$Revision: 1324 $"
9 (defconst ipython-version "$Revision: 1325 $"
10 10 "VC version number.")
11 11
12 12 ;;; Commentary
13 13 ;; This library makes all the functionality python-mode has when running with
14 14 ;; the normal python-interpreter available for ipython, too. It also enables a
15 15 ;; persistent py-shell command history accross sessions (if you exit python
16 16 ;; with C-d in py-shell) and defines the command `ipython-to-doctest', which
17 17 ;; can be used to convert bits of a ipython session into something that can be
18 18 ;; used for doctests. To install, put this file somewhere in your emacs
19 19 ;; `load-path' [1] and add the following line to your ~/.emacs file (the first
20 20 ;; line only needed if the default (``"ipython"``) is wrong)::
21 21 ;;
22 22 ;; (setq ipython-command "/SOME-PATH/ipython")
23 23 ;; (require 'ipython)
24 24 ;;
25 25 ;; Ipython will be set as the default python shell, but only if the ipython
26 26 ;; executable is in the path. For ipython sessions autocompletion with <tab>
27 27 ;; is also enabled (experimental feature!). Please also note that all the
28 28 ;; terminal functions in py-shell are handled by emacs's comint, **not** by
29 29 ;; (i)python, so importing readline etc. will have 0 effect.
30 30 ;;
31 31 ;; To start an interactive ipython session run `py-shell' with ``M-x py-shell``
32 32 ;; (or the default keybinding ``C-c C-!``).
33 33 ;;
34 34 ;; NOTE: This mode is currently somewhat alpha and although I hope that it
35 35 ;; will work fine for most cases, doing certain things (like the
36 36 ;; autocompletion and a decent scheme to switch between python interpreters)
37 37 ;; properly will also require changes to ipython that will likely have to wait
38 38 ;; for a larger rewrite scheduled some time in the future.
39 39 ;;
40 40 ;; Also note that you currently NEED THE CVS VERSION OF PYTHON.EL.
41 41 ;;
42 42 ;; Further note that I don't know whether this runs under windows or not and
43 43 ;; that if it doesn't I can't really help much, not being afflicted myself.
44 44 ;;
45 45 ;;
46 46 ;; Hints for effective usage
47 47 ;; -------------------------
48 48 ;;
49 49 ;; - IMO the best feature by far of the ipython/emacs combo is how much easier it
50 50 ;; makes it to find and fix bugs thanks to the ``%pdb on``/ pdbtrack combo. Try
51 51 ;; it: first in the ipython to shell do ``%pdb on`` then do something that will
52 52 ;; raise an exception (FIXME nice example) -- and be amazed how easy it is to
53 53 ;; inspect the live objects in each stack frames and to jump to the
54 54 ;; corresponding sourcecode locations as you walk up and down the stack trace
55 55 ;; (even without ``%pdb on`` you can always use ``C-c -`` (`py-up-exception')
56 56 ;; to jump to the corresponding source code locations).
57 57 ;;
58 58 ;; - emacs gives you much more powerful commandline editing and output searching
59 59 ;; capabilities than ipython-standalone -- isearch is your friend if you
60 60 ;; quickly want to print 'DEBUG ...' to stdout out etc.
61 61 ;;
62 62 ;; - This is not really specific to ipython, but for more convenient history
63 63 ;; access you might want to add something like the following to *the beggining*
64 64 ;; of your ``.emacs`` (if you want behavior that's more similar to stand-alone
65 65 ;; ipython, you can change ``meta p`` etc. for ``control p``)::
66 66 ;;
67 67 ;; (require 'comint)
68 68 ;; (define-key comint-mode-map [(meta p)]
69 69 ;; 'comint-previous-matching-input-from-input)
70 70 ;; (define-key comint-mode-map [(meta n)]
71 71 ;; 'comint-next-matching-input-from-input)
72 72 ;; (define-key comint-mode-map [(control meta n)]
73 73 ;; 'comint-next-input)
74 74 ;; (define-key comint-mode-map [(control meta p)]
75 75 ;; 'comint-previous-input)
76 76 ;;
77 77 ;; - Be aware that if you customize py-python-command previously, this value
78 78 ;; will override what ipython.el does (because loading the customization
79 79 ;; variables comes later).
80 80 ;;
81 81 ;; Please send comments and feedback to the ipython-list
82 82 ;; (<ipython-user@scipy.net>) where I (a.s.) or someone else will try to
83 83 ;; answer them (it helps if you specify your emacs version, OS etc;
84 84 ;; familiarity with <http://www.catb.org/~esr/faqs/smart-questions.html> might
85 85 ;; speed up things further).
86 86 ;;
87 87 ;; Footnotes:
88 88 ;;
89 89 ;; [1] If you don't know what `load-path' is, C-h v load-path will tell
90 90 ;; you; if required you can also add a new directory. So assuming that
91 91 ;; ipython.el resides in ~/el/, put this in your emacs:
92 92 ;;
93 93 ;;
94 94 ;; (add-to-list 'load-path "~/el")
95 95 ;; (setq ipython-command "/some-path/ipython")
96 96 ;; (require 'ipython)
97 97 ;;
98 98 ;;
99 99 ;;
100 100 ;;
101 101 ;; TODO:
102 102 ;; - do autocompletion properly
103 103 ;; - implement a proper switching between python interpreters
104 104 ;;
105 105 ;; BUGS:
106 106 ;; - neither::
107 107 ;;
108 108 ;; (py-shell "-c print 'FOOBAR'")
109 109 ;;
110 110 ;; nor::
111 111 ;;
112 112 ;; (let ((py-python-command-args (append py-python-command-args
113 113 ;; '("-c" "print 'FOOBAR'"))))
114 114 ;; (py-shell))
115 115 ;;
116 116 ;; seem to print anything as they should
117 117 ;;
118 118 ;; - look into init priority issues with `py-python-command' (if it's set
119 119 ;; via custom)
120 120
121 121
122 122 ;;; Code
123 123 (require 'cl)
124 124 (require 'shell)
125 125 (require 'executable)
126 126 (require 'ansi-color)
127 127
128 128 (defcustom ipython-command "ipython"
129 129 "*Shell command used to start ipython."
130 130 :type 'string
131 131 :group 'python)
132 132
133 133 ;; Users can set this to nil
134 134 (defvar py-shell-initial-switch-buffers t
135 135 "If nil, don't switch to the *Python* buffer on the first call to
136 136 `py-shell'.")
137 137
138 138 (defvar ipython-backup-of-py-python-command nil
139 139 "HACK")
140 140
141 141
142 142 (defvar ipython-de-input-prompt-regexp "\\(?:
143 143 In \\[[0-9]+\\]: *.*
144 144 ----+> \\(.*
145 145 \\)[\n]?\\)\\|\\(?:
146 146 In \\[[0-9]+\\]: *\\(.*
147 147 \\)\\)\\|^[ ]\\{3\\}[.]\\{3,\\}: *\\(.*
148 148 \\)"
149 149 "A regular expression to match the IPython input prompt and the python
150 150 command after it. The first match group is for a command that is rewritten,
151 151 the second for a 'normal' command, and the third for a multiline command.")
152 152 (defvar ipython-de-output-prompt-regexp "^Out\\[[0-9]+\\]: "
153 153 "A regular expression to match the output prompt of IPython.")
154 154
155 155
156 156 (if (not (executable-find ipython-command))
157 157 (message (format "Can't find executable %s - ipython.el *NOT* activated!!!"
158 158 ipython-command))
159 159 ;; XXX load python-mode, so that we can screw around with its variables
160 160 ;; this has the disadvantage that python-mode is loaded even if no
161 161 ;; python-file is ever edited etc. but it means that `py-shell' works
162 162 ;; without loading a python-file first. Obviously screwing around with
163 163 ;; python-mode's variables like this is a mess, but well.
164 164 (require 'python-mode)
165 165 ;; turn on ansi colors for ipython and activate completion
166 166 (defun ipython-shell-hook ()
167 167 ;; the following is to synchronize dir-changes
168 168 (make-local-variable 'shell-dirstack)
169 169 (setq shell-dirstack nil)
170 170 (make-local-variable 'shell-last-dir)
171 171 (setq shell-last-dir nil)
172 172 (make-local-variable 'shell-dirtrackp)
173 173 (setq shell-dirtrackp t)
174 174 (add-hook 'comint-input-filter-functions 'shell-directory-tracker nil t)
175 175
176 176 (ansi-color-for-comint-mode-on)
177 177 (define-key py-shell-map [tab] 'ipython-complete)
178 178 ;;XXX this is really just a cheap hack, it only completes symbols in the
179 179 ;;interactive session -- useful nonetheless.
180 180 (define-key py-mode-map [(meta tab)] 'ipython-complete)
181 181
182 182 )
183 183 (add-hook 'py-shell-hook 'ipython-shell-hook)
184 184 ;; Regular expression that describes tracebacks for IPython in context and
185 185 ;; verbose mode.
186 186
187 187 ;;Adapt python-mode settings for ipython.
188 188 ;; (this works for %xmode 'verbose' or 'context')
189 189
190 190 ;; XXX putative regexps for syntax errors; unfortunately the
191 191 ;; current python-mode traceback-line-re scheme is too primitive,
192 192 ;; so it's either matching syntax errors, *or* everything else
193 193 ;; (XXX: should ask Fernando for a change)
194 194 ;;"^ File \"\\(.*?\\)\", line \\([0-9]+\\).*\n.*\n.*\nSyntaxError:"
195 195 ;;^ File \"\\(.*?\\)\", line \\([0-9]+\\)"
196 196
197 197 (setq py-traceback-line-re
198 198 "\\(^[^\t ].+?\\.py\\).*\n +[0-9]+[^\00]*?\n-+> \\([0-9]+\\) +")
199 199
200 200 ;; Recognize the ipython pdb, whose prompt is 'ipdb>' instead of '(Pdb)'
201 201 (setq py-pdbtrack-input-prompt "\n[(<]*[Ii]?[Pp]db[>)]+ ")
202 202
203 203 (setq py-shell-input-prompt-1-regexp "^In \\[[0-9]+\\]: *"
204 204 py-shell-input-prompt-2-regexp "^ [.][.][.]+: *" )
205 205 ;; select a suitable color-scheme
206 206 (unless (member "-colors" py-python-command-args)
207 207 (setq py-python-command-args
208 208 (nconc py-python-command-args
209 209 (list "-colors"
210 210 (cond
211 211 ((eq frame-background-mode 'dark)
212 212 "DarkBG")
213 213 ((eq frame-background-mode 'light)
214 214 "LightBG")
215 215 (t ; default (backg-mode isn't always set by XEmacs)
216 216 "LightBG"))))))
217 217 (unless (equal ipython-backup-of-py-python-command py-python-command)
218 218 (setq ipython-backup-of-py-python-command py-python-command))
219 219 (setq py-python-command ipython-command))
220 220
221 221
222 222 ;; MODIFY py-shell so that it loads the editing history
223 223 (defadvice py-shell (around py-shell-with-history)
224 224 "Add persistent command-history support (in
225 225 $PYTHONHISTORY (or \"~/.ipython/history\", if we use IPython)). Also, if
226 226 `py-shell-initial-switch-buffers' is nil, it only switches to *Python* if that
227 227 buffer already exists."
228 228 (if (comint-check-proc "*Python*")
229 229 ad-do-it
230 230 (setq comint-input-ring-file-name
231 231 (if (string-equal py-python-command ipython-command)
232 232 (concat (or (getenv "IPYTHONDIR") "~/.ipython") "/history")
233 233 (or (getenv "PYTHONHISTORY") "~/.python-history.py")))
234 234 (comint-read-input-ring t)
235 235 (let ((buf (current-buffer)))
236 236 ad-do-it
237 237 (unless py-shell-initial-switch-buffers
238 238 (switch-to-buffer-other-window buf)))))
239 239 (ad-activate 'py-shell)
240 240 ;; (defadvice py-execute-region (before py-execute-buffer-ensure-process)
241 241 ;; "HACK: test that ipython is already running before executing something.
242 242 ;; Doing this properly seems not worth the bother (unless people actually
243 243 ;; request it)."
244 244 ;; (unless (comint-check-proc "*Python*")
245 245 ;; (error "Sorry you have to first do M-x py-shell to send something to ipython.")))
246 246 ;; (ad-activate 'py-execute-region)
247 247
248 248 (defadvice py-execute-region (around py-execute-buffer-ensure-process)
249 249 "HACK: if `py-shell' is not active or ASYNC is explicitly desired, fall back
250 250 to python instead of ipython."
251 251 (let ((py-python-command (if (and (comint-check-proc "*Python*") (not async))
252 252 py-python-command
253 253 ipython-backup-of-py-python-command)))
254 254 ad-do-it))
255 255 (ad-activate 'py-execute-region)
256 256
257 257 (defun ipython-to-doctest (start end)
258 258 "Transform a cut-and-pasted bit from an IPython session into something that
259 259 looks like it came from a normal interactive python session, so that it can
260 260 be used in doctests. Example:
261 261
262 262
263 263 In [1]: import sys
264 264
265 265 In [2]: sys.stdout.write 'Hi!\n'
266 266 ------> sys.stdout.write ('Hi!\n')
267 267 Hi!
268 268
269 269 In [3]: 3 + 4
270 270 Out[3]: 7
271 271
272 272 gets converted to:
273 273
274 274 >>> import sys
275 275 >>> sys.stdout.write ('Hi!\n')
276 276 Hi!
277 277 >>> 3 + 4
278 278 7
279 279
280 280 "
281 281 (interactive "*r\n")
282 282 ;(message (format "###DEBUG s:%de:%d" start end))
283 283 (save-excursion
284 284 (save-match-data
285 285 ;; replace ``In [3]: bla`` with ``>>> bla`` and
286 286 ;; ``... : bla`` with ``... bla``
287 287 (goto-char start)
288 288 (while (re-search-forward ipython-de-input-prompt-regexp end t)
289 289 ;(message "finding 1")
290 290 (cond ((match-string 3) ;continued
291 291 (replace-match "... \\3" t nil))
292 292 (t
293 293 (replace-match ">>> \\1\\2" t nil))))
294 294 ;; replace ``
295 295 (goto-char start)
296 296 (while (re-search-forward ipython-de-output-prompt-regexp end t)
297 297 (replace-match "" t nil)))))
298 298
299 299 (defvar ipython-completion-command-string
300 300 "print ';'.join(__IP.Completer.all_completions('%s')) #PYTHON-MODE SILENT\n"
301 301 "The string send to ipython to query for all possible completions")
302 302
303 303
304 304 ;; xemacs doesn't have `comint-preoutput-filter-functions' so we'll try the
305 305 ;; following wonderful hack to work around this case
306 306 (if (featurep 'xemacs)
307 307 ;;xemacs
308 308 (defun ipython-complete ()
309 309 "Try to complete the python symbol before point. Only knows about the stuff
310 310 in the current *Python* session."
311 311 (interactive)
312 312 (let* ((ugly-return nil)
313 313 (sep ";")
314 314 (python-process (or (get-buffer-process (current-buffer))
315 315 ;XXX hack for .py buffers
316 316 (get-process py-which-bufname)))
317 317 ;; XXX currently we go backwards to find the beginning of an
318 318 ;; expression part; a more powerful approach in the future might be
319 319 ;; to let ipython have the complete line, so that context can be used
320 320 ;; to do things like filename completion etc.
321 321 (beg (save-excursion (skip-chars-backward "a-z0-9A-Z_." (point-at-bol))
322 322 (point)))
323 323 (end (point))
324 324 (pattern (buffer-substring-no-properties beg end))
325 325 (completions nil)
326 326 (completion-table nil)
327 327 completion
328 328 (comint-output-filter-functions
329 329 (append comint-output-filter-functions
330 330 '(ansi-color-filter-apply
331 331 (lambda (string)
332 332 ;(message (format "DEBUG filtering: %s" string))
333 333 (setq ugly-return (concat ugly-return string))
334 334 (delete-region comint-last-output-start
335 335 (process-mark (get-buffer-process (current-buffer)))))))))
336 336 ;(message (format "#DEBUG pattern: '%s'" pattern))
337 337 (process-send-string python-process
338 338 (format ipython-completion-command-string pattern))
339 339 (accept-process-output python-process)
340 340 ;(message (format "DEBUG return: %s" ugly-return))
341 341 (setq completions
342 342 (split-string (substring ugly-return 0 (position ?\n ugly-return)) sep))
343 343 (setq completion-table (loop for str in completions
344 344 collect (list str nil)))
345 345 (setq completion (try-completion pattern completion-table))
346 346 (cond ((eq completion t))
347 347 ((null completion)
348 348 (message "Can't find completion for \"%s\"" pattern)
349 349 (ding))
350 350 ((not (string= pattern completion))
351 351 (delete-region beg end)
352 352 (insert completion))
353 353 (t
354 354 (message "Making completion list...")
355 355 (with-output-to-temp-buffer "*Python Completions*"
356 356 (display-completion-list (all-completions pattern completion-table)))
357 357 (message "Making completion list...%s" "done")))))
358 358 ;; emacs
359 359 (defun ipython-complete ()
360 360 "Try to complete the python symbol before point. Only knows about the stuff
361 361 in the current *Python* session."
362 362 (interactive)
363 363 (let* ((ugly-return nil)
364 364 (sep ";")
365 365 (python-process (or (get-buffer-process (current-buffer))
366 366 ;XXX hack for .py buffers
367 367 (get-process py-which-bufname)))
368 368 ;; XXX currently we go backwards to find the beginning of an
369 369 ;; expression part; a more powerful approach in the future might be
370 370 ;; to let ipython have the complete line, so that context can be used
371 371 ;; to do things like filename completion etc.
372 372 (beg (save-excursion (skip-chars-backward "a-z0-9A-Z_." (point-at-bol))
373 373 (point)))
374 374 (end (point))
375 375 (pattern (buffer-substring-no-properties beg end))
376 376 (completions nil)
377 377 (completion-table nil)
378 378 completion
379 379 (comint-preoutput-filter-functions
380 380 (append comint-preoutput-filter-functions
381 381 '(ansi-color-filter-apply
382 382 (lambda (string)
383 383 (setq ugly-return (concat ugly-return string))
384 384 "")))))
385 385 (process-send-string python-process
386 386 (format ipython-completion-command-string pattern))
387 387 (accept-process-output python-process)
388 388 (setq completions
389 389 (split-string (substring ugly-return 0 (position ?\n ugly-return)) sep))
390 390 ;(message (format "DEBUG completions: %S" completions))
391 391 (setq completion-table (loop for str in completions
392 392 collect (list str nil)))
393 393 (setq completion (try-completion pattern completion-table))
394 394 (cond ((eq completion t))
395 395 ((null completion)
396 396 (message "Can't find completion for \"%s\"" pattern)
397 397 (ding))
398 398 ((not (string= pattern completion))
399 399 (delete-region beg end)
400 400 (insert completion))
401 401 (t
402 402 (message "Making completion list...")
403 403 (with-output-to-temp-buffer "*IPython Completions*"
404 404 (display-completion-list (all-completions pattern completion-table)))
405 405 (message "Making completion list...%s" "done")))))
406 406 )
407 407
408 ;;; autoindent support: patch sent in by Jin Liu <m.liu.jin@gmail.com>,
409 ;;; originally written by doxgen@newsmth.net
410 ;;; Minor modifications by fperez for xemacs compatibility.
411
412 (defvar ipython-autoindent t
413 "If non-nil, enable autoindent for IPython shell through python-mode.")
414
415 (defvar ipython-indenting-buffer-name "*IPython Indentation Calculation*"
416 "Temporary buffer for indenting multiline statement.")
417
418 (defun ipython-get-indenting-buffer ()
419 "Return a temporary buffer set in python-mode. Create one if necessary."
420 (let ((buf (get-buffer-create ipython-indenting-buffer-name)))
421 (set-buffer buf)
422 (unless (eq major-mode 'python-mode)
423 (python-mode))
424 buf))
425
426 (defvar ipython-indentation-string nil
427 "Indentation for the next line in a multiline statement.")
428
429 (defun ipython-send-and-indent ()
430 "Send the current line to IPython, and calculate the indentation for
431 the next line."
432 (interactive)
433 (if ipython-autoindent
434 (let ((line (buffer-substring (point-at-bol) (point)))
435 (after-prompt1)
436 (after-prompt2))
437 (save-excursion
438 (comint-bol t)
439 (if (looking-at py-shell-input-prompt-1-regexp)
440 (setq after-prompt1 t)
441 (setq after-prompt2 (looking-at py-shell-input-prompt-2-regexp)))
442 (with-current-buffer (ipython-get-indenting-buffer)
443 (when after-prompt1
444 (erase-buffer))
445 (when (or after-prompt1 after-prompt2)
446 (delete-region (point-at-bol) (point))
447 (insert line)
448 (newline-and-indent))))))
449 ;; send input line to ipython interpreter
450 (comint-send-input))
451
452 (defun ipython-indentation-hook (string)
453 "Insert indentation string if py-shell-input-prompt-2-regexp
454 matches last process output."
455 (let* ((start-marker (or comint-last-output-start
456 (point-min-marker)))
457 (end-marker (process-mark (get-buffer-process (current-buffer))))
458 (text (ansi-color-filter-apply (buffer-substring start-marker end-marker))))
459 (progn
460 ;; XXX if `text' matches both pattern, it MUST be the last prompt-2
461 (cond ((and (string-match "\n$" text) (string-match
462 py-shell-input-prompt-2-regexp text))
463 (with-current-buffer (ipython-get-indenting-buffer)
464 (erase-buffer)))
465 ;; still a prompt-2
466 ((string-match py-shell-input-prompt-2-regexp text)
467 (with-current-buffer (ipython-get-indenting-buffer)
468 (setq ipython-indentation-string
469 (buffer-substring (point-at-bol) (point))))
470 (unless (eq ipython-indentation-string nil)
471 (message "ipython-indentation-hook: %s#%s##" text
472 ipython-indentation-string))
473 (goto-char end-marker)
474 (insert ipython-indentation-string)))
475 (setq ipython-indentation-string nil))))
476
477 (add-hook 'py-shell-hook
478 (lambda ()
479 (add-hook 'comint-output-filter-functions
480 'ipython-indentation-hook)))
481
482 (define-key py-shell-map (kbd "RET") 'ipython-send-and-indent)
483 ;;; / end autoindent support
484
408 485 (provide 'ipython)
General Comments 0
You need to be logged in to leave comments. Login now