Skip to content

Commit 5b08740

Browse files
committed
Pastebin + confirmation in GTK, this means:
- moved stdout_hist to repl children (and its methods) - added statusbar to gtk_.ReplWidget
1 parent a5aa691 commit 5b08740

File tree

4 files changed

+232
-75
lines changed

4 files changed

+232
-75
lines changed

bpython/cli.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ def __init__(self, scr, interp, statusbar, config, idle=None):
240240
Repl.__init__(self, interp, config)
241241
interp.writetb = self.writetb
242242
self.scr = scr
243+
self.stdout_hist = ''
243244
self.list_win = newwin(get_colpair(config, 'background'), 1, 1, 1, 1)
244245
self.cpos = 0
245246
self.do_exit = False
@@ -998,6 +999,78 @@ def resize(self):
998999
self.statusbar.resize(refresh=False)
9991000
self.redraw()
10001001

1002+
def getstdout(self):
1003+
"""This method returns the 'spoofed' stdout buffer, for writing to a
1004+
file or sending to a pastebin or whatever."""
1005+
1006+
return self.stdout_hist + '\n'
1007+
1008+
1009+
def reevaluate(self):
1010+
"""Clear the buffer, redraw the screen and re-evaluate the history"""
1011+
1012+
self.evaluating = True
1013+
self.stdout_hist = ''
1014+
self.f_string = ''
1015+
self.buffer = []
1016+
self.scr.erase()
1017+
self.s_hist = []
1018+
# Set cursor position to -1 to prevent paren matching
1019+
self.cpos = -1
1020+
1021+
self.prompt(False)
1022+
1023+
self.iy, self.ix = self.scr.getyx()
1024+
for line in self.history:
1025+
if py3:
1026+
self.stdout_hist += line + '\n'
1027+
else:
1028+
self.stdout_hist += line.encode(getpreferredencoding()) + '\n'
1029+
self.print_line(line)
1030+
self.s_hist[-1] += self.f_string
1031+
# I decided it was easier to just do this manually
1032+
# than to make the print_line and history stuff more flexible.
1033+
self.scr.addstr('\n')
1034+
more = self.push(line)
1035+
self.prompt(more)
1036+
self.iy, self.ix = self.scr.getyx()
1037+
1038+
self.cpos = 0
1039+
indent = next_indentation(self.s, self.config.tab_length)
1040+
self.s = ''
1041+
self.scr.refresh()
1042+
1043+
if self.buffer:
1044+
for _ in xrange(indent):
1045+
self.tab()
1046+
1047+
self.evaluating = False
1048+
#map(self.push, self.history)
1049+
#^-- That's how simple this method was at first :(
1050+
1051+
def write(self, s):
1052+
"""For overriding stdout defaults"""
1053+
if '\x04' in s:
1054+
for block in s.split('\x04'):
1055+
self.write(block)
1056+
return
1057+
if s.rstrip() and '\x03' in s:
1058+
t = s.split('\x03')[1]
1059+
else:
1060+
t = s
1061+
1062+
if not py3 and isinstance(t, unicode):
1063+
t = t.encode(getpreferredencoding())
1064+
1065+
if not self.stdout_hist:
1066+
self.stdout_hist = t
1067+
else:
1068+
self.stdout_hist += t
1069+
1070+
self.echo(s)
1071+
self.s_hist.append(s.rstrip())
1072+
1073+
10011074
def show_list(self, items, topline=None, current_item=None):
10021075
shared = Struct()
10031076
shared.cols = 0

bpython/gtk_.py

Lines changed: 86 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@
3333
import os
3434
import sys
3535
from locale import LC_ALL, getpreferredencoding, setlocale
36+
from xmlrpclib import ServerProxy, Error as XMLRPCError
37+
from string import Template
38+
from urllib import quote as urlquote
3639

3740
import gobject
3841
import gtk
@@ -42,6 +45,7 @@
4245
from bpython.formatter import theme_map
4346
import bpython.args
4447

48+
py3 = sys.version_info[0] == 3
4549

