View | Details | Raw Unified | Return to bug 1981
Collapse All | Expand All

(-)a/src/visualizer/visualizer/core.py (-9 / +9 lines)
 Lines 1124-1130    Link Here 
1124
        # acquire and release the simulation lock around each code
1124
        # acquire and release the simulation lock around each code
1125
        # that is executed.
1125
        # that is executed.
1126
1126
1127
        original_runcode = __IPYTHON__.runcode
1127
        original_runcode = self.ipython.runcode
1128
        def runcode(ip, *args):
1128
        def runcode(ip, *args):
1129
            #print "lock"
1129
            #print "lock"
1130
            self.simulation.lock.acquire()
1130
            self.simulation.lock.acquire()
 Lines 1134-1140    Link Here 
1134
                #print "unlock"
1134
                #print "unlock"
1135
                self.simulation.lock.release()
1135
                self.simulation.lock.release()
1136
        import types
1136
        import types
1137
        __IPYTHON__.runcode = types.MethodType(runcode, __IPYTHON__)                
1137
        self.ipython.runcode = types.MethodType(runcode, self.ipython)                
1138
1138
1139
    def autoscale_view(self):
1139
    def autoscale_view(self):
1140
        if not self.nodes:
1140
        if not self.nodes:
 Lines 1285-1291    Link Here 
1285
                    ns3_node = ns.network.NodeList.GetNode(self.selected_node.node_index)
1285
                    ns3_node = ns.network.NodeList.GetNode(self.selected_node.node_index)
1286
                finally:
1286
                finally:
1287
                    self.simulation.lock.release()
1287
                    self.simulation.lock.release()
1288
            __IPYTHON__.user_ns['selected_node'] = ns3_node
1288
            self.ipython.updateNamespace({'selected_node': ns3_node})
1289
1289
1290
1290
1291
    def select_node(self, node):
1291
    def select_node(self, node):
 Lines 1439-1456    Link Here 
1439
        self.shell_window.set_resizable(True)
1439
        self.shell_window.set_resizable(True)
1440
        scrolled_window = gtk.ScrolledWindow()
1440
        scrolled_window = gtk.ScrolledWindow()
1441
        scrolled_window.set_policy(gtk.POLICY_AUTOMATIC,gtk.POLICY_AUTOMATIC)
1441
        scrolled_window.set_policy(gtk.POLICY_AUTOMATIC,gtk.POLICY_AUTOMATIC)
1442
        ipython = ipython_view.IPythonView()
1442
        self.ipython = ipython_view.IPythonView()
1443
        ipython.modify_font(pango.FontDescription(SHELL_FONT))
1443
        self.ipython.modify_font(pango.FontDescription(SHELL_FONT))
1444
        ipython.set_wrap_mode(gtk.WRAP_CHAR)
1444
        self.ipython.set_wrap_mode(gtk.WRAP_CHAR)
1445
        ipython.show()
1445
        self.ipython.show()
1446
        scrolled_window.add(ipython)
1446
        scrolled_window.add(self.ipython)
1447
        scrolled_window.show()
1447
        scrolled_window.show()
1448
        self.shell_window.add(scrolled_window)
1448
        self.shell_window.add(scrolled_window)
1449
        self.shell_window.show()
1449
        self.shell_window.show()
1450
        self.shell_window.connect('destroy', self._on_shell_window_destroy)
1450
        self.shell_window.connect('destroy', self._on_shell_window_destroy)
1451
1451
1452
        self._update_ipython_selected_node()
1452
        self._update_ipython_selected_node()
1453
        __IPYTHON__.user_ns['viz'] = self
1453
        self.ipython.updateNamespace({'viz': self})
1454
1454
1455
1455
1456
    def _on_shell_window_destroy(self, window):
1456
    def _on_shell_window_destroy(self, window):
(-)a/src/visualizer/visualizer/ipython_view.py (-96 / +403 lines)
 Lines 13-19    Link Here 
