A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
ipython_view.py
Go to the documentation of this file.
1 """
2 Backend to the console plugin.
3 
4 @author: Eitan Isaacson
5 @organization: IBM Corporation
6 @copyright: Copyright (c) 2007 IBM Corporation
7 @license: BSD
8 
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}
12 """
13 # this file is a modified version of source code from the Accerciser project
14 # http://live.gnome.org/accerciser
15 
16 import gtk
17 import re
18 import sys
19 import os
20 import pango
21 from StringIO import StringIO
22 import IPython
23 
24 ansi_colors = {'0;30': 'Black',
25  '0;31': 'Red',
26  '0;32': 'Green',
27  '0;33': 'Brown',
28  '0;34': 'Blue',
29  '0;35': 'Purple',
30  '0;36': 'Cyan',
31  '0;37': 'LightGray',
32  '1;30': 'DarkGray',
33  '1;31': 'DarkRed',
34  '1;32': 'SeaGreen',
35  '1;33': 'Yellow',
36  '1;34': 'LightBlue',
37  '1;35': 'MediumPurple',
38  '1;36': 'LightCyan',
39  '1;37': 'White'}
40 
42  def __init__(self,argv=None,user_ns=None,user_global_ns=None,
43  cin=None, cout=None,cerr=None, input_func=None):
44  if input_func:
45  IPython.iplib.raw_input_original = input_func
46  if cin:
47  IPython.Shell.Term.cin = cin
48  if cout:
49  IPython.Shell.Term.cout = cout
50  if cerr:
51  IPython.Shell.Term.cerr = cerr
52 
53  if argv is None:
54  argv=[]
55 
56  # This is to get rid of the blockage that occurs during
57  # IPython.Shell.InteractiveShell.user_setup()
58  IPython.iplib.raw_input = lambda x: None
59 
60  self.term = IPython.genutils.IOTerm(cin=cin, cout=cout, cerr=cerr)
61  os.environ['TERM'] = 'dumb'
62  excepthook = sys.excepthook
63  self.IP = IPython.Shell.make_IPython(argv,user_ns=user_ns,
64  user_global_ns=user_global_ns,
65  embedded=True,
66  shell_class=IPython.Shell.InteractiveShell)
67  self.IP.system = lambda cmd: self.shell(self.IP.var_expand(cmd),
68  header='IPython system call: ',
69  verbose=self.IP.rc.system_verbose)
70  sys.excepthook = excepthook
71  self.iter_more = 0
72  self.history_level = 0
73  self.complete_sep = re.compile('[\s\{\}\[\]\(\)]')
74 
75  def execute(self):
76  self.history_level = 0
77  orig_stdout = sys.stdout
78  sys.stdout = IPython.Shell.Term.cout
79  try:
80  line = self.IP.raw_input(None, self.iter_more)
81  if self.IP.autoindent:
82  self.IP.readline_startup_hook(None)
83  except KeyboardInterrupt:
84  self.IP.write('\nKeyboardInterrupt\n')
85  self.IP.resetbuffer()
86  # keep cache in sync with the prompt counter:
87  self.IP.outputcache.prompt_count -= 1
88 
89  if self.IP.autoindent:
90  self.IP.indent_current_nsp = 0
91  self.iter_more = 0
92  except:
93  self.IP.showtraceback()
94  else:
95  self.iter_more = self.IP.push(line)
96  if (self.IP.SyntaxTB.last_syntax_error and
97  self.IP.rc.autoedit_syntax):
98  self.IP.edit_syntax_error()
99  if self.iter_more:
100  self.prompt = str(self.IP.outputcache.prompt2).strip()
101  if self.IP.autoindent:
102  self.IP.readline_startup_hook(self.IP.pre_readline)
103  else:
104  self.prompt = str(self.IP.outputcache.prompt1).strip()
105  sys.stdout = orig_stdout
106 
107  def historyBack(self):
108  self.history_level -= 1
109  return self._getHistory()
110 
111  def historyForward(self):
112  self.history_level += 1
113  return self._getHistory()
114 
115  def _getHistory(self):
116  try:
117  rv = self.IP.user_ns['In'][self.history_level].strip('\n')
118  except IndexError:
119  self.history_level = 0
120  rv = ''
121  return rv
122 
123  def updateNamespace(self, ns_dict):
124  self.IP.user_ns.update(ns_dict)
125 
126  def complete(self, line):
127  split_line = self.complete_sep.split(line)
128  possibilities = self.IP.complete(split_line[-1])
129  if possibilities:
130  common_prefix = reduce(self._commonPrefix, possibilities)
131  completed = line[:-len(split_line[-1])]+common_prefix
132  else:
133  completed = line
134  return completed, possibilities
135 
136  def _commonPrefix(self, str1, str2):
137  for i in range(len(str1)):
138  if not str2.startswith(str1[:i+1]):
139  return str1[:i]
140  return str1
141 
142  def shell(self, cmd,verbose=0,debug=0,header=''):
143  stat = 0
144  if verbose or debug: print header+cmd
145  # flush stdout so we don't mangle python's buffering
146  if not debug:
147  input, output = os.popen4(cmd)
148  print output.read()
149  output.close()
150  input.close()
151 
152 class ConsoleView(gtk.TextView):
153  def __init__(self):
154  gtk.TextView.__init__(self)
155  self.modify_font(pango.FontDescription('Mono'))
156  self.set_cursor_visible(True)
157  self.text_buffer = self.get_buffer()
158  self.mark = self.text_buffer.create_mark('scroll_mark',
159  self.text_buffer.get_end_iter(),
160  False)
161  for code in ansi_colors:
162  self.text_buffer.create_tag(code,
163  foreground=ansi_colors[code],
164  weight=700)
165  self.text_buffer.create_tag('0')
166  self.text_buffer.create_tag('notouch', editable=False)
167  self.color_pat = re.compile('\x01?\x1b\[(.*?)m\x02?')
168  self.line_start = \
169  self.text_buffer.create_mark('line_start',
170  self.text_buffer.get_end_iter(), True
171  )
172  self.connect('key-press-event', self._onKeypress)
174 
175  def write(self, text, editable=False):
176  segments = self.color_pat.split(text)
177  segment = segments.pop(0)
178  start_mark = self.text_buffer.create_mark(None,
179  self.text_buffer.get_end_iter(),
180  True)
181  self.text_buffer.insert(self.text_buffer.get_end_iter(), segment)
182 
183  if segments:
184  ansi_tags = self.color_pat.findall(text)
185  for tag in ansi_tags:
186  i = segments.index(tag)
187  self.text_buffer.insert_with_tags_by_name(self.text_buffer.get_end_iter(),
188  segments[i+1], tag)
189  segments.pop(i)
190  if not editable:
191  self.text_buffer.apply_tag_by_name('notouch',
192  self.text_buffer.get_iter_at_mark(start_mark),
193  self.text_buffer.get_end_iter())
194  self.text_buffer.delete_mark(start_mark)
195  self.scroll_mark_onscreen(self.mark)
196 
197  def showPrompt(self, prompt):
198  self.write(prompt)
199  self.text_buffer.move_mark(self.line_start,self.text_buffer.get_end_iter())
200 
201  def changeLine(self, text):
202  iter = self.text_buffer.get_iter_at_mark(self.line_start)
203  iter.forward_to_line_end()
204  self.text_buffer.delete(self.text_buffer.get_iter_at_mark(self.line_start), iter)
205  self.write(text, True)
206 
207  def getCurrentLine(self):
208  rv = self.text_buffer.get_slice(self.text_buffer.get_iter_at_mark(self.line_start),
209  self.text_buffer.get_end_iter(), False)
210  return rv
211 
212  def showReturned(self, text):
213  iter = self.text_buffer.get_iter_at_mark(self.line_start)
214  iter.forward_to_line_end()
215  self.text_buffer.apply_tag_by_name('notouch',
216  self.text_buffer.get_iter_at_mark(self.line_start),
217  iter)
218  self.write('\n'+text)
219  if text:
220  self.write('\n')
221  self.showPrompt(self.prompt)
222  self.text_buffer.move_mark(self.line_start,self.text_buffer.get_end_iter())
223  self.text_buffer.place_cursor(self.text_buffer.get_end_iter())
224 
225  def _onKeypress(self, obj, event):
226  if not event.string:
227  return
228  insert_mark = self.text_buffer.get_insert()
229  insert_iter = self.text_buffer.get_iter_at_mark(insert_mark)
230  selection_mark = self.text_buffer.get_selection_bound()
231  selection_iter = self.text_buffer.get_iter_at_mark(selection_mark)
232  start_iter = self.text_buffer.get_iter_at_mark(self.line_start)
233  if start_iter.compare(insert_iter) <= 0 and \
234  start_iter.compare(selection_iter) <= 0:
235  return
236  elif start_iter.compare(insert_iter) > 0 and \
237  start_iter.compare(selection_iter) > 0:
238  self.text_buffer.place_cursor(start_iter)
239  elif insert_iter.compare(selection_iter) < 0:
240  self.text_buffer.move_mark(insert_mark, start_iter)
241  elif insert_iter.compare(selection_iter) > 0:
242  self.text_buffer.move_mark(selection_mark, start_iter)
243 
244 
246  def __init__(self):
247  ConsoleView.__init__(self)
248  self.cout = StringIO()
249  IterableIPShell.__init__(self, cout=self.cout,cerr=self.cout,
250  input_func=self.raw_input)
251  self.connect('key_press_event', self.keyPress)
252  self.execute()
253  self.cout.truncate(0)
254  self.showPrompt(self.prompt)
255  self.interrupt = False
256 
257  def raw_input(self, prompt=''):
258  if self.interrupt:
259  self.interrupt = False
260  raise KeyboardInterrupt
261  return self.getCurrentLine()
262 
263  def keyPress(self, widget, event):
264  if event.state & gtk.gdk.CONTROL_MASK and event.keyval == 99:
265  self.interrupt = True
266  self._processLine()
267  return True
268  elif event.keyval == gtk.keysyms.Return:
269  self._processLine()
270  return True
271  elif event.keyval == gtk.keysyms.Up:
272  self.changeLine(self.historyBack())
273  return True
274  elif event.keyval == gtk.keysyms.Down:
275  self.changeLine(self.historyForward())
276  return True
277  elif event.keyval == gtk.keysyms.Tab:
278  if not self.getCurrentLine().strip():
279  return False
280  completed, possibilities = self.complete(self.getCurrentLine())
281  if len(possibilities) > 1:
282  slice = self.getCurrentLine()
283  self.write('\n')
284  for symbol in possibilities:
285  self.write(symbol+'\n')
286  self.showPrompt(self.prompt)
287  self.changeLine(completed or slice)
288  return True
289 
290  def _processLine(self):
291  self.history_pos = 0
292  self.execute()
293  rv = self.cout.getvalue()
294  if rv: rv = rv.strip('\n')
295  self.showReturned(rv)
296  self.cout.truncate(0)