2 Backend to the console plugin.
4 @author: Eitan Isaacson
5 @organization: IBM Corporation
6 @copyright: Copyright (c) 2007 IBM Corporation
9 All rights reserved. This program and the accompanying materials are made
10 available under the terms of the BSD which accompanies this distribution, and
11 is available at U{http://www.opensource.org/licenses/bsd-license.php}
21 from StringIO
import StringIO
24 from pkg_resources
import parse_version
32 def __init__(self,argv=None,user_ns=None,user_global_ns=None,
33 cin=
None, cout=
None,cerr=
None, input_func=
None):
37 @param argv: Command line options for IPython
39 @param user_ns: User namespace.
40 @type user_ns: dictionary
41 @param user_global_ns: User global namespace.
42 @type user_global_ns: dictionary.
43 @param cin: Console standard input.
45 @param cout: Console standard output.
47 @param cerr: Console standard error.
49 @param input_func: Replacement for builtin raw_input()
50 @type input_func: function
54 if parse_version(IPython.release.version) >= parse_version(
"1.2.1"):
55 IPython.terminal.interactiveshell.raw_input_original = input_func
57 IPython.frontend.terminal.interactiveshell.raw_input_original = input_func
59 io.stdin = io.IOStream(cin)
61 io.stdout = io.IOStream(cout)
63 io.stderr = io.IOStream(cerr)
68 io.raw_input =
lambda x:
None
70 os.environ[
'TERM'] =
'dumb'
71 excepthook = sys.excepthook
73 from IPython.config.loader
import Config
75 cfg.InteractiveShell.colors =
"Linux"
80 old_stdout, old_stderr = sys.stdout, sys.stderr
81 sys.stdout, sys.stderr = io.stdout.stream, io.stderr.stream
85 if parse_version(IPython.release.version) >= parse_version(
"1.2.1"):
86 self.
IP = IPython.terminal.embed.InteractiveShellEmbed.instance(\
87 config=cfg, user_ns=user_ns)
89 self.
IP = IPython.frontend.terminal.embed.InteractiveShellEmbed.instance(\
90 config=cfg, user_ns=user_ns)
92 sys.stdout, sys.stderr = old_stdout, old_stderr
94 self.IP.system =
lambda cmd: self.
shell(self.IP.var_expand(cmd),
95 header=
'IPython system call: ')
100 self.IP.raw_input = input_func
101 sys.excepthook = excepthook
107 self.IP.readline_startup_hook(self.IP.pre_readline)
114 Update self.IP namespace for autocompletion with sys.modules
116 for k, v
in list(sys.modules.items()):
118 self.IP.user_ns.update({k:v})
122 Executes the current line provided by the shell object.
125 orig_stdout = sys.stdout
126 sys.stdout = IPython.utils.io.stdout
128 orig_stdin = sys.stdin
129 sys.stdin = IPython.utils.io.stdin;
132 self.IP.hooks.pre_prompt_hook()
137 self.IP.showtraceback()
138 if self.IP.autoindent:
139 self.IP.rl_do_indent =
True
142 line = self.IP.raw_input(self.
prompt)
143 except KeyboardInterrupt:
144 self.IP.write(
'\nKeyboardInterrupt\n')
145 self.IP.input_splitter.reset()
147 self.IP.showtraceback()
149 self.IP.input_splitter.push(line)
150 self.
iter_more = self.IP.input_splitter.push_accepts_more()
152 if (self.IP.SyntaxTB.last_syntax_error
and
153 self.IP.autoedit_syntax):
154 self.IP.edit_syntax_error()
156 if parse_version(IPython.release.version) >= parse_version(
"2.0.0-dev"):
157 source_raw = self.IP.input_splitter.raw_reset()
159 source_raw = self.IP.input_splitter.source_raw_reset()[1]
160 self.IP.run_cell(source_raw, store_history=
True)
161 self.IP.rl_do_indent =
False
165 self.IP.rl_do_indent =
True
168 sys.stdout = orig_stdout
169 sys.stdin = orig_stdin
173 Generate prompt depending on is_continuation value
175 @param is_continuation
176 @type is_continuation: boolean
178 @return: The prompt string representation
185 ver = IPython.__version__
187 prompt = self.IP.hooks.generate_prompt(is_continuation)
190 prompt = self.IP.prompt_manager.render(
'in2')
192 prompt = self.IP.prompt_manager.render(
'in')
199 Provides one history command back.
201 @return: The command string.
211 Provides one history command forward.
213 @return: The command string.
222 Get's the command string of the current history level.
224 @return: Historic command string.
235 Add the current dictionary to the shell namespace.
237 @param ns_dict: A dictionary of symbol-values.
238 @type ns_dict: dictionary
240 self.IP.user_ns.update(ns_dict)
244 Returns an auto completed line and/or posibilities for completion.
246 @param line: Given line so far.
249 @return: Line completed as for as possible,
250 and possible further completions.
253 split_line = self.complete_sep.split(line)
255 possibilities = self.IP.complete(split_line[-1])
258 possibilities = [
'', []]
260 def _commonPrefix(str1, str2):
262 Reduction function. returns common prefix of two given strings.
264 @param str1: First string.
266 @param str2: Second string
269 @return: Common prefix to both strings.
272 for i
in range(len(str1)):
273 if not str2.startswith(str1[:i+1]):
277 common_prefix = reduce(_commonPrefix, possibilities[1])
or line[-1]
278 completed = line[:-len(split_line[-1])]+common_prefix
283 return completed, possibilities[1]
286 def shell(self, cmd,verbose=0,debug=0,header=''):
288 Replacement method to allow shell commands without them blocking.
290 @param cmd: Shell command to execute.
292 @param verbose: Verbosity
293 @type verbose: integer
294 @param debug: Debug level
296 @param header: Header to be printed before output
300 if verbose
or debug:
print header+cmd
303 input, output = os.popen4(cmd)
310 Specialized text view for console-like workflow.
312 @cvar ANSI_COLORS: Mapping of terminal colors to X11 names.
313 @type ANSI_COLORS: dictionary
315 @ivar text_buffer: Widget's text buffer.
316 @type text_buffer: gtk.TextBuffer
317 @ivar color_pat: Regex of terminal color pattern
318 @type color_pat: _sre.SRE_Pattern
319 @ivar mark: Scroll mark for automatic scrolling on input.
320 @type mark: gtk.TextMark
321 @ivar line_start: Start of command line mark.
322 @type line_start: gtk.TextMark
324 ANSI_COLORS = {
'0;30':
'Black',
'0;31':
'Red',
325 '0;32':
'Green',
'0;33':
'Brown',
326 '0;34':
'Blue',
'0;35':
'Purple',
327 '0;36':
'Cyan',
'0;37':
'LightGray',
328 '1;30':
'DarkGray',
'1;31':
'DarkRed',
329 '1;32':
'SeaGreen',
'1;33':
'Yellow',
330 '1;34':
'LightBlue',
'1;35':
'MediumPurple',
331 '1;36':
'LightCyan',
'1;37':
'White'}
335 Initialize console view.
337 gtk.TextView.__init__(self)
338 self.modify_font(pango.FontDescription(
'Mono'))
339 self.set_cursor_visible(
True)
341 self.
mark = self.text_buffer.create_mark(
'scroll_mark',
342 self.text_buffer.get_end_iter(),
345 self.text_buffer.create_tag(code,
348 self.text_buffer.create_tag(
'0')
349 self.text_buffer.create_tag(
'notouch', editable=
False)
352 self.text_buffer.create_mark(
'line_start',
353 self.text_buffer.get_end_iter(),
True)
354 self.connect(
'key-press-event', self.
onKeyPress)
356 def write(self, text, editable=False):
357 gobject.idle_add(self.
_write, text, editable)
361 Write given text to buffer.
363 @param text: Text to append.
365 @param editable: If true, added text is editable.
366 @type editable: boolean
368 segments = self.color_pat.split(text)
369 segment = segments.pop(0)
370 start_mark = self.text_buffer.create_mark(
None,
371 self.text_buffer.get_end_iter(),
373 self.text_buffer.insert(self.text_buffer.get_end_iter(), segment)
376 ansi_tags = self.color_pat.findall(text)
377 for tag
in ansi_tags:
378 i = segments.index(tag)
379 self.text_buffer.insert_with_tags_by_name(self.text_buffer.get_end_iter(),
380 segments[i+1], str(tag))
383 self.text_buffer.apply_tag_by_name(
'notouch',
384 self.text_buffer.get_iter_at_mark(start_mark),
385 self.text_buffer.get_end_iter())
386 self.text_buffer.delete_mark(start_mark)
387 self.scroll_mark_onscreen(self.
mark)
394 Prints prompt at start of line.
396 @param prompt: Prompt to print.
401 self.text_buffer.get_end_iter())
408 Replace currently entered command line with given text.
410 @param text: Text to use as replacement.
413 iter = self.text_buffer.get_iter_at_mark(self.
line_start)
414 iter.forward_to_line_end()
415 self.text_buffer.delete(self.text_buffer.get_iter_at_mark(self.
line_start), iter)
420 Get text in current command line.
422 @return: Text of current command line.
425 rv = self.text_buffer.get_slice(
426 self.text_buffer.get_iter_at_mark(self.
line_start),
427 self.text_buffer.get_end_iter(),
False)
435 Show returned text from last command and print new prompt.
437 @param text: Text to show.
440 iter = self.text_buffer.get_iter_at_mark(self.
line_start)
441 iter.forward_to_line_end()
442 self.text_buffer.apply_tag_by_name(
444 self.text_buffer.get_iter_at_mark(self.
line_start),
450 self.text_buffer.move_mark(self.
line_start,self.text_buffer.get_end_iter())
451 self.text_buffer.place_cursor(self.text_buffer.get_end_iter())
453 if self.IP.rl_do_indent:
454 indentation = self.IP.input_splitter.indent_spaces *
' '
455 self.text_buffer.insert_at_cursor(indentation)
459 Key press callback used for correcting behavior for console-like
460 interfaces. For example 'home' should go to prompt, not to begining of
463 @param widget: Widget that key press accored in.
464 @type widget: gtk.Widget
465 @param event: Event object
466 @type event: gtk.gdk.Event
468 @return: Return True if event should not trickle.
471 insert_mark = self.text_buffer.get_insert()
472 insert_iter = self.text_buffer.get_iter_at_mark(insert_mark)
473 selection_mark = self.text_buffer.get_selection_bound()
474 selection_iter = self.text_buffer.get_iter_at_mark(selection_mark)
475 start_iter = self.text_buffer.get_iter_at_mark(self.
line_start)
476 if event.keyval == gtk.keysyms.Home:
477 if event.state & gtk.gdk.CONTROL_MASK
or event.state & gtk.gdk.MOD1_MASK:
479 elif event.state & gtk.gdk.SHIFT_MASK:
480 self.text_buffer.move_mark(insert_mark, start_iter)
483 self.text_buffer.place_cursor(start_iter)
485 elif event.keyval == gtk.keysyms.Left:
486 insert_iter.backward_cursor_position()
487 if not insert_iter.editable(
True):
489 elif not event.string:
491 elif start_iter.compare(insert_iter) <= 0
and \
492 start_iter.compare(selection_iter) <= 0:
494 elif start_iter.compare(insert_iter) > 0
and \
495 start_iter.compare(selection_iter) > 0:
496 self.text_buffer.place_cursor(start_iter)
497 elif insert_iter.compare(selection_iter) < 0:
498 self.text_buffer.move_mark(insert_mark, start_iter)
499 elif insert_iter.compare(selection_iter) > 0:
500 self.text_buffer.move_mark(selection_mark, start_iter)
506 For some reason we can't extend onKeyPress directly (bug #500900).
510 class IPythonView(ConsoleView, IterableIPShell):
512 Sub-class of both modified IPython shell and L{ConsoleView} this makes
513 a GTK+ IPython console.
517 Initialize. Redirect I/O to console.
519 ConsoleView.__init__(self)
521 IterableIPShell.__init__(self, cout=self.
cout,cerr=self.
cout,
526 self.cout.truncate(0)
531 Custom raw_input() replacement. Get's current line from console buffer.
533 @param prompt: Prompt to print. Here for compatability as replacement.
536 @return: The current command line text.
541 raise KeyboardInterrupt
546 Key press callback with plenty of shell goodness, like history,
547 autocompletions, etc.
549 @param widget: Widget that key press occured in.
550 @type widget: gtk.Widget
551 @param event: Event object.
552 @type event: gtk.gdk.Event
554 @return: True if event should not trickle.
558 if event.state & gtk.gdk.CONTROL_MASK
and event.keyval == 99:
562 elif event.keyval == gtk.keysyms.Return:
565 elif event.keyval == gtk.keysyms.Up:
568 elif event.keyval == gtk.keysyms.Down:
571 elif event.keyval == gtk.keysyms.Tab:
575 if len(possibilities) > 1:
578 for symbol
in possibilities:
579 self.
write(symbol+
'\n')
586 Process current command line.
590 rv = self.cout.getvalue()
591 if rv: rv = rv.strip(
'\n')
593 self.cout.truncate(0)
596 if __name__ ==
"__main__":
597 window = gtk.Window()
598 window.set_default_size(640, 320)
599 window.connect(
'delete-event',
lambda x, y: gtk.main_quit())