13
# this file is a modified version of source code from the Accerciser project
13
# this file is a modified version of source code from the Accerciser project
14
# http://live.gnome.org/accerciser
14
# http://live.gnome.org/accerciser
15
15
16
import gtk
16
import gtk, gobject
17
import re
17
import re
18
import sys
18
import sys
19
import os
19
import os
 Lines 21-145    Link Here 
21
from StringIO import StringIO
21
from StringIO import StringIO
22
import IPython
22
import IPython
23
23
24
ansi_colors =  {'0;30': 'Black',
24
from pkg_resources import parse_version
25
                '0;31': 'Red',
25
26
                '0;32': 'Green',
26
try:
27
                '0;33': 'Brown',
27
  import IPython
28
                '0;34': 'Blue',
28
except ImportError:
29
                '0;35': 'Purple',
29
  IPython = None
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
30
41
class IterableIPShell:
31
class IterableIPShell:
42
  def __init__(self,argv=None,user_ns=None,user_global_ns=None,
32
  def __init__(self,argv=None,user_ns=None,user_global_ns=None,
43
               cin=None, cout=None,cerr=None, input_func=None):
33
               cin=None, cout=None,cerr=None, input_func=None):
34
    '''
35
    
36
    
37
    @param argv: Command line options for IPython
38
    @type argv: list
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.
44
    @type cin: IO stream
45
    @param cout: Console standard output.
46
    @type cout: IO stream 
47
    @param cerr: Console standard error.
48
    @type cerr: IO stream
49
    @param input_func: Replacement for builtin raw_input()
50
    @type input_func: function
51
    '''
52
    io = IPython.utils.io
44
    if input_func:
53
    if input_func:
45
      IPython.iplib.raw_input_original = input_func
54
      if parse_version(IPython.release.version) >= parse_version("1.2.1"):
55
        IPython.terminal.interactiveshell.raw_input_original = input_func
56
      else:
57
        IPython.frontend.terminal.interactiveshell.raw_input_original = input_func
46
    if cin:
58
    if cin:
47
      IPython.Shell.Term.cin = cin
59
      io.stdin = io.IOStream(cin)
48
    if cout:
60
    if cout:
49
      IPython.Shell.Term.cout = cout
61
      io.stdout = io.IOStream(cout)
50
    if cerr:
62
    if cerr:
51
      IPython.Shell.Term.cerr = cerr
63
      io.stderr = io.IOStream(cerr)
52
53
    if argv is None:
54
      argv=[]
55
64
56
    # This is to get rid of the blockage that occurs during 
65
    # This is to get rid of the blockage that occurs during 
57
    # IPython.Shell.InteractiveShell.user_setup()
66
    # IPython.Shell.InteractiveShell.user_setup()
58
    IPython.iplib.raw_input = lambda x: None
59
67
60
    self.term = IPython.genutils.IOTerm(cin=cin, cout=cout, cerr=cerr)
68
    io.raw_input = lambda x: None
69
61
    os.environ['TERM'] = 'dumb'
70
    os.environ['TERM'] = 'dumb'
62
    excepthook = sys.excepthook
71
    excepthook = sys.excepthook 
63
    self.IP = IPython.Shell.make_IPython(argv,user_ns=user_ns,
72
64
                                         user_global_ns=user_global_ns,
73
    from IPython.config.loader import Config
65
                                         embedded=True,
74
    cfg = Config()
66
                                         shell_class=IPython.Shell.InteractiveShell)
75
    cfg.InteractiveShell.colors = "Linux"
76
77
    # InteractiveShell's __init__ overwrites io.stdout,io.stderr with
78
    # sys.stdout, sys.stderr, this makes sure they are right
79
    #
80
    old_stdout, old_stderr = sys.stdout, sys.stderr
81
    sys.stdout, sys.stderr = io.stdout.stream, io.stderr.stream
82
83
    # InteractiveShell inherits from SingletonConfigurable, so use instance()
84
    #
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)
88
    else:
89
      self.IP = IPython.frontend.terminal.embed.InteractiveShellEmbed.instance(\
90
              config=cfg, user_ns=user_ns)
91
92
    sys.stdout, sys.stderr = old_stdout, old_stderr
93
67
    self.IP.system = lambda cmd: self.shell(self.IP.var_expand(cmd),
94
    self.IP.system = lambda cmd: self.shell(self.IP.var_expand(cmd),
68
                                            header='IPython system call: ',
95
                                            header='IPython system call: ')
69
                                            verbose=self.IP.rc.system_verbose)
96
#                                            local_ns=user_ns)
97
                                            #global_ns=user_global_ns)
98
                                            #verbose=self.IP.rc.system_verbose)
99
100
    self.IP.raw_input = input_func
70
    sys.excepthook = excepthook
101
    sys.excepthook = excepthook
71
    self.iter_more = 0
102
    self.iter_more = 0
72
    self.history_level = 0
103
    self.history_level = 0
73
    self.complete_sep =  re.compile('[\s\{\}\[\]\(\)]')
104
    self.complete_sep =  re.compile('[\s\{\}\[\]\(\)]')
105
    self.updateNamespace({'exit':lambda:None})
106
    self.updateNamespace({'quit':lambda:None})
107
    self.IP.readline_startup_hook(self.IP.pre_readline)
108
    # Workaround for updating namespace with sys.modules
109
    #
110
    self.__update_namespace()
111
112
  def __update_namespace(self):
113
    '''
114
    Update self.IP namespace for autocompletion with sys.modules
115
    '''
116
    for k, v in list(sys.modules.items()):
117
        if not '.' in k:
118
          self.IP.user_ns.update({k:v})
74
119
75
  def execute(self):
120
  def execute(self):
121
    '''
122
    Executes the current line provided by the shell object.
123
    '''
76
    self.history_level = 0
124
    self.history_level = 0
77
    orig_stdout = sys.stdout
125
    orig_stdout = sys.stdout
78
    sys.stdout = IPython.Shell.Term.cout
126
    sys.stdout = IPython.utils.io.stdout
127
128
    orig_stdin = sys.stdin
129
    sys.stdin = IPython.utils.io.stdin;
130
    self.prompt = self.generatePrompt(self.iter_more)
131
132
    self.IP.hooks.pre_prompt_hook()
133
    if self.iter_more:
134
        try:
135
            self.prompt = self.generatePrompt(True)
136
        except:
137
            self.IP.showtraceback()
138
        if self.IP.autoindent:
139
            self.IP.rl_do_indent = True
140
79
    try:
141
    try:
80
      line = self.IP.raw_input(None, self.iter_more)
142
      line = self.IP.raw_input(self.prompt)
81
      if self.IP.autoindent:
82
        self.IP.readline_startup_hook(None)
83
    except KeyboardInterrupt:
143
    except KeyboardInterrupt:
84
      self.IP.write('\nKeyboardInterrupt\n')
144
      self.IP.write('\nKeyboardInterrupt\n')
85
      self.IP.resetbuffer()
145
      self.IP.input_splitter.reset()
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:
146
    except:
93
      self.IP.showtraceback()
147
      self.IP.showtraceback()
94
    else:
148
    else:
95
      self.iter_more = self.IP.push(line)
149
      self.IP.input_splitter.push(line)
150
      self.iter_more = self.IP.input_splitter.push_accepts_more()
151
      self.prompt = self.generatePrompt(self.iter_more)
96
      if (self.IP.SyntaxTB.last_syntax_error and
152
      if (self.IP.SyntaxTB.last_syntax_error and
97
          self.IP.rc.autoedit_syntax):
153
          self.IP.autoedit_syntax):
98
        self.IP.edit_syntax_error()
154
          self.IP.edit_syntax_error()
99
    if self.iter_more:
155
      if not self.iter_more:
100
      self.prompt = str(self.IP.outputcache.prompt2).strip()
156
          if parse_version(IPython.release.version) >= parse_version("2.0.0-dev"):
101
      if self.IP.autoindent:
157
            source_raw = self.IP.input_splitter.raw_reset()
102
        self.IP.readline_startup_hook(self.IP.pre_readline)
158
          else:
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
162
      else:
163
          # TODO: Auto-indent
164
          #
165
          self.IP.rl_do_indent = True
166
          pass
167
168
    sys.stdout = orig_stdout
169
    sys.stdin = orig_stdin
170
171
  def generatePrompt(self, is_continuation):
172
    '''
173
    Generate prompt depending on is_continuation value
174
175
    @param is_continuation
176
    @type is_continuation: boolean 
177
178
    @return: The prompt string representation
179
    @rtype: string
180
181
    '''
182
183
    # Backwards compatibility with ipyton-0.11
184
    #
185
    ver = IPython.__version__
186
    if '0.11' in ver:
187
        prompt = self.IP.hooks.generate_prompt(is_continuation)
103
    else:
188
    else:
104
      self.prompt = str(self.IP.outputcache.prompt1).strip()
189
        if is_continuation:
105
    sys.stdout = orig_stdout
190
            prompt = self.IP.prompt_manager.render('in2')
191
        else:
192
            prompt = self.IP.prompt_manager.render('in')
193
194
    return prompt
195
106
196
107
  def historyBack(self):
197
  def historyBack(self):
198
    '''
199
    Provides one history command back.
200
    
201
    @return: The command string.
202
    @rtype: string
203
    '''
108
    self.history_level -= 1
204
    self.history_level -= 1
205
    if not self._getHistory():
206
      self.history_level +=1
109
    return self._getHistory()
207
    return self._getHistory()
110
208
111
  def historyForward(self):
209
  def historyForward(self):
112
    self.history_level += 1
210
    '''
211
    Provides one history command forward.
212
    
213
    @return: The command string.
214
    @rtype: string
215
    '''
216
    if self.history_level < 0:
217
      self.history_level += 1
113
    return self._getHistory()
218
    return self._getHistory()
114
219
115
  def _getHistory(self):
220
  def _getHistory(self):
221
    '''
222
    Get's the command string of the current history level.
223
    
224
    @return: Historic command string.
225
    @rtype: string
226
    '''
116
    try:
227
    try:
117
      rv = self.IP.user_ns['In'][self.history_level].strip('\n')
228
      rv = self.IP.user_ns['In'][self.history_level].strip('\n')
118
    except IndexError:
229
    except IndexError:
119
      self.history_level = 0
120
      rv = ''
230
      rv = ''
121
    return rv
231
    return rv
122
232
123
  def updateNamespace(self, ns_dict):
233
  def updateNamespace(self, ns_dict):
234
    '''
235
    Add the current dictionary to the shell namespace.
236
    
237
    @param ns_dict: A dictionary of symbol-values.
238
    @type ns_dict: dictionary
239
    '''
124
    self.IP.user_ns.update(ns_dict)
240
    self.IP.user_ns.update(ns_dict)
125
241
126
  def complete(self, line):
242
  def complete(self, line):
243
    '''
244
    Returns an auto completed line and/or posibilities for completion.
245
    
246
    @param line: Given line so far.
247
    @type line: string
248
    
249
    @return: Line completed as for as possible, 
250
    and possible further completions.
251
    @rtype: tuple
252
    '''
127
    split_line = self.complete_sep.split(line)
253
    split_line = self.complete_sep.split(line)
128
    possibilities = self.IP.complete(split_line[-1])
254
    if split_line[-1]:
129
    if possibilities:
255
      possibilities = self.IP.complete(split_line[-1])
130
      common_prefix = reduce(self._commonPrefix, possibilities)
131
      completed = line[:-len(split_line[-1])]+common_prefix
132
    else:
256
    else:
133
      completed = line