4650
_COLORS = dict(b='blue', c='cyan', g='green', m='magenta', r='red',
4751
w='white', y='yellow', k='black', d='black')
@@ -136,8 +140,13 @@ class Statusbar(gtk.Statusbar):
136140
def __init__(self):
137141
gtk.Statusbar.__init__(self)
138142

139-
context_id = self.get_context_id('StatusBar')
140-
# self.push(context_id, text)
143+
self.context_id = self.get_context_id('StatusBar')
144+
145+
def message(self, s, n=3):
146+
self.push(self.context_id, s)
147+
148+
def prompt(self, s):
149+
pass
141150

142151

143152
class SuggestionWindow(gtk.Window):
@@ -281,6 +290,7 @@ def __init__(self, interpreter, config):
281290
self.modify_base('normal', gtk.gdk.color_parse(_COLORS[self.config.color_gtk_scheme['background']]))
282291

283292
self.text_buffer = self.get_buffer()
293+
self.statusbar = Statusbar()
284294
tags = dict()
285295
for (name, value) in self.config.color_gtk_scheme.iteritems():
286296
tag = tags[name] = self.text_buffer.create_tag(name)
@@ -563,6 +573,68 @@ def on_suggestion_selection_changed(self, selection, word):
563573
self.get_cursor_iter())
564574
self.text_buffer.insert_at_cursor(word)
565575

576+
def pastebin(self, widget):
577+
"""Upload to a pastebin and display the URL in the status bar."""
578+
579+
# FIXME cleanup
580+
response = False
581+
582+
if self.config.pastebin_confirm:
583+
dialog = gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_INFO, gtk.BUTTONS_YES_NO,
584+
"Pastebin buffer?")
585+
response = True if dialog.run() == gtk.RESPONSE_YES else False
586+
dialog.destroy()
587+
else:
588+
response = True
589+
590+
if not response:
591+
self.statusbar.message("Pastebin aborted")
592+
return
593+
# end FIXME
594+
595+
pasteservice = ServerProxy(self.config.pastebin_url)
596+
597+
s = self.stdout_hist
598+
599+
if s == self.prev_pastebin_content:
600+
self.statusbar.message('Duplicate pastebin. Previous URL: ' +
601+
self.prev_pastebin_url)
602+
return
603+
604+
self.prev_pastebin_content = s
605+
606+
self.statusbar.message('Posting data to pastebin...')
607+
try:
608+
paste_id = pasteservice.pastes.newPaste('pycon', s)
609+
except XMLRPCError, e:
610+
self.statusbar.message('Upload failed: %s' % (str(e), ) )
611+
return
612+
613+
paste_url_template = Template(self.config.pastebin_show_url)
614+
paste_id = urlquote(paste_id)
615+
paste_url = paste_url_template.safe_substitute(paste_id=paste_id)
616+
self.prev_pastebin_url = paste_url
617+
self.statusbar.message('Pastebin URL: %s' % (paste_url, ), 10)
618+
619+
def write(self, s):
620+
"""For overriding stdout defaults"""
621+
if '\x04' in s:
622+
for block in s.split('\x04'):
623+
self.write(block)
624+
return
625+
if s.rstrip() and '\x03' in s:
626+
t = s.split('\x03')[1]
627+
else:
628+
t = s
629+
630+
if not py3 and isinstance(t, unicode):
631+
t = t.encode(getpreferredencoding())
632+
633+
self.echo(s)
634+
self.s_hist.append(s.rstrip())
635+
636+
637+
566638
def prompt(self, more):
567639
"""
568640
Show the appropriate Python prompt.
@@ -618,6 +690,12 @@ def set_cursor_to_valid_insert_position(self):
618690
if line_start_iter.compare(cursor_iter) > 0:
619691
self.text_buffer.place_cursor(line_start_iter)
620692

693+
@property
694+
def stdout_hist(self):
695+
bounds = self.text_buffer.get_bounds()
696+
text = self.text_buffer.get_text(bounds[0], bounds[1])
697+
return text
698+
621699
def writetb(self, lines):
622700
with ExceptionManager(ExceptionDialog,
623701
'An error occured while trying to display '
@@ -693,7 +771,11 @@ def main(args=None):
693771

694772
filem = gtk.MenuItem("File")
695773
filem.set_submenu(filemenu)
696-
774+
775+
pastebin = gtk.MenuItem("Pastebin")
776+
pastebin.connect("activate", repl_widget.pastebin)
777+
filemenu.append(pastebin)
778+
697779
exit = gtk.MenuItem("Exit")
698780
exit.connect("activate", gtk.main_quit)
699781
filemenu.append(exit)
@@ -711,7 +793,7 @@ def main(args=None):
711793
sw.add(repl_widget)
712794
container.add(sw)
713795

714-
sb = Statusbar()
796+
sb = repl_widget.statusbar
715797
container.pack_end(sb, expand=False)
716798

717799
parent.show_all()

bpython/repl.py

Lines changed: 0 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,6 @@ def __init__(self, interp, config):
284284
self.interp.syntaxerror_callback = self.clear_current_line
285285
self.match = False
286286
self.rl_history = History()
287-
self.stdout_hist = ''
288287
self.s_hist = []
289288
self.history = []
290289
self.evaluating = False
@@ -598,12 +597,6 @@ def next_indentation(self):
598597
indentation = 0
599598
return indentation
600599

601-
def getstdout(self):
602-
"""This method returns the 'spoofed' stdout buffer, for writing to a
603-
file or sending to a pastebin or whatever."""
604-
605-
return self.stdout_hist + '\n'
606-
607600
def formatforfile(self, s):
608601
"""Format the stdout buffer to something suitable for writing to disk,
609602
i.e. without >>> and ... at input lines and with "# OUT: " prepended to
@@ -710,70 +703,6 @@ def undo(self, n=1):
710703

