Learn how easy it is to sync an existing GitHub or Google Code repo to a SourceForge project! See Demo

Close

Diff of /plugins/shell.py [2c229c] .. [6fe32e] Maximize Restore

  Switch to unified view

a/plugins/shell.py b/plugins/shell.py
...
...
82
    quickhelp = quickhelp + all_but_mac
82
    quickhelp = quickhelp + all_but_mac
83
83
84
chnames = [i[0] for i in choices]
84
chnames = [i[0] for i in choices]
85
chlookup = dict(choices)
85
chlookup = dict(choices)
86
86
87
class StartupError(Exception):
88
    pass
89
90
close_stdin = "<CLOSE STDIN>"
91
92
class process:
93
    def __init__(self, parent, cmd, end_callback):
94
        self.process = wx.Process(parent)
95
        self.process.Redirect()
96
        self.process.pid = wx.Execute(cmd, wx.EXEC_ASYNC, self.process)
97
        if self.process.pid:
98
            #what was up with wx.Process.Get*Stream names?
99
            self.process._stdin_ = self.process.GetOutputStream()
100
            self.process._stdout_ = self.process.GetInputStream()
101
            self.process._stderr_ = self.process.GetErrorStream()
102
            self.process.Bind(wx.EVT_END_PROCESS, end_callback)
103
            return
104
        self.b = []
105
        raise StartupError
106
            
107
    def Poll(self, input=''):
108
        if input and self.process and self.process._stdin_:
109
            self.process._stdin_.write(input)
110
            ## y = self.process._stdin_.LastWrite()
111
            ## if y != len(input):
112
                ## print "sent %s of %s"%(y, len(input))
113
        x = []
114
        for s in (self.process._stderr_, self.process._stdout_):
115
            if s and s.CanRead():
116
                x.append(s.read())
117
            else:
118
                x.append('')
119
        return x
120
        
121
    def CloseInp(self):
122
        if self.process and self.process._stdin_:
123
            self.process.CloseOutput()
124
            self.process._stdin_ = None
125
    
126
    def Kill(self, ks):
127
        errors = {wx.KILL_BAD_SIGNAL: "KILL_BAD_SIGNAL",
128
                  wx.KILL_ACCESS_DENIED: "KILL_ACCESS_DENIED",
129
                  wx.KILL_ERROR: "KILL_ERROR"}
130
        if self.process:
131
            if ks == close_stdin:
132
                self.CloseInp()
133
                return 1, None
134
            elif wx.Process.Exists(self.process.pid):
135
                signal = getattr(wx, ks)
136
                r = wx.Process.Kill(self.process.pid, signal)
137
            else:
138
                r = 65535
139
                self.CloseInp()
140
                return 1, None
141
            
142
            if r not in (wx.KILL_OK, wx.KILL_NO_PROCESS, 65535):
143
                return 0, (self.process.pid, signal, errors.get(r, "UNKNOWN_KILL_ERROR %s"%r))
144
            else:
145
                return 1, None
146
87
class Shell(wx.Panel):
147
class Shell(wx.Panel):
88
    def __init__(self, parent, root, prefs={}):
148
    def __init__(self, parent, root, prefs={}):
89
        wx.Panel.__init__(self, parent, -1)
149
        wx.Panel.__init__(self, parent, -1)
90
        self.root = root
150
        self.root = root
91
151
...
...
137
        self.Bind(wx.EVT_BUTTON, self.OnExecuteBtn, self.exBtn)
197
        self.Bind(wx.EVT_BUTTON, self.OnExecuteBtn, self.exBtn)
138
        self.Bind(wx.EVT_BUTTON, self.OnShowPopup, b)
198
        self.Bind(wx.EVT_BUTTON, self.OnShowPopup, b)
139
        self.Bind(wx.EVT_BUTTON, self.OnSendText, self.sndBtn)
199
        self.Bind(wx.EVT_BUTTON, self.OnSendText, self.sndBtn)
140
        self.Bind(wx.EVT_TEXT_ENTER, self.OnSendText, self.inp)
200
        self.Bind(wx.EVT_TEXT_ENTER, self.OnSendText, self.inp)