257
      completed = line
134
    return completed, possibilities
258
      possibilities = ['', []]
135
259
    if possibilities:
136
  def _commonPrefix(self, str1, str2):
260
      def _commonPrefix(str1, str2):
137
    for i in range(len(str1)):
261
        '''
138
      if not str2.startswith(str1[:i+1]):
262
        Reduction function. returns common prefix of two given strings.
139
        return str1[:i]
263
        
140
    return str1
264
        @param str1: First string.
265
        @type str1: string
266
        @param str2: Second string
267
        @type str2: string
268
        
269
        @return: Common prefix to both strings.
270
        @rtype: string
271
        '''
272
        for i in range(len(str1)):
273
          if not str2.startswith(str1[:i+1]):
274
            return str1[:i]
275
        return str1
276
      if possibilities[1]:
277
        common_prefix = reduce(_commonPrefix, possibilities[1]) or line[-1]
278
        completed = line[:-len(split_line[-1])]+common_prefix
279
      else:
280
        completed = line
281
    else:
282
      completed = line
283
    return completed, possibilities[1]
284
  
141
285
142
  def shell(self, cmd,verbose=0,debug=0,header=''):
286
  def shell(self, cmd,verbose=0,debug=0,header=''):
287
    '''
288
    Replacement method to allow shell commands without them blocking.
289
    
290
    @param cmd: Shell command to execute.
291
    @type cmd: string
292
    @param verbose: Verbosity
293
    @type verbose: integer
294
    @param debug: Debug level
295
    @type debug: integer
296
    @param header: Header to be printed before output
297
    @type header: string
298
    '''
143
    stat = 0
299
    stat = 0
144
    if verbose or debug: print header+cmd
300
    if verbose or debug: print header+cmd
145
    # flush stdout so we don't mangle python's buffering
301
    # flush stdout so we don't mangle python's buffering
 Lines 150-156    Link Here 
150
      input.close()
306
      input.close()
151
307
152
class ConsoleView(gtk.TextView):
308
class ConsoleView(gtk.TextView):
309
  '''
310
  Specialized text view for console-like workflow.
311
312
  @cvar ANSI_COLORS: Mapping of terminal colors to X11 names.
313
  @type ANSI_COLORS: dictionary
314
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
323
  '''
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'}
332
153
  def __init__(self):
333
  def __init__(self):
334
    '''
335
    Initialize console view.
336
    '''
154
    gtk.TextView.__init__(self)
337
    gtk.TextView.__init__(self)
155
    self.modify_font(pango.FontDescription('Mono'))
338
    self.modify_font(pango.FontDescription('Mono'))
156
    self.set_cursor_visible(True)
339
    self.set_cursor_visible(True)
 Lines 158-178    Link Here 
158
    self.mark = self.text_buffer.create_mark('scroll_mark',
341
    self.mark = self.text_buffer.create_mark('scroll_mark',
159
                                             self.text_buffer.get_end_iter(),
342
                                             self.text_buffer.get_end_iter(),
160
                                             False)
343
                                             False)
161
    for code in ansi_colors:
344
    for code in self.ANSI_COLORS:
162
      self.text_buffer.create_tag(code,
345
      self.text_buffer.create_tag(code, 
163
                                  foreground=ansi_colors[code],
346
                                  foreground=self.ANSI_COLORS[code], 
164
                                  weight=700)
347
                                  weight=700)
165
    self.text_buffer.create_tag('0')
348
    self.text_buffer.create_tag('0')
166
    self.text_buffer.create_tag('notouch', editable=False)
349
    self.text_buffer.create_tag('notouch', editable=False)
167
    self.color_pat = re.compile('\x01?\x1b\[(.*?)m\x02?')
350
    self.color_pat = re.compile('\x01?\x1b\[(.*?)m\x02?')
168
    self.line_start = \
351
    self.line_start = \