711704
self.rl_history.entries = entries
712705

713-
def reevaluate(self):
714-
"""Clear the buffer, redraw the screen and re-evaluate the history"""
715-
716-
self.evaluating = True
717-
self.stdout_hist = ''
718-
self.f_string = ''
719-
self.buffer = []
720-
self.scr.erase()
721-
self.s_hist = []
722-
# Set cursor position to -1 to prevent paren matching
723-
self.cpos = -1
724-
725-
self.prompt(False)
726-
727-
self.iy, self.ix = self.scr.getyx()
728-
for line in self.history:
729-
if py3:
730-
self.stdout_hist += line + '\n'
731-
else:
732-
self.stdout_hist += line.encode(getpreferredencoding()) + '\n'
733-
self.print_line(line)
734-
self.s_hist[-1] += self.f_string
735-
# I decided it was easier to just do this manually
736-
# than to make the print_line and history stuff more flexible.
737-
self.scr.addstr('\n')
738-
more = self.push(line)
739-
self.prompt(more)
740-
self.iy, self.ix = self.scr.getyx()
741-
742-
self.cpos = 0
743-
indent = next_indentation(self.s, self.config.tab_length)
744-
self.s = ''
745-
self.scr.refresh()
746-
747-
if self.buffer:
748-
for _ in xrange(indent):
749-
self.tab()
750-
751-
self.evaluating = False
752-
#map(self.push, self.history)
753-
#^-- That's how simple this method was at first :(
754-
755-
def write(self, s):
756-
"""For overriding stdout defaults"""
757-
if '\x04' in s:
758-
for block in s.split('\x04'):
759-
self.write(block)
760-
return
761-
if s.rstrip() and '\x03' in s:
762-
t = s.split('\x03')[1]
763-
else:
764-
t = s
765-
766-
if not py3 and isinstance(t, unicode):
767-
t = t.encode(getpreferredencoding())
768-
769-
if not self.stdout_hist:
770-
self.stdout_hist = t
771-
else:
772-
self.stdout_hist += t
773-
774-
self.echo(s)
775-
self.s_hist.append(s.rstrip())
776-
777706
def flush(self):
778707
"""Olivier Grisel brought it to my attention that the logging
779708
module tries to call this method, since it makes assumptions

0 commit comments

Comments
 (0)