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}
16 from __future__
import print_function
21 from gi.repository
import Pango
22 from StringIO
import StringIO
25 from pkg_resources
import parse_version
75 def __init__(self,argv=None,user_ns=None,user_global_ns=None,
76 cin=None, cout=None,cerr=None, input_func=None):
79 @param self: this object
80 @param argv: Command line options for IPython
81 @param user_ns: User namespace.
82 @param user_global_ns: User global namespace.
83 @param cin: Console standard input.
84 @param cout: Console standard output.
85 @param cerr: Console standard error.
86 @param input_func: Replacement for builtin raw_input()
91 if parse_version(IPython.release.version) >= parse_version(
"1.2.1"):
92 IPython.terminal.interactiveshell.raw_input_original = input_func
94 IPython.frontend.terminal.interactiveshell.raw_input_original = input_func
96 io.stdin = io.IOStream(cin)
98 io.stdout = io.IOStream(cout)
100 io.stderr = io.IOStream(cerr)
105 io.raw_input =
lambda x:
None
107 os.environ[
'TERM'] =
'dumb'
108 excepthook = sys.excepthook
110 from IPython.config.loader
import Config
112 cfg.InteractiveShell.colors =
"Linux"
117 old_stdout, old_stderr = sys.stdout, sys.stderr
118 sys.stdout, sys.stderr = io.stdout.stream, io.stderr.stream
122 if parse_version(IPython.release.version) >= parse_version(
"1.2.1"):
123 self.
IP = IPython.terminal.embed.InteractiveShellEmbed.instance(\
124 config=cfg, user_ns=user_ns)
126 self.
IP = IPython.frontend.terminal.embed.InteractiveShellEmbed.instance(\
127 config=cfg, user_ns=user_ns)
129 sys.stdout, sys.stderr = old_stdout, old_stderr
131 self.
IP.system =
lambda cmd: self.
shell(self.
IP.var_expand(cmd),
132 header=
'IPython system call: ')
137 self.
IP.raw_input = input_func
138 sys.excepthook = excepthook
144 self.
IP.readline_startup_hook(self.
IP.pre_readline)
151 Update self.IP namespace for autocompletion with sys.modules
153 for k, v
in list(sys.modules.items()):
155 self.
IP.user_ns.update({k:v})
159 Executes the current line provided by the shell object.
162 orig_stdout = sys.stdout
163 sys.stdout = IPython.utils.io.stdout
165 orig_stdin = sys.stdin
166 sys.stdin = IPython.utils.io.stdin;
169 self.
IP.hooks.pre_prompt_hook()
174 self.
IP.showtraceback()
175 if self.
IP.autoindent:
176 self.
IP.rl_do_indent =
True
179 line = self.
IP.raw_input(self.
prompt)
180 except KeyboardInterrupt:
181 self.
IP.write(
'\nKeyboardInterrupt\n')
182 self.
IP.input_splitter.reset()
184 self.
IP.showtraceback()
186 self.
IP.input_splitter.push(line)
187 self.
iter_more = self.
IP.input_splitter.push_accepts_more()
189 if (self.
IP.SyntaxTB.last_syntax_error
and
190 self.
IP.autoedit_syntax):
191 self.
IP.edit_syntax_error()
193 if parse_version(IPython.release.version) >= parse_version(
"2.0.0-dev"):
194 source_raw = self.
IP.input_splitter.raw_reset()
196 source_raw = self.
IP.input_splitter.source_raw_reset()[1]
197 self.
IP.run_cell(source_raw, store_history=
True)
198 self.
IP.rl_do_indent =
False
202 self.
IP.rl_do_indent =
True
205 sys.stdout = orig_stdout
206 sys.stdin = orig_stdin
210 Generate prompt depending on is_continuation value
212 @param is_continuation
213 @return: The prompt string representation
219 ver = IPython.__version__
221 prompt = self.
IP.hooks.generate_prompt(is_continuation)
224 prompt = self.
IP.prompt_manager.render(
'in2')
226 prompt = self.
IP.prompt_manager.render(
'in')
233 Provides one history command back.
235 @param self this object
236 @return: The command string.
245 Provides one history command forward.
247 @param self this object
248 @return: The command string.
256 Gets the command string of the current history level.
258 @param self this object
259 @return: Historic command string.
269 Add the current dictionary to the shell namespace.
271 @param ns_dict: A dictionary of symbol-values.
274 self.
IP.user_ns.update(ns_dict)
278 Returns an auto completed line and/or possibilities for completion.
280 @param line: Given line so far.
281 @return: Line completed as for as possible, and possible further completions.
285 possibilities = self.
IP.
complete(split_line[-1])
288 possibilities = [
'', []]
290 def _commonPrefix(str1, str2):
292 Reduction function. returns common prefix of two given strings.
294 @param str1: First string.
295 @param str2: Second string
296 @return: Common prefix to both strings.
298 for i
in range(len(str1)):
299 if not str2.startswith(str1[:i+1]):
303 common_prefix = reduce(_commonPrefix, possibilities[1])
or line[-1]
304 completed = line[:-len(split_line[-1])]+common_prefix
309 return completed, possibilities[1]
312 def shell(self, cmd,verbose=0,debug=0,header=''):
314 Replacement method to allow shell commands without them blocking.
316 @param cmd: Shell command to execute.
317 @param verbose: Verbosity
318 @param debug: Debug level
319 @param header: Header to be printed before output
323 if verbose
or debug: print(header+cmd)
326 input, output = os.popen4(cmd)
344 Specialized text view for console-like workflow.
346 @cvar ANSI_COLORS: Mapping of terminal colors to X11 names.
347 @type ANSI_COLORS: dictionary
349 @ivar text_buffer: Widget's text buffer.
350 @type text_buffer: Gtk.TextBuffer
351 @ivar color_pat: Regex of terminal color pattern
352 @type color_pat: _sre.SRE_Pattern
353 @ivar mark: Scroll mark for automatic scrolling on input.
354 @type mark: Gtk.TextMark
355 @ivar line_start: Start of command line mark.
356 @type line_start: Gtk.TextMark
358 ANSI_COLORS = {
'0;30':
'Black',
'0;31':
'Red',
359 '0;32':
'Green',
'0;33':
'Brown',
360 '0;34':
'Blue',
'0;35':
'Purple',
361 '0;36':
'Cyan',
'0;37':
'LightGray',
362 '1;30':
'DarkGray',
'1;31':
'DarkRed',
363 '1;32':
'SeaGreen',
'1;33':
'Yellow',
364 '1;34':
'LightBlue',
'1;35':
'MediumPurple',
365 '1;36':
'LightCyan',
'1;37':
'White'}
369 Initialize console view.
371 GObject.GObject.__init__(self)
372 self.modify_font(Pango.FontDescription(
'Mono'))
373 self.set_cursor_visible(
True)
383 self.
text_buffer.create_tag(
'notouch', editable=
False)
384 self.
color_pat = re.compile(
'\x01?\x1b\[(.*?)m\x02?')
388 self.connect(
'key-press-event', self.
onKeyPress)
390 def write(self, text, editable=False):
392 Write given text to buffer.
394 @param text: Text to append.
395 @param editable: If true, added text is editable.
398 GObject.idle_add(self.
_write, text, editable)
402 Write given text to buffer.
404 @param text: Text to append.
405 @param editable: If true, added text is editable.
409 segment = segments.pop(0)
417 for tag
in ansi_tags:
418 i = segments.index(tag)
420 segments[i+1], str(tag))
427 self.scroll_mark_onscreen(self.
mark)
431 Prints prompt at start of line.
433 @param prompt: Prompt to print.
440 Prints prompt at start of line.
442 @param prompt: Prompt to print.
451 Replace currently entered command line with given text.
453 @param text: Text to use as replacement.
460 Replace currently entered command line with given text.
462 @param text: Text to use as replacement.
466 iter.forward_to_line_end()
472 Get text in current command line.
474 @return Text of current command line.
483 Show returned text from last command and print new prompt.
485 @param text: Text to show.
492 Show returned text from last command and print new prompt.
494 @param text: Text to show.
498 iter.forward_to_line_end()
510 if self.IP.rl_do_indent:
511 indentation = self.IP.input_splitter.indent_spaces *
' '
516 Key press callback used for correcting behavior for console-like
517 interfaces. For example 'home' should go to prompt, not to beginning of
520 @param widget: Widget that key press accored in.
521 @param event: Event object
522 @return Return True if event should not trickle.
525 insert_iter = self.
text_buffer.get_iter_at_mark(insert_mark)
526 selection_mark = self.
text_buffer.get_selection_bound()
527 selection_iter = self.
text_buffer.get_iter_at_mark(selection_mark)
529 if event.keyval == Gdk.KEY_Home:
530 if event.get_state() & Gdk.ModifierType.CONTROL_MASK
or event.get_state() & Gdk.ModifierType.MOD1_MASK:
532 elif event.get_state() & Gdk.ModifierType.SHIFT_MASK:
533 self.
text_buffer.move_mark(insert_mark, start_iter)
538 elif event.keyval == Gdk.KEY_Left:
539 insert_iter.backward_cursor_position()
540 if not insert_iter.editable(
True):
542 elif not event.string:
544 elif start_iter.compare(insert_iter) <= 0
and \
545 start_iter.compare(selection_iter) <= 0:
547 elif start_iter.compare(insert_iter) > 0
and \
548 start_iter.compare(selection_iter) > 0:
550 elif insert_iter.compare(selection_iter) < 0:
551 self.
text_buffer.move_mark(insert_mark, start_iter)
552 elif insert_iter.compare(selection_iter) > 0:
553 self.
text_buffer.move_mark(selection_mark, start_iter)
559 For some reason we can't extend onKeyPress directly (bug #500900).
560 @param event key press
566 class IPythonView(ConsoleView, IterableIPShell):
582 Sub-class of both modified IPython shell and L{ConsoleView} this makes
583 a GTK+ IPython console.
587 Initialize. Redirect I/O to console.
589 ConsoleView.__init__(self)
590 self.
cout = StringIO()
591 IterableIPShell.__init__(self, cout=self.
cout,cerr=self.
cout,
601 Custom raw_input() replacement. Gets current line from console buffer.
603 @param prompt: Prompt to print. Here for compatibility as replacement.
604 @return The current command line text.
608 raise KeyboardInterrupt
613 Key press callback with plenty of shell goodness, like history,
614 autocompletions, etc.
616 @param event: Event object.
617 @return True if event should not trickle.
620 if event.get_state() & Gdk.ModifierType.CONTROL_MASK
and event.keyval == 99:
624 elif event.keyval == Gdk.KEY_Return:
627 elif event.keyval == Gdk.KEY_Up:
630 elif event.keyval == Gdk.KEY_Down:
633 elif event.keyval == Gdk.KEY_Tab:
637 if len(possibilities) > 1:
640 for symbol
in possibilities:
641 self.
write(symbol+
'\n')
648 Process current command line.
653 rv = self.
cout.getvalue()
654 if rv: rv = rv.strip(
'\n')
656 self.
cout.truncate(0)
659 if __name__ ==
"__main__":
660 window = Gtk.Window()
661 window.set_default_size(640, 320)
662 window.connect(
'delete-event',
lambda x, y: Gtk.main_quit())