141
        self.inp.Bind(wx.EVT_CHAR, self.OnChar, self.inp)
201
        self.inp.Bind(wx.EVT_CHAR, self.OnChar, self.inp)
142
        self.Bind(wx.EVT_END_PROCESS, self.OnProcessEnded)
143
        self.Bind(wx.EVT_BUTTON, self.OnKillProcess, self.killBtn)
202
        self.Bind(wx.EVT_BUTTON, self.OnKillProcess, self.killBtn)
144
203
145
        # Do the layout
204
        # Do the layout
146
        box1 = wx.BoxSizer(wx.HORIZONTAL)
205
        box1 = wx.BoxSizer(wx.HORIZONTAL)
147
        box1.Add(prompt, 0, wx.ALIGN_CENTER)
206
        box1.Add(prompt, 0, wx.ALIGN_CENTER)
...
...
244
                if ' ' in v:
303
                if ' ' in v:
245
                    x[k] = '"%s"'%v
304
                    x[k] = '"%s"'%v
246
            
305
            
247
            cmd = cmd%x
306
            cmd = cmd%x
248
        
307
        
249
        self.process = wx.Process(self)
308
        try:
250
        self.process.Redirect()
309
            self.process = process(self, cmd, self.OnProcessEnded)
251
        self.process.pid = wx.Execute(cmd, wx.EXEC_ASYNC, self.process)
252
        if self.process.pid:
253
            #what was up with wx.Process.Get*Stream names?
254
            self.process._stdin_ = self.process.GetOutputStream()
255
            self.process._stdout_ = self.process.GetInputStream()
256
            self.process._stderr_ = self.process.GetErrorStream()
257
258
            self.started()
310
            self.started()
259
        
260
            self.root.SetStatusText("Started, pid: %i command: %s"%(self.process.pid, cmd))
311
            self.root.SetStatusText("Started, pid: %i command: %s"%(self.process.process.pid, cmd))
261
        else:
312
        except StartupError:
262
            self.process = None
313
            self.process = None
263
            self.root.SetStatusText("Couldn't start command: %s"%cmd)
314
            self.root.SetStatusText("Couldn't start command: %s"%cmd)
264
            self.root.SetStatusText("Try disabling/enabling the use of a shell, or running the shell directly")
315
            self.root.SetStatusText("Try disabling/enabling the use of a shell, or running the shell directly")            
265
316
266
    def ended(self):
317
    def ended(self):
267
        self.process = None
318
        self.process = None
268
        for i in self.set1:
319
        for i in self.set1:
269
            i.Enable(True)
320
            i.Enable(True)
...
...
271
            i.Enable(False)
322
            i.Enable(False)
272
        self.timer.Stop()
323
        self.timer.Stop()
273
    
324
    
274
    def OnProcessEnded(self, evt):
325
    def OnProcessEnded(self, evt):
275
        self.OnCloseStream(evt)
326
        self.OnCloseStream(evt)
276
        for s in (self.process._stdout_, self.process._stderr_):
327
        for i in self.process.Poll():
277
            if s.CanRead():
278
                self.AppendText(s.read())
328
            self.AppendText(i)
279
        self.root.SetStatusText("Process Ended, pid:%s,  exitCode: %s"%(evt.GetPid(), evt.GetExitCode()))
329
        self.root.SetStatusText("Process Ended, pid:%s,  exitCode: %s"%(evt.GetPid(), evt.GetExitCode()))
280
        self.ended()
330
        self.ended()
281
    
331
    
282
    def OnSendText(self, evt):
332
    def OnSendText(self, evt):
283
        if self.process and self.process._stdin_:
333
        if self.process and self.process.process._stdin_:
284
            c = self.inp.GetValue()
334
            c = self.inp.GetValue()
285
            #handle string escaping...
335
            #handle string escaping...
286
            if c.strip():
336
            if c.strip():
287
                fix(self.inp, c, 10)
337
                fix(self.inp, c, 10)
288
            if c and c[-1] in ['"', "'"] and self.unescape.GetValue():
338
            if c and c[-1] in ['"', "'"] and self.unescape.GetValue():
...
...
293
            try:
343
            try:
294
                c = str(c+'\n')
344
                c = str(c+'\n')
295
            except UnicodeEncodeError, why:
345
            except UnicodeEncodeError, why:
296
                self.root.SetStatusText("Couldn't send to subprocess: %s"%why)
346
                self.root.SetStatusText("Couldn't send to subprocess: %s"%why)
297
                return
347
                return
298
            self.process._stdin_.write(c)
348
            ta = self.process.Poll(c)
299
            if self.echo.GetValue():
349
            if self.echo.GetValue():
300
                self.AppendText(c)
350
                self.AppendText(c)
301
            ## snt = self.process._stdin_.LastWrite()
351
            for i in ta:
352
                self.AppendText(i)
302
            self.inp.SetValue('')
353
            self.inp.SetValue('')
303
            self.inp.SetFocus()
354
            self.inp.SetFocus()
304
355
305
    def OnCloseStream(self, evt):
356
    def OnCloseStream(self, evt):
306
        if self.process and self.process._stdin_:
307
            self.process.CloseOutput()
357
        self.process.CloseInp()
308
            self.process._stdin_ = None
309
            self.inp.Enable(False)
358
        self.inp.Enable(False)
310
            self.sndBtn.Enable(False)
359
        self.sndBtn.Enable(False)
311
            ## if self.outbuf:
312
                ## self.SetStatusText("Didn't write to subprocess: %r"%self.outbuf)
313
                ## self.outbuf = ''
314
    
360
    
315
    def OnKillProcess(self, evt):
361
    def OnKillProcess(self, evt):
316
        errors = {wx.KILL_BAD_SIGNAL: "KILL_BAD_SIGNAL",
317
                  wx.KILL_ACCESS_DENIED: "KILL_ACCESS_DENIED",
318
                  wx.KILL_ERROR: "KILL_ERROR"}
319
        if self.process:
362
        if self.process:
320
            ks = self.killSel.GetValue()
363
            succ, args = self.process.Kill(self.killSel.GetValue())
321
            if ks == '<CLOSE STDIN>':
364
            if succ:
322
                return self.OnCloseStream(evt)
365
                self.OnCloseStream(evt)
323
            elif wx.Process.Exists(self.process.pid):
324
                signal = getattr(wx, ks)
325
                r = wx.Process.Kill(self.process.pid, signal)
326
            else:
366
            else:
327
                r = 65535
328
                self.OnCloseStream(evt)
329
            
330
            if r not in (wx.KILL_OK, wx.KILL_NO_PROCESS, 65535):
331
                self.root.SetStatusText("***Error killing process: %i  with signal: %i  error: %s ***"%(self.process.pid, signal, errors.get(r, "UNKNOWN_KILL_ERROR %s"%r)))
367
                self.root.SetStatusText("***Error killing process: %i  with signal: %i  error: %s ***"%args)
332
            else:
333
                self.OnCloseStream(evt)
334
    
368
    
335
    def AppendText(self, txt):
369
    def AppendText(self, txt):
336
        if not txt:
370
        if not txt:
337
            return
371
            return
338
        
372
        
...
...
381
            for i in xrange(lines-1, max(lines-screenlines-1, -1), -1):
415
            for i in xrange(lines-1, max(lines-screenlines-1, -1), -1):
382
                lp -= self.out.GetLineLength(i) + (i != lines-1)
416
                lp -= self.out.GetLineLength(i) + (i != lines-1)
383
            self.out.ShowPosition(lp)
417
            self.out.ShowPosition(lp)
384
    
418
    
385
    def OnPoll(self, evt):
419
    def OnPoll(self, evt):
386
        ## if self.outbuf:
387
            ## self.process._stdin_.write(self.outbuf)
388
            ## ## snt = self.process._stdin_.LastWrite()
389
            ## self.outbuf = ''
390
        
420
        
391
        if self.process and not self.pause.GetValue():
421
        if self.process and not self.pause.GetValue():
392
            for s in (self.process._stderr_, self.process._stdout_):
422
            for i in self.process.Poll():
393
                if s.CanRead():
394
                    self.AppendText(s.read())
423
                self.AppendText(i)