Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/terminal.py
diff options
context:
space:
mode:
authorroot <root@ghunt-desktop.(none)>2010-10-30 19:36:14 (GMT)
committer root <root@ghunt-desktop.(none)>2010-10-30 19:36:14 (GMT)
commit966312ba98d729177238f4663d789a789663eb2e (patch)
treee39e90f5699170b3cc05e03fdd8b2e05110d9498 /terminal.py
parent7e0dfb3e1df6ffa0194048d93ac4f55df00107a0 (diff)
start working on release 7, include all new files, breakpoints still need work
Diffstat (limited to 'terminal.py')
-rw-r--r--terminal.py295
1 files changed, 295 insertions, 0 deletions
diff --git a/terminal.py b/terminal.py
new file mode 100644
index 0000000..697037d
--- /dev/null
+++ b/terminal.py
@@ -0,0 +1,295 @@
+# Copyright (C) 2007, Eduardo Silva <edsiper@gmail.com>.
+# Copyright (C) 2008, One Laptop Per Child
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+import os, os.path, ConfigParser, sys
+
+from gettext import gettext as _
+
+# Initialize logging.
+import logging
+_logger = logging.getLogger('PyDebug')
+
+import gtk
+import vte
+import pango
+
+from sugar.graphics.toolbutton import ToolButton
+import sugar.graphics.toolbutton
+import sugar.activity.activity
+import sugar.env
+import sugar.activity.bundlebuilder
+
+from shutil import copy, copytree
+
+MASKED_ENVIRONMENT = [
+ 'DBUS_SESSION_BUS_ADDRESS',
+ 'PPID'
+]
+
+
+class Terminal():
+
+ def __init__(self,activity):
+ self.terminal_notebook = gtk.Notebook()
+ self._create_tab({'cwd':self.sugar_bundle_path})
+ self._create_tab({'cwd':self.activity_playpen})
+
+ #start the debugger user interface
+ #alias_cmd = 'alias go="%s/bin/ipython.py -gthread"\n'%(self.sugar_bundle_path,)
+ alias_cmd = 'alias go="%s/bin/ipython.py "\n'%(self.sugar_bundle_path,)
+ self.feed_virtual_terminal(0,alias_cmd)
+
+ #self.feed_virtual_terminal(0,'%s/bin/ipython.py -gthread\n'%self.sugar_bundle_path)
+ self.feed_virtual_terminal(0,'%s/bin/ipython.py \n'%self.sugar_bundle_path)
+
+ #the following become obsolete when start_debug starts automatically via ipython_config.py
+ #cmd = 'run ' + os.path.join(self.sugar_bundle_path,'bin','start_debug.py') + '\n'
+ #self.feed_virtual_terminal(0,cmd)
+
+ def _get_terminal_canvas(self):
+ self.terminal_notebook.set_property("tab-pos", gtk.POS_BOTTOM)
+ self.terminal_notebook.set_scrollable(True)
+ self.terminal_notebook.show()
+ return self.terminal_notebook
+
+ def _open_tab_cb(self, btn):
+ index = self._create_tab(None)
+ self.terminal_notebook.page = index
+
+ def _close_tab_cb(self, btn):
+ self._close_tab(self.terminal_notebook.props.page)
+
+ def _prev_tab_cb(self, btn):
+ if self.terminal_notebook.props.page == 0:
+ self.terminal_notebook.props.page = self.terminal_notebook.get_n_pages() - 1
+ else:
+ self.terminal_notebook.props.page = self.terminal_notebook.props.page - 1
+ vt = self.terminal_notebook.get_nth_page(self.terminal_notebook.get_current_page()).vt
+ vt.grab_focus()
+
+ def _next_tab_cb(self, btn):
+ if self.terminal_notebook.props.page == self.terminal_notebook.get_n_pages() - 1:
+ self.terminal_notebook.props.page = 0
+ else:
+ self.terminal_notebook.props.page = self.terminal_notebook.props.page + 1
+ vt = self.terminal_notebook.get_nth_page(self.terminal_notebook.get_current_page()).vt
+ vt.grab_focus()
+
+ def _close_tab(self, index):
+ self.terminal_notebook.remove_page(index)
+ if self.terminal_notebook.get_n_pages() == 0:
+ self.close()
+
+ def _tab_child_exited_cb(self, vt):
+ for i in range(self.terminal_notebook.get_n_pages()):
+ if self.terminal_notebook.get_nth_page(i).vt == vt:
+ self._close_tab(i)
+ return
+
+ def _tab_title_changed_cb(self, vt):
+ for i in range(self.terminal_notebook.get_n_pages()):
+ if self.terminal_notebook.get_nth_page(i).vt == vt:
+ label = self.terminal_notebook.get_nth_page(i).label
+ label.set_text(vt.get_window_title())
+ return
+
+ def _drag_data_received_cb(self, widget, context, x, y, selection, target, time):
+ widget.feed_child(selection.data)
+ context.finish(True, False, time)
+ return True
+
+ def _create_tab(self, tab_state):
+ vt = vte.Terminal()
+ vt.connect("child-exited", self._tab_child_exited_cb)
+ vt.connect("window-title-changed", self._tab_title_changed_cb)
+
+ vt.drag_dest_set(gtk.DEST_DEFAULT_MOTION|gtk.DEST_DEFAULT_DROP,
+ [('text/plain', 0, 0), ('STRING', 0, 1)],
+ gtk.gdk.ACTION_DEFAULT|
+ gtk.gdk.ACTION_COPY)
+ vt.connect('drag_data_received', self._drag_data_received_cb)
+
+ self._configure_vt(vt)
+
+ vt.show()
+
+ label = gtk.Label()
+
+ scrollbar = gtk.VScrollbar(vt.get_adjustment())
+ scrollbar.show()
+
+ box = gtk.HBox()
+ box.pack_start(vt)
+ box.pack_start(scrollbar)
+
+ box.vt = vt
+ box.label = label
+
+ index = self.terminal_notebook.append_page(box, label)
+ if index == 0:
+ vt.set_colors(gtk.gdk.color_parse('#000000'), gtk.gdk.color_parse('#FFFFCC'), [])
+ self.terminal_notebook.show_all()
+
+ # Uncomment this to only show the tab bar when there is at least one tab.
+ # I think it's useful to always see it, since it displays the 'window title'.
+ #self.terminal_notebook.props.show_tabs = self.terminal_notebook.get_n_pages() > 1
+
+ # Launch the default shell in the HOME directory.
+ os.chdir(os.environ["HOME"])
+
+ if tab_state:
+ # Restore the environment.
+ # This is currently not enabled.
+ env = tab_state.get('env',[])
+
+ filtered_env = []
+ for e in env:
+ var, sep, value = e.partition('=')
+ if var not in MASKED_ENVIRONMENT:
+ filtered_env.append(var + sep + value)
+
+ # TODO: Make the shell restore these environment variables, then clear out TERMINAL_ENV.
+ #os.environ['TERMINAL_ENV'] = '\n'.join(filtered_env)
+
+ # Restore the working directory.
+ if tab_state.has_key('cwd'):
+ os.chdir(tab_state['cwd'])
+
+ # Restore the scrollback buffer.
+ if tab_state.has_key('scrollback'):
+ for l in tab_state['scrollback']:
+ vt.feed(l + '\r\n')
+
+ box.pid = vt.fork_command()
+
+ self.terminal_notebook.props.page = index
+ vt.grab_focus()
+
+ return index
+
+ def feed_virtual_terminal(self,terminal,command):
+ if terminal > len(self.terminal_notebook)-1 or terminal < 0:
+ _logger.debug('in feed_virtual_terminal: terminal out of bounds %s'%terminal)
+ return
+ self.terminal_notebook.set_current_page(terminal)
+ vt = self.terminal_notebook.get_nth_page(terminal).vt
+ vt.feed_child(command)
+
+ def message_terminal(self,terminal,command):
+ if terminal > len(self.terminal_notebook)-1 or terminal < 0:
+ _logging.debug('in feed_virtual_terminal: terminal out of bounds %s'%terminal)
+ return
+ self.terminal_notebook.set_current_page(terminal)
+ vt = self.terminal_notebook.get_nth_page(terminal).vt
+ vt.feed(command)
+
+ def _copy_cb(self, button):
+ vt = self.terminal_notebook.get_nth_page(self.terminal_notebook.get_current_page()).vt
+ if vt.get_has_selection():
+ vt.copy_clipboard()
+
+ def _paste_cb(self, button):
+ vt = self.terminal_notebook.get_nth_page(self.terminal_notebook.get_current_page()).vt
+ vt.paste_clipboard()
+
+ def _become_root_cb(self, button):
+ vt = self.terminal_notebook.get_nth_page(self.terminal_notebook.get_current_page()).vt
+ vt.feed('\r\n')
+ vt.fork_command("/bin/su", ('/bin/su', '-'))
+
+ def set_terminal_focus(self):
+ self.terminal_notebook.grab_focus()
+ page = self.terminal_notebook.get_nth_page(self.terminal_notebook.get_current_page())
+ page.grab_focus()
+ vt = page.vt
+ vt.grab_focus()
+ _logger.debug('attemped to grab focus')
+ return False
+
+ def _fullscreen_cb(self, btn):
+ self.fullscreen()
+
+ def _key_press_cb(self, window, event):
+ # Escape keypresses are routed directly to the vte and then dropped.
+ # This hack prevents Sugar from hijacking them and canceling fullscreen mode.
+ if gtk.gdk.keyval_name(event.keyval) == 'Escape':
+ vt = self.terminal_notebook.get_nth_page(self.terminal_notebook.get_current_page()).vt
+ vt.event(event)
+ return True
+
+ return False
+
+
+
+ def _get_conf(self, conf, var, default):
+ if conf.has_option('terminal', var):
+ if isinstance(default, bool):
+ return conf.getboolean('terminal', var)
+ elif isinstance(default, int):
+ return conf.getint('terminal', var)
+ else:
+ return conf.get('terminal', var)
+ else:
+ conf.set('terminal', var, default)
+
+ return default
+
+ def _configure_vt(self, vt):
+ conf = ConfigParser.ConfigParser()
+ conf_file = os.path.join(os.environ['HOME'], 'terminalrc')
+
+ if os.path.isfile(conf_file):
+ f = open(conf_file, 'r')
+ conf.readfp(f)
+ f.close()
+ else:
+ conf.add_section('terminal')
+
+ font = self._get_conf(conf, 'font', 'Monospace')
+ vt.set_font(pango.FontDescription(font))
+
+ fg_color = self._get_conf(conf, 'fg_color', '#000000')
+ bg_color = self._get_conf(conf, 'bg_color', '#FFFFFF')
+ vt.set_colors(gtk.gdk.color_parse(fg_color), gtk.gdk.color_parse(bg_color), [])
+
+ blink = self._get_conf(conf, 'cursor_blink', False)
+ vt.set_cursor_blinks(blink)
+
+ bell = self._get_conf(conf, 'bell', False)
+ vt.set_audible_bell(bell)
+
+ scrollback_lines = self._get_conf(conf, 'scrollback_lines', 1000)
+ vt.set_scrollback_lines(scrollback_lines)
+
+ vt.set_allow_bold(True)
+
+ scroll_key = self._get_conf(conf, 'scroll_on_keystroke', True)
+ vt.set_scroll_on_keystroke(scroll_key)
+
+ scroll_output = self._get_conf(conf, 'scroll_on_output', False)
+ vt.set_scroll_on_output(scroll_output)
+
+ emulation = self._get_conf(conf, 'emulation', 'xterm')
+ vt.set_emulation(emulation)
+
+ visible_bell = self._get_conf(conf, 'visible_bell', False)
+ vt.set_visible_bell(visible_bell)
+
+ conf.write(open(conf_file, 'w'))
+
+
+