169
                self.text_buffer.create_mark('line_start',
352
        self.text_buffer.create_mark('line_start', 
170
                        self.text_buffer.get_end_iter(), True
353
                                     self.text_buffer.get_end_iter(), True)
171
                )
354
    self.connect('key-press-event', self.onKeyPress)
172
    self.connect('key-press-event', self._onKeypress)
355
    
173
    self.last_cursor_pos = 0
356
  def write(self, text, editable=False):
357
    gobject.idle_add(self._write, text, editable)
174
358
175
  def write(self, text, editable=False):
359
  def _write(self, text, editable=False):
360
    '''
361
    Write given text to buffer.
362
    
363
    @param text: Text to append.
364
    @type text: string
365
    @param editable: If true, added text is editable.
366
    @type editable: boolean
367
    '''
176
    segments = self.color_pat.split(text)
368
    segments = self.color_pat.split(text)
177
    segment = segments.pop(0)
369
    segment = segments.pop(0)
178
    start_mark = self.text_buffer.create_mark(None,
370
    start_mark = self.text_buffer.create_mark(None,
 Lines 185-191    Link Here 
185
      for tag in ansi_tags:
377
      for tag in ansi_tags:
186
        i = segments.index(tag)
378
        i = segments.index(tag)
187
        self.text_buffer.insert_with_tags_by_name(self.text_buffer.get_end_iter(),
379
        self.text_buffer.insert_with_tags_by_name(self.text_buffer.get_end_iter(),
188
                                             segments[i+1], tag)
380
                                                  segments[i+1], str(tag))
189
        segments.pop(i)
381
        segments.pop(i)
190
    if not editable:
382
    if not editable:
191
      self.text_buffer.apply_tag_by_name('notouch',
383
      self.text_buffer.apply_tag_by_name('notouch',
 Lines 195-266    Link Here 
195
    self.scroll_mark_onscreen(self.mark)
387
    self.scroll_mark_onscreen(self.mark)
196
388
197
  def showPrompt(self, prompt):
389
  def showPrompt(self, prompt):
198
    self.write(prompt)
390
    gobject.idle_add(self._showPrompt, prompt)
199
    self.text_buffer.move_mark(self.line_start,self.text_buffer.get_end_iter())
391
392
  def _showPrompt(self, prompt):
393
    '''
394
    Prints prompt at start of line.
395
    
396
    @param prompt: Prompt to print.
397
    @type prompt: string
398
    '''
399
    self._write(prompt)
400
    self.text_buffer.move_mark(self.line_start,
401
                               self.text_buffer.get_end_iter())
200
402
201
  def changeLine(self, text):
403
  def changeLine(self, text):
404
    gobject.idle_add(self._changeLine, text)
405
406
  def _changeLine(self, text):
407
    '''
408
    Replace currently entered command line with given text.
409
    
410
    @param text: Text to use as replacement.
411
    @type text: string
412
    '''
202
    iter = self.text_buffer.get_iter_at_mark(self.line_start)
413
    iter = self.text_buffer.get_iter_at_mark(self.line_start)
203
    iter.forward_to_line_end()
414
    iter.forward_to_line_end()
204
    self.text_buffer.delete(self.text_buffer.get_iter_at_mark(self.line_start), iter)
415
    self.text_buffer.delete(self.text_buffer.get_iter_at_mark(self.line_start), iter)
205
    self.write(text, True)
416
    self._write(text, True)
206
417
207
  def getCurrentLine(self):
418
  def getCurrentLine(self):
208
    rv = self.text_buffer.get_slice(self.text_buffer.get_iter_at_mark(self.line_start),
419
    '''
209
                                    self.text_buffer.get_end_iter(), False)
420
    Get text in current command line.
421
    
422
    @return: Text of current command line.
423
    @rtype: string
424
    '''
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)
210
    return rv
428
    return rv
211
429
212
  def showReturned(self, text):
430
  def showReturned(self, text):
431
    gobject.idle_add(self._showReturned, text)
432
433
  def _showReturned(self, text):
434
    '''
435
    Show returned text from last command and print new prompt.
436
    
437
    @param text: Text to show.
438
    @type text: string
439
    '''
213
    iter = self.text_buffer.get_iter_at_mark(self.line_start)
440
    iter = self.text_buffer.get_iter_at_mark(self.line_start)
214
    iter.forward_to_line_end()
441
    iter.forward_to_line_end()
215
    self.text_buffer.apply_tag_by_name('notouch',
442
    self.text_buffer.apply_tag_by_name(
216
                                       self.text_buffer.get_iter_at_mark(self.line_start),
443
      'notouch', 
217
                                       iter)
444
      self.text_buffer.get_iter_at_mark(self.line_start),
218
    self.write('\n'+text)
445
      iter)
446
    self._write('\n'+text)
219
    if text:
447
    if text:
220
      self.write('\n')
448
      self._write('\n')
221
    self.showPrompt(self.prompt)
449
    self._showPrompt(self.prompt)
222
    self.text_buffer.move_mark(self.line_start,self.text_buffer.get_end_iter())
450
    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())
451
    self.text_buffer.place_cursor(self.text_buffer.get_end_iter())
224
452
225
  def _onKeypress(self, obj, event):
453
    if self.IP.rl_do_indent:
226
    if not event.string:
454
      indentation = self.IP.input_splitter.indent_spaces * ' '
227
      return
455
      self.text_buffer.insert_at_cursor(indentation)
456
457
  def onKeyPress(self, widget, event):
458
    '''
459
    Key press callback used for correcting behavior for console-like 
460
    interfaces. For example 'home' should go to prompt, not to begining of
461
    line.
462
    
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
467
    
468
    @return: Return True if event should not trickle.
469
    @rtype: boolean
470
    '''
228
    insert_mark = self.text_buffer.get_insert()
471
    insert_mark = self.text_buffer.get_insert()
229
    insert_iter = self.text_buffer.get_iter_at_mark(insert_mark)
472
    insert_iter = self.text_buffer.get_iter_at_mark(insert_mark)
230
    selection_mark = self.text_buffer.get_selection_bound()
473
    selection_mark = self.text_buffer.get_selection_bound()
231
    selection_iter = self.text_buffer.get_iter_at_mark(selection_mark)
474
    selection_iter = self.text_buffer.get_iter_at_mark(selection_mark)
232
    start_iter = self.text_buffer.get_iter_at_mark(self.line_start)
475
    start_iter = self.text_buffer.get_iter_at_mark(self.line_start)
233
    if start_iter.compare(insert_iter) <= 0 and \
476
    if event.keyval == gtk.keysyms.Home:
477
      if event.state & gtk.gdk.CONTROL_MASK or event.state & gtk.gdk.MOD1_MASK:
478
        pass
479
      elif event.state & gtk.gdk.SHIFT_MASK:
480
        self.text_buffer.move_mark(insert_mark, start_iter)
481
        return True
482
      else:
483
        self.text_buffer.place_cursor(start_iter)
484
        return True
485
    elif event.keyval == gtk.keysyms.Left:
486
      insert_iter.backward_cursor_position()
487
      if not insert_iter.editable(True):
488
        return True
489
    elif not event.string:
490
      pass
491
    elif start_iter.compare(insert_iter) <= 0 and \
234
          start_iter.compare(selection_iter) <= 0:
492
          start_iter.compare(selection_iter) <= 0:
235
      return
493
      pass
236
    elif start_iter.compare(insert_iter) > 0 and \
494
    elif start_iter.compare(insert_iter) > 0 and \
237
          start_iter.compare(selection_iter) > 0:
495
          start_iter.compare(selection_iter) > 0:
238
      self.text_buffer.place_cursor(start_iter)
496
      self.text_buffer.place_cursor(start_iter)
239
    elif insert_iter.compare(selection_iter) < 0:
497
    elif insert_iter.compare(selection_iter) < 0:
240
      self.text_buffer.move_mark(insert_mark, start_iter)
498
      self.text_buffer.move_mark(insert_mark, start_iter)
241
    elif insert_iter.compare(selection_iter) > 0:
499
    elif insert_iter.compare(selection_iter) > 0:
242
      self.text_buffer.move_mark(selection_mark, start_iter)
500
      self.text_buffer.move_mark(selection_mark, start_iter)             
243
501
502
    return self.onKeyPressExtend(event)
503
504
  def onKeyPressExtend(self, event):
505
    '''
506
    For some reason we can't extend onKeyPress directly (bug #500900).
507
    '''
508
    pass
244
509
245
class IPythonView(ConsoleView, IterableIPShell):
510
class IPythonView(ConsoleView, IterableIPShell):
511
  '''
512
  Sub-class of both modified IPython shell and L{ConsoleView} this makes
513
  a GTK+ IPython console.
514
  '''
246
  def __init__(self):
515
  def __init__(self):
516
    '''
517
    Initialize. Redirect I/O to console.
518
    '''
247
    ConsoleView.__init__(self)
519
    ConsoleView.__init__(self)
248
    self.cout = StringIO()
520
    self.cout = StringIO()
249
    IterableIPShell.__init__(self, cout=self.cout,cerr=self.cout,
521
    IterableIPShell.__init__(self, cout=self.cout,cerr=self.cout,
250
                             input_func=self.raw_input)
522
                             input_func=self.raw_input)
251
    self.connect('key_press_event', self.keyPress)
523
    self.interrupt = False
252
    self.execute()
524
    self.execute()
525
    self.prompt = self.generatePrompt(False)
253
    self.cout.truncate(0)
526
    self.cout.truncate(0)
254
    self.showPrompt(self.prompt)
527
    self.showPrompt(self.prompt)
255
    self.interrupt = False
256
528
257
  def raw_input(self, prompt=''):
529
  def raw_input(self, prompt=''):
530
    '''
531
    Custom raw_input() replacement. Get's current line from console buffer.
532
    
533
    @param prompt: Prompt to print. Here for compatability as replacement.
534
    @type prompt: string
535
    
536
    @return: The current command line text.
537
    @rtype: string
538
    '''
258
    if self.interrupt:
539
    if self.interrupt:
259
      self.interrupt = False
540
      self.interrupt = False
260
      raise KeyboardInterrupt
541
      raise KeyboardInterrupt
261
    return self.getCurrentLine()
542
    return self.getCurrentLine()
262
543
263
  def keyPress(self, widget, event):
544
  def onKeyPressExtend(self, event):
545
    '''
546
    Key press callback with plenty of shell goodness, like history, 
547
    autocompletions, etc.
548
    
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
553
    
554
    @return: True if event should not trickle.
555
    @rtype: boolean
556
    '''
557
264
    if event.state & gtk.gdk.CONTROL_MASK and event.keyval == 99:
558
    if event.state & gtk.gdk.CONTROL_MASK and event.keyval == 99:
265
      self.interrupt = True
559
      self.interrupt = True
266
      self._processLine()
560
      self._processLine()
 Lines 288-296    Link Here 
288
      return True
582
      return True
289
583
290
  def _processLine(self):
584
  def _processLine(self):
585
    '''
586
    Process current command line.
587
    '''
291
    self.history_pos = 0
588
    self.history_pos = 0
292
    self.execute()
589
    self.execute()
293
    rv = self.cout.getvalue()
590
    rv = self.cout.getvalue()
294
    if rv: rv = rv.strip('\n')
591
    if rv: rv = rv.strip('\n')
295
    self.showReturned(rv)
592
    self.showReturned(rv)
296
    self.cout.truncate(0)
593
    self.cout.truncate(0)
594
    self.cout.seek(0)
595
 
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())
600
  window.add(IPythonView())
601
  window.show_all()
602
  gtk.main()
603
    

Return to bug 1981