diff options
author | Perberos <[email protected]> | 2011-11-07 16:46:58 -0300 |
---|---|---|
committer | Perberos <[email protected]> | 2011-11-07 16:46:58 -0300 |
commit | 528c1e5ff51e213936e800fc5a9a25da99c0bdf2 (patch) | |
tree | 77f8aa456b09367ba81f04d4562fc935f898a951 /plugins/pythonconsole | |
download | pluma-528c1e5ff51e213936e800fc5a9a25da99c0bdf2.tar.bz2 pluma-528c1e5ff51e213936e800fc5a9a25da99c0bdf2.tar.xz |
initial
Diffstat (limited to 'plugins/pythonconsole')
-rwxr-xr-x | plugins/pythonconsole/Makefile.am | 15 | ||||
-rwxr-xr-x | plugins/pythonconsole/pythonconsole.gedit-plugin.desktop.in | 10 | ||||
-rwxr-xr-x | plugins/pythonconsole/pythonconsole/Makefile.am | 17 | ||||
-rwxr-xr-x | plugins/pythonconsole/pythonconsole/__init__.py | 78 | ||||
-rwxr-xr-x | plugins/pythonconsole/pythonconsole/config.py | 134 | ||||
-rwxr-xr-x | plugins/pythonconsole/pythonconsole/config.ui | 107 | ||||
-rwxr-xr-x | plugins/pythonconsole/pythonconsole/console.py | 370 |
7 files changed, 731 insertions, 0 deletions
diff --git a/plugins/pythonconsole/Makefile.am b/plugins/pythonconsole/Makefile.am new file mode 100755 index 00000000..c27227f3 --- /dev/null +++ b/plugins/pythonconsole/Makefile.am @@ -0,0 +1,15 @@ +# Python Console Plugin +SUBDIRS = pythonconsole +plugindir = $(GEDIT_PLUGINS_LIBS_DIR) + +plugin_in_files = pythonconsole.gedit-plugin.desktop.in +%.gedit-plugin: %.gedit-plugin.desktop.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< $@ -d -u -c $(top_builddir)/po/.intltool-merge-cache + +plugin_DATA = $(plugin_in_files:.gedit-plugin.desktop.in=.gedit-plugin) + +EXTRA_DIST = $(plugin_in_files) + +CLEANFILES = $(plugin_DATA) +DISTCLEANFILES = $(plugin_DATA) + +-include $(top_srcdir)/git.mk diff --git a/plugins/pythonconsole/pythonconsole.gedit-plugin.desktop.in b/plugins/pythonconsole/pythonconsole.gedit-plugin.desktop.in new file mode 100755 index 00000000..8cc65648 --- /dev/null +++ b/plugins/pythonconsole/pythonconsole.gedit-plugin.desktop.in @@ -0,0 +1,10 @@ +[Gedit Plugin] +Loader=python +Module=pythonconsole +IAge=2 +_Name=Python Console +_Description=Interactive Python console standing in the bottom panel +Icon=mate-mime-text-x-python +Authors=Steve Frécinaux <[email protected]> +Copyright=Copyright © 2006 Steve Frécinaux +Website=http://www.gedit.org diff --git a/plugins/pythonconsole/pythonconsole/Makefile.am b/plugins/pythonconsole/pythonconsole/Makefile.am new file mode 100755 index 00000000..7aa91fe9 --- /dev/null +++ b/plugins/pythonconsole/pythonconsole/Makefile.am @@ -0,0 +1,17 @@ +# Python console plugin + +plugindir = $(GEDIT_PLUGINS_LIBS_DIR)/pythonconsole +plugin_PYTHON = \ + __init__.py \ + console.py \ + config.py + +uidir = $(GEDIT_PLUGINS_DATA_DIR)/pythonconsole/ui +ui_DATA = config.ui + +EXTRA_DIST = $(ui_DATA) + +CLEANFILES = +DISTCLEANFILES = + +-include $(top_srcdir)/git.mk diff --git a/plugins/pythonconsole/pythonconsole/__init__.py b/plugins/pythonconsole/pythonconsole/__init__.py new file mode 100755 index 00000000..60f70e9f --- /dev/null +++ b/plugins/pythonconsole/pythonconsole/__init__.py @@ -0,0 +1,78 @@ +# -*- coding: utf-8 -*- + +# __init__.py -- plugin object +# +# Copyright (C) 2006 - Steve Frécinaux +# +# 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Parts from "Interactive Python-GTK Console" (stolen from epiphany's console.py) +# Copyright (C), 1998 James Henstridge <[email protected]> +# Copyright (C), 2005 Adam Hooper <[email protected]> +# Bits from gedit Python Console Plugin +# Copyrignt (C), 2005 Raphaël Slinckx + +import gtk +import gedit + +from console import PythonConsole +from config import PythonConsoleConfigDialog +from config import PythonConsoleConfig + +PYTHON_ICON = 'mate-mime-text-x-python' + +class PythonConsolePlugin(gedit.Plugin): + def __init__(self): + gedit.Plugin.__init__(self) + self.dlg = None + + def activate(self, window): + console = PythonConsole(namespace = {'__builtins__' : __builtins__, + 'gedit' : gedit, + 'window' : window}) + console.eval('print "You can access the main window through ' \ + '\'window\' :\\n%s" % window', False) + bottom = window.get_bottom_panel() + image = gtk.Image() + image.set_from_icon_name(PYTHON_ICON, gtk.ICON_SIZE_MENU) + bottom.add_item(console, _('Python Console'), image) + window.set_data('PythonConsolePluginInfo', console) + + def deactivate(self, window): + console = window.get_data("PythonConsolePluginInfo") + console.stop() + window.set_data("PythonConsolePluginInfo", None) + bottom = window.get_bottom_panel() + bottom.remove_item(console) + +def create_configure_dialog(self): + + if not self.dlg: + self.dlg = PythonConsoleConfigDialog(self.get_data_dir()) + + dialog = self.dlg.dialog() + window = gedit.app_get_default().get_active_window() + if window: + dialog.set_transient_for(window) + + return dialog + +# Here we dynamically insert create_configure_dialog based on if configuration +# is enabled. This has to be done like this because gedit checks if a plugin +# is configurable solely on the fact that it has this member defined or not +if PythonConsoleConfig.enabled(): + PythonConsolePlugin.create_configure_dialog = create_configure_dialog + +# ex:et:ts=4: diff --git a/plugins/pythonconsole/pythonconsole/config.py b/plugins/pythonconsole/pythonconsole/config.py new file mode 100755 index 00000000..fed4699b --- /dev/null +++ b/plugins/pythonconsole/pythonconsole/config.py @@ -0,0 +1,134 @@ +# -*- coding: utf-8 -*- + +# config.py -- Config dialog +# +# Copyright (C) 2008 - B. Clausius +# +# 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Parts from "Interactive Python-GTK Console" (stolen from epiphany's console.py) +# Copyright (C), 1998 James Henstridge <[email protected]> +# Copyright (C), 2005 Adam Hooper <[email protected]> +# Bits from gedit Python Console Plugin +# Copyrignt (C), 2005 Raphaël Slinckx + +import os +import gtk + +__all__ = ('PythonConsoleConfig', 'PythonConsoleConfigDialog') + +MATECONF_KEY_BASE = '/apps/gedit-2/plugins/pythonconsole' +MATECONF_KEY_COMMAND_COLOR = MATECONF_KEY_BASE + '/command-color' +MATECONF_KEY_ERROR_COLOR = MATECONF_KEY_BASE + '/error-color' + +DEFAULT_COMMAND_COLOR = '#314e6c' # Blue Shadow +DEFAULT_ERROR_COLOR = '#990000' # Accent Red Dark + +class PythonConsoleConfig(object): + try: + import mateconf + except ImportError: + mateconf = None + + def __init__(self): + pass + + @staticmethod + def enabled(): + return PythonConsoleConfig.mateconf != None + + @staticmethod + def add_handler(handler): + if PythonConsoleConfig.mateconf: + PythonConsoleConfig.mateconf.client_get_default().notify_add(MATECONF_KEY_BASE, handler) + + color_command = property( + lambda self: self.mateconf_get_str(MATECONF_KEY_COMMAND_COLOR, DEFAULT_COMMAND_COLOR), + lambda self, value: self.mateconf_set_str(MATECONF_KEY_COMMAND_COLOR, value)) + + color_error = property( + lambda self: self.mateconf_get_str(MATECONF_KEY_ERROR_COLOR, DEFAULT_ERROR_COLOR), + lambda self, value: self.mateconf_set_str(MATECONF_KEY_ERROR_COLOR, value)) + + @staticmethod + def mateconf_get_str(key, default=''): + if not PythonConsoleConfig.mateconf: + return default + + val = PythonConsoleConfig.mateconf.client_get_default().get(key) + if val is not None and val.type == mateconf.VALUE_STRING: + return val.get_string() + else: + return default + + @staticmethod + def mateconf_set_str(key, value): + if not PythonConsoleConfig.mateconf: + return + + v = PythonConsoleConfig.mateconf.Value(mateconf.VALUE_STRING) + v.set_string(value) + PythonConsoleConfig.mateconf.client_get_default().set(key, v) + +class PythonConsoleConfigDialog(object): + + def __init__(self, datadir): + object.__init__(self) + self._dialog = None + self._ui_path = os.path.join(datadir, 'ui', 'config.ui') + self.config = PythonConsoleConfig() + + def dialog(self): + if self._dialog is None: + self._ui = gtk.Builder() + self._ui.add_from_file(self._ui_path) + + self.set_colorbutton_color(self._ui.get_object('colorbutton-command'), + self.config.color_command) + self.set_colorbutton_color(self._ui.get_object('colorbutton-error'), + self.config.color_error) + + self._ui.connect_signals(self) + + self._dialog = self._ui.get_object('dialog-config') + self._dialog.show_all() + else: + self._dialog.present() + + return self._dialog + + @staticmethod + def set_colorbutton_color(colorbutton, value): + try: + color = gtk.gdk.color_parse(value) + except ValueError: + pass # Default color in config.ui used + else: + colorbutton.set_color(color) + + def on_dialog_config_response(self, dialog, response_id): + self._dialog.destroy() + + def on_dialog_config_destroy(self, dialog): + self._dialog = None + self._ui = None + + def on_colorbutton_command_color_set(self, colorbutton): + self.config.color_command = colorbutton.get_color().to_string() + + def on_colorbutton_error_color_set(self, colorbutton): + self.config.color_error = colorbutton.get_color().to_string() + +# ex:et:ts=4: diff --git a/plugins/pythonconsole/pythonconsole/config.ui b/plugins/pythonconsole/pythonconsole/config.ui new file mode 100755 index 00000000..4ffe26f6 --- /dev/null +++ b/plugins/pythonconsole/pythonconsole/config.ui @@ -0,0 +1,107 @@ +<?xml version="1.0"?> +<interface> + <requires lib="gtk+" version="2.14"/> + <!-- interface-naming-policy toplevel-contextual --> + <object class="GtkDialog" id="dialog-config"> + <property name="window_position">center-on-parent</property> + <property name="destroy_with_parent">True</property> + <property name="type_hint">dialog</property> + <property name="has_separator">False</property> + <signal name="destroy" handler="on_dialog_config_destroy"/> + <signal name="response" handler="on_dialog_config_response"/> + <child internal-child="vbox"> + <object class="GtkVBox" id="dialog-vbox1"> + <property name="visible">True</property> + <child> + <object class="GtkTable" id="table2"> + <property name="visible">True</property> + <property name="border_width">6</property> + <property name="n_rows">2</property> + <property name="n_columns">2</property> + <property name="column_spacing">6</property> + <property name="row_spacing">6</property> + <child> + <object class="GtkLabel" id="label-command"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">C_ommand color:</property> + <property name="use_underline">True</property> + <property name="mnemonic_widget">colorbutton-command</property> + </object> + </child> + <child> + <object class="GtkLabel" id="label-error"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">_Error color:</property> + <property name="use_underline">True</property> + <property name="mnemonic_widget">colorbutton-error</property> + </object> + <packing> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + </packing> + </child> + <child> + <object class="GtkColorButton" id="colorbutton-command"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="color">#31314e4e6c6c</property> + <signal name="color_set" handler="on_colorbutton_command_color_set"/> + </object> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + </packing> + </child> + <child> + <object class="GtkColorButton" id="colorbutton-error"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="color">#999900000000</property> + <signal name="color_set" handler="on_colorbutton_error_color_set"/> + </object> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + </packing> + </child> + </object> + <packing> + <property name="position">1</property> + </packing> + </child> + <child internal-child="action_area"> + <object class="GtkHButtonBox" id="dialog-action_area1"> + <property name="visible">True</property> + <property name="layout_style">end</property> + <child> + <object class="GtkButton" id="button1"> + <property name="label">gtk-close</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="use_stock">True</property> + </object> + <packing> + <property name="position">0</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="pack_type">end</property> + <property name="position">0</property> + </packing> + </child> + </object> + </child> + <action-widgets> + <action-widget response="-7">button1</action-widget> + </action-widgets> + </object> +</interface> diff --git a/plugins/pythonconsole/pythonconsole/console.py b/plugins/pythonconsole/pythonconsole/console.py new file mode 100755 index 00000000..e9d7a331 --- /dev/null +++ b/plugins/pythonconsole/pythonconsole/console.py @@ -0,0 +1,370 @@ +# -*- coding: utf-8 -*- + +# pythonconsole.py -- Console widget +# +# Copyright (C) 2006 - Steve Frécinaux +# +# 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Parts from "Interactive Python-GTK Console" (stolen from epiphany's console.py) +# Copyright (C), 1998 James Henstridge <[email protected]> +# Copyright (C), 2005 Adam Hooper <[email protected]> +# Bits from gedit Python Console Plugin +# Copyrignt (C), 2005 Raphaël Slinckx + +import string +import sys +import re +import traceback +import gobject +import gtk +import pango + +from config import PythonConsoleConfig + +__all__ = ('PythonConsole', 'OutFile') + +class PythonConsole(gtk.ScrolledWindow): + + __gsignals__ = { + 'grab-focus' : 'override', + } + + def __init__(self, namespace = {}): + gtk.ScrolledWindow.__init__(self) + + self.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) + self.set_shadow_type(gtk.SHADOW_IN) + self.view = gtk.TextView() + self.view.modify_font(pango.FontDescription('Monospace')) + self.view.set_editable(True) + self.view.set_wrap_mode(gtk.WRAP_WORD_CHAR) + self.add(self.view) + self.view.show() + + buffer = self.view.get_buffer() + self.normal = buffer.create_tag("normal") + self.error = buffer.create_tag("error") + self.command = buffer.create_tag("command") + + PythonConsoleConfig.add_handler(self.apply_preferences) + self.apply_preferences() + + self.__spaces_pattern = re.compile(r'^\s+') + self.namespace = namespace + + self.block_command = False + + # Init first line + buffer.create_mark("input-line", buffer.get_end_iter(), True) + buffer.insert(buffer.get_end_iter(), ">>> ") + buffer.create_mark("input", buffer.get_end_iter(), True) + + # Init history + self.history = [''] + self.history_pos = 0 + self.current_command = '' + self.namespace['__history__'] = self.history + + # Set up hooks for standard output. + self.stdout = OutFile(self, sys.stdout.fileno(), self.normal) + self.stderr = OutFile(self, sys.stderr.fileno(), self.error) + + # Signals + self.view.connect("key-press-event", self.__key_press_event_cb) + buffer.connect("mark-set", self.__mark_set_cb) + + def do_grab_focus(self): + self.view.grab_focus() + + def apply_preferences(self, *args): + config = PythonConsoleConfig() + self.error.set_property("foreground", config.color_error) + self.command.set_property("foreground", config.color_command) + + def stop(self): + self.namespace = None + + def __key_press_event_cb(self, view, event): + modifier_mask = gtk.accelerator_get_default_mod_mask() + event_state = event.state & modifier_mask + + if event.keyval == gtk.keysyms.d and event_state == gtk.gdk.CONTROL_MASK: + self.destroy() + + elif event.keyval == gtk.keysyms.Return and event_state == gtk.gdk.CONTROL_MASK: + # Get the command + buffer = view.get_buffer() + inp_mark = buffer.get_mark("input") + inp = buffer.get_iter_at_mark(inp_mark) + cur = buffer.get_end_iter() + line = buffer.get_text(inp, cur) + self.current_command = self.current_command + line + "\n" + self.history_add(line) + + # Prepare the new line + cur = buffer.get_end_iter() + buffer.insert(cur, "\n... ") + cur = buffer.get_end_iter() + buffer.move_mark(inp_mark, cur) + + # Keep indentation of precendent line + spaces = re.match(self.__spaces_pattern, line) + if spaces is not None: + buffer.insert(cur, line[spaces.start() : spaces.end()]) + cur = buffer.get_end_iter() + + buffer.place_cursor(cur) + gobject.idle_add(self.scroll_to_end) + return True + + elif event.keyval == gtk.keysyms.Return: + # Get the marks + buffer = view.get_buffer() + lin_mark = buffer.get_mark("input-line") + inp_mark = buffer.get_mark("input") + + # Get the command line + inp = buffer.get_iter_at_mark(inp_mark) + cur = buffer.get_end_iter() + line = buffer.get_text(inp, cur) + self.current_command = self.current_command + line + "\n" + self.history_add(line) + + # Make the line blue + lin = buffer.get_iter_at_mark(lin_mark) + buffer.apply_tag(self.command, lin, cur) + buffer.insert(cur, "\n") + + cur_strip = self.current_command.rstrip() + + if cur_strip.endswith(":") \ + or (self.current_command[-2:] != "\n\n" and self.block_command): + # Unfinished block command + self.block_command = True + com_mark = "... " + elif cur_strip.endswith("\\"): + com_mark = "... " + else: + # Eval the command + self.__run(self.current_command) + self.current_command = '' + self.block_command = False + com_mark = ">>> " + + # Prepare the new line + cur = buffer.get_end_iter() + buffer.move_mark(lin_mark, cur) + buffer.insert(cur, com_mark) + cur = buffer.get_end_iter() + buffer.move_mark(inp_mark, cur) + buffer.place_cursor(cur) + gobject.idle_add(self.scroll_to_end) + return True + + elif event.keyval == gtk.keysyms.KP_Down or event.keyval == gtk.keysyms.Down: + # Next entry from history + view.emit_stop_by_name("key_press_event") + self.history_down() + gobject.idle_add(self.scroll_to_end) + return True + + elif event.keyval == gtk.keysyms.KP_Up or event.keyval == gtk.keysyms.Up: + # Previous entry from history + view.emit_stop_by_name("key_press_event") + self.history_up() + gobject.idle_add(self.scroll_to_end) + return True + + elif event.keyval == gtk.keysyms.KP_Left or event.keyval == gtk.keysyms.Left or \ + event.keyval == gtk.keysyms.BackSpace: + buffer = view.get_buffer() + inp = buffer.get_iter_at_mark(buffer.get_mark("input")) + cur = buffer.get_iter_at_mark(buffer.get_insert()) + if inp.compare(cur) == 0: + if not event_state: + buffer.place_cursor(inp) + return True + return False + + # For the console we enable smart/home end behavior incoditionally + # since it is useful when editing python + + elif (event.keyval == gtk.keysyms.KP_Home or event.keyval == gtk.keysyms.Home) and \ + event_state == event_state & (gtk.gdk.SHIFT_MASK|gtk.gdk.CONTROL_MASK): + # Go to the begin of the command instead of the begin of the line + buffer = view.get_buffer() + iter = buffer.get_iter_at_mark(buffer.get_mark("input")) + ins = buffer.get_iter_at_mark(buffer.get_insert()) + + while iter.get_char().isspace(): + iter.forward_char() + + if iter.equal(ins): + iter = buffer.get_iter_at_mark(buffer.get_mark("input")) + + if event_state & gtk.gdk.SHIFT_MASK: + buffer.move_mark_by_name("insert", iter) + else: + buffer.place_cursor(iter) + return True + + elif (event.keyval == gtk.keysyms.KP_End or event.keyval == gtk.keysyms.End) and \ + event_state == event_state & (gtk.gdk.SHIFT_MASK|gtk.gdk.CONTROL_MASK): + + buffer = view.get_buffer() + iter = buffer.get_end_iter() + ins = buffer.get_iter_at_mark(buffer.get_insert()) + + iter.backward_char() + + while iter.get_char().isspace(): + iter.backward_char() + + iter.forward_char() + + if iter.equal(ins): + iter = buffer.get_end_iter() + + if event_state & gtk.gdk.SHIFT_MASK: + buffer.move_mark_by_name("insert", iter) + else: + buffer.place_cursor(iter) + return True + + def __mark_set_cb(self, buffer, iter, name): + input = buffer.get_iter_at_mark(buffer.get_mark("input")) + pos = buffer.get_iter_at_mark(buffer.get_insert()) + self.view.set_editable(pos.compare(input) != -1) + + def get_command_line(self): + buffer = self.view.get_buffer() + inp = buffer.get_iter_at_mark(buffer.get_mark("input")) + cur = buffer.get_end_iter() + return buffer.get_text(inp, cur) + + def set_command_line(self, command): + buffer = self.view.get_buffer() + mark = buffer.get_mark("input") + inp = buffer.get_iter_at_mark(mark) + cur = buffer.get_end_iter() + buffer.delete(inp, cur) + buffer.insert(inp, command) + self.view.grab_focus() + + def history_add(self, line): + if line.strip() != '': + self.history_pos = len(self.history) + self.history[self.history_pos - 1] = line + self.history.append('') + + def history_up(self): + if self.history_pos > 0: + self.history[self.history_pos] = self.get_command_line() + self.history_pos = self.history_pos - 1 + self.set_command_line(self.history[self.history_pos]) + + def history_down(self): + if self.history_pos < len(self.history) - 1: + self.history[self.history_pos] = self.get_command_line() + self.history_pos = self.history_pos + 1 + self.set_command_line(self.history[self.history_pos]) + + def scroll_to_end(self): + iter = self.view.get_buffer().get_end_iter() + self.view.scroll_to_iter(iter, 0.0) + return False + + def write(self, text, tag = None): + buffer = self.view.get_buffer() + if tag is None: + buffer.insert(buffer.get_end_iter(), text) + else: + buffer.insert_with_tags(buffer.get_end_iter(), text, tag) + gobject.idle_add(self.scroll_to_end) + + def eval(self, command, display_command = False): + buffer = self.view.get_buffer() + lin = buffer.get_mark("input-line") + buffer.delete(buffer.get_iter_at_mark(lin), + buffer.get_end_iter()) + + if isinstance(command, list) or isinstance(command, tuple): + for c in command: + if display_command: + self.write(">>> " + c + "\n", self.command) + self.__run(c) + else: + if display_command: + self.write(">>> " + c + "\n", self.command) + self.__run(command) + + cur = buffer.get_end_iter() + buffer.move_mark_by_name("input-line", cur) + buffer.insert(cur, ">>> ") + cur = buffer.get_end_iter() + buffer.move_mark_by_name("input", cur) + self.view.scroll_to_iter(buffer.get_end_iter(), 0.0) + + def __run(self, command): + sys.stdout, self.stdout = self.stdout, sys.stdout + sys.stderr, self.stderr = self.stderr, sys.stderr + + # eval and exec are broken in how they deal with utf8-encoded + # strings so we have to explicitly decode the command before + # passing it along + command = command.decode('utf8') + + try: + try: + r = eval(command, self.namespace, self.namespace) + if r is not None: + print `r` + except SyntaxError: + exec command in self.namespace + except: + if hasattr(sys, 'last_type') and sys.last_type == SystemExit: + self.destroy() + else: + traceback.print_exc() + + sys.stdout, self.stdout = self.stdout, sys.stdout + sys.stderr, self.stderr = self.stderr, sys.stderr + + def destroy(self): + pass + #gtk.ScrolledWindow.destroy(self) + +class OutFile: + """A fake output file object. It sends output to a TK test widget, + and if asked for a file number, returns one set on instance creation""" + def __init__(self, console, fn, tag): + self.fn = fn + self.console = console + self.tag = tag + def close(self): pass + def flush(self): pass + def fileno(self): return self.fn + def isatty(self): return 0 + def read(self, a): return '' + def readline(self): return '' + def readlines(self): return [] + def write(self, s): self.console.write(s, self.tag) + def writelines(self, l): self.console.write(l, self.tag) + def seek(self, a): raise IOError, (29, 'Illegal seek') + def tell(self): raise IOError, (29, 'Illegal seek') + truncate = tell + +# ex:et:ts=4: |