##// END OF EJS Templates
Added heartbeat support.
Added heartbeat support.

File last commit:

r2897:5f8498ba
r2910:e4350871
Show More
console_widget.py
1430 lines | 55.7 KiB | text/x-python | PythonLexer
epatters
Initial checkin of Qt frontend code.
r2602 # Standard library imports
epatters
The ConsoleWidget now only pages text if it exceeds the height of the visible window.
r2843 import re
epatters
* Added API for setting the font of a ConsoleWidget....
r2665 import sys
epatters
* Implemented "smart paste" for ConsoleWidget. Continuation prompts are now inserted automatically on paste....
r2763 from textwrap import dedent
epatters
Initial checkin of Qt frontend code.
r2602
# System library imports
from PyQt4 import QtCore, QtGui
# Local imports
epatters
Made IPythonWidget and its subclasses Configurable.
r2884 from IPython.config.configurable import Configurable
from IPython.frontend.qt.util import MetaQObjectHasTraits
from IPython.utils.traitlets import Bool, Enum, Int
epatters
* Moved AnsiCodeProcessor to separate file, refactored its API, and added unit tests....
r2716 from ansi_code_processor import QtAnsiCodeProcessor
epatters
Initial checkin of Qt frontend code.
r2602 from completion_widget import CompletionWidget
epatters
Fixed bug in ConsoleWidget where text could be dragged and dropped.
r2865 class ConsolePlainTextEdit(QtGui.QPlainTextEdit):
""" A QPlainTextEdit suitable for use with ConsoleWidget.
"""
# Prevents text from being moved by drag and drop. Note that is not, for
# some reason, sufficient to catch drag events in the ConsoleWidget's
# event filter.
def dragEnterEvent(self, event): pass
def dragLeaveEvent(self, event): pass
def dragMoveEvent(self, event): pass
def dropEvent(self, event): pass
class ConsoleTextEdit(QtGui.QTextEdit):
""" A QTextEdit suitable for use with ConsoleWidget.
"""
# See above.
def dragEnterEvent(self, event): pass
def dragLeaveEvent(self, event): pass
def dragMoveEvent(self, event): pass
def dropEvent(self, event): pass
epatters
Made IPythonWidget and its subclasses Configurable.
r2884 class ConsoleWidget(Configurable, QtGui.QWidget):
epatters
* Added a pager with several different options to ConsoleWidget....
r2776 """ An abstract base class for console-type widgets. This class has
functionality for:
* Maintaining a prompt and editing region
* Providing the traditional Unix-style console keyboard shortcuts
* Performing tab completion
* Paging text
* Handling ANSI escape codes
ConsoleWidget also provides a number of utility methods that will be
convenient to implementors of a console-style widget.
epatters
Initial checkin of Qt frontend code.
r2602 """
epatters
Made IPythonWidget and its subclasses Configurable.
r2884 __metaclass__ = MetaQObjectHasTraits
epatters
Initial checkin of Qt frontend code.
r2602
epatters
* Added option (disabled by default) to ConsoleWidget for overriding global/window-level shortcuts....
r2668 # Whether to process ANSI escape codes.
epatters
Made IPythonWidget and its subclasses Configurable.
r2884 ansi_codes = Bool(True, config=True)
epatters
* Added option (disabled by default) to ConsoleWidget for overriding global/window-level shortcuts....
r2668
epatters
Made IPythonWidget and its subclasses Configurable.
r2884 # The maximum number of lines of text before truncation. Specifying a
# non-positive number disables text truncation (not recommended).
buffer_size = Int(500, config=True)
epatters
* Added option (disabled by default) to ConsoleWidget for overriding global/window-level shortcuts....
r2668
epatters
Cleanup and minor UI fixes.
r2772 # Whether to use a list widget or plain text output for tab completion.
epatters
Made IPythonWidget and its subclasses Configurable.
r2884 gui_completion = Bool(True, config=True)
# The type of underlying text widget to use. Valid values are 'plain', which
# specifies a QPlainTextEdit, and 'rich', which specifies a QTextEdit.
# NOTE: this value can only be specified during initialization.
kind = Enum(['plain', 'rich'], default_value='plain', config=True)
# The type of paging to use. Valid values are:
# 'inside' : The widget pages like a traditional terminal pager.
# 'hsplit' : When paging is requested, the widget is split
# horizontally. The top pane contains the console, and the
# bottom pane contains the paged text.
# 'vsplit' : Similar to 'hsplit', except that a vertical splitter used.
# 'custom' : No action is taken by the widget beyond emitting a
# 'custom_page_requested(str)' signal.
# 'none' : The text is written directly to the console.
# NOTE: this value can only be specified during initialization.
paging = Enum(['inside', 'hsplit', 'vsplit', 'custom', 'none'],
default_value='inside', config=True)
epatters
* Added option (disabled by default) to ConsoleWidget for overriding global/window-level shortcuts....
r2668
# Whether to override ShortcutEvents for the keybindings defined by this
# widget (Ctrl+n, Ctrl+a, etc). Enable this if you want this widget to take
# priority (when it has focus) over, e.g., window-level menu shortcuts.
epatters
Made IPythonWidget and its subclasses Configurable.
r2884 override_shortcuts = Bool(False)
epatters
* Added option (disabled by default) to ConsoleWidget for overriding global/window-level shortcuts....
r2668
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 # Signals that indicate ConsoleWidget state.
copy_available = QtCore.pyqtSignal(bool)
redo_available = QtCore.pyqtSignal(bool)
undo_available = QtCore.pyqtSignal(bool)
epatters
* Added a pager with several different options to ConsoleWidget....
r2776 # Signal emitted when paging is needed and the paging style has been
# specified as 'custom'.
epatters
Added preliminary editor support to IPythonWidget.
r2793 custom_page_requested = QtCore.pyqtSignal(object)
epatters
* Added a pager with several different options to ConsoleWidget....
r2776
epatters
* Added option (disabled by default) to ConsoleWidget for overriding global/window-level shortcuts....
r2668 # Protected class variables.
epatters
Initial checkin of Qt frontend code.
r2602 _ctrl_down_remap = { QtCore.Qt.Key_B : QtCore.Qt.Key_Left,
QtCore.Qt.Key_F : QtCore.Qt.Key_Right,
QtCore.Qt.Key_A : QtCore.Qt.Key_Home,
QtCore.Qt.Key_E : QtCore.Qt.Key_End,
QtCore.Qt.Key_P : QtCore.Qt.Key_Up,
QtCore.Qt.Key_N : QtCore.Qt.Key_Down,
QtCore.Qt.Key_D : QtCore.Qt.Key_Delete, }
epatters
* Added ability to interrupt a kernel to FrontendWidget...
r2687 _shortcuts = set(_ctrl_down_remap.keys() +
epatters
Numerous usability enhancements to the Qt console widget, particularly with regard to key bindings.
r2897 [ QtCore.Qt.Key_C, QtCore.Qt.Key_V, QtCore.Qt.Key_O ])
epatters
Initial checkin of Qt frontend code.
r2602
#---------------------------------------------------------------------------
epatters
Minor comment cleanup.
r2669 # 'QObject' interface
epatters
Initial checkin of Qt frontend code.
r2602 #---------------------------------------------------------------------------
epatters
Made IPythonWidget and its subclasses Configurable.
r2884 def __init__(self, parent=None, **kw):
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 """ Create a ConsoleWidget.
epatters
Made IPythonWidget and its subclasses Configurable.
r2884 Parameters:
-----------
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 parent : QWidget, optional [default None]
The parent for this widget.
"""
epatters
Made IPythonWidget and its subclasses Configurable.
r2884 QtGui.QWidget.__init__(self, parent)
Configurable.__init__(self, **kw)
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736
epatters
* Added a pager with several different options to ConsoleWidget....
r2776 # Create the layout and underlying text widget.
layout = QtGui.QStackedLayout(self)
epatters
Improved the size hint for ConsoleWidget. We now acheive a width of 80 characters, through a mixture of better margin calculation and, well, fudging a little bit.
r2882 layout.setContentsMargins(0, 0, 0, 0)
epatters
Made IPythonWidget and its subclasses Configurable.
r2884 self._control = self._create_control()
epatters
* Added a pager with several different options to ConsoleWidget....
r2776 self._page_control = None
self._splitter = None
epatters
Made IPythonWidget and its subclasses Configurable.
r2884 if self.paging in ('hsplit', 'vsplit'):
epatters
* Added a pager with several different options to ConsoleWidget....
r2776 self._splitter = QtGui.QSplitter()
epatters
Made IPythonWidget and its subclasses Configurable.
r2884 if self.paging == 'hsplit':
epatters
* Added a pager with several different options to ConsoleWidget....
r2776 self._splitter.setOrientation(QtCore.Qt.Horizontal)
else:
self._splitter.setOrientation(QtCore.Qt.Vertical)
self._splitter.addWidget(self._control)
layout.addWidget(self._splitter)
else:
layout.addWidget(self._control)
# Create the paging widget, if necessary.
epatters
Made IPythonWidget and its subclasses Configurable.
r2884 if self.paging in ('inside', 'hsplit', 'vsplit'):
epatters
* Added a pager with several different options to ConsoleWidget....
r2776 self._page_control = self._create_page_control()
if self._splitter:
self._page_control.hide()
self._splitter.addWidget(self._page_control)
else:
layout.addWidget(self._page_control)
epatters
Initial checkin of Qt frontend code.
r2602
epatters
* IPythonWidget now has IPython-style prompts that are futher stylabla via CSS...
r2715 # Initialize protected variables. Some variables contain useful state
# information for subclasses; they should be considered read-only.
epatters
Initial checkin of Qt frontend code.
r2602 self._ansi_processor = QtAnsiCodeProcessor()
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 self._completion_widget = CompletionWidget(self._control)
epatters
* Added 'started_listening' and 'stopped_listening' signals to QtKernelManager. The FrontendWidget listens for these signals....
r2643 self._continuation_prompt = '> '
epatters
* IPythonWidget now has IPython-style prompts that are futher stylabla via CSS...
r2715 self._continuation_prompt_html = None
epatters
Initial checkin of Qt frontend code.
r2602 self._executing = False
self._prompt = ''
epatters
* IPythonWidget now has IPython-style prompts that are futher stylabla via CSS...
r2715 self._prompt_html = None
epatters
Initial checkin of Qt frontend code.
r2602 self._prompt_pos = 0
epatters
* Fixed regression from last commit: syntax highlighting works robustly again....
r2866 self._prompt_sep = ''
epatters
Initial checkin of Qt frontend code.
r2602 self._reading = False
epatters
Reading a line is now correctly implemented in ConsoleWidget.
r2706 self._reading_callback = None
epatters
* ConsoleWidget now has better support for non-GUI tab completion. Multiple matches are formatted into columns....
r2723 self._tab_width = 8
epatters
Initial checkin of Qt frontend code.
r2602
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 # Set a monospaced font.
self.reset_font()
epatters
Initial checkin of Qt frontend code.
r2602
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 def eventFilter(self, obj, event):
""" Reimplemented to ensure a console-like behavior in the underlying
epatters
Numerous usability enhancements to the Qt console widget, particularly with regard to key bindings.
r2897 text widgets.
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 """
epatters
Cleanup and minor UI fixes.
r2772 etype = event.type()
epatters
Numerous usability enhancements to the Qt console widget, particularly with regard to key bindings.
r2897 if etype == QtCore.QEvent.KeyPress:
# Re-map keys for all filtered widgets.
key = event.key()
if self._control_key_down(event.modifiers()) and \
key in self._ctrl_down_remap:
new_event = QtGui.QKeyEvent(QtCore.QEvent.KeyPress,
self._ctrl_down_remap[key],
QtCore.Qt.NoModifier)
QtGui.qApp.sendEvent(obj, new_event)
return True
elif obj == self._control:
return self._event_filter_console_keypress(event)
elif obj == self._page_control:
return self._event_filter_page_keypress(event)
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736
epatters
Cleanup and minor UI fixes.
r2772 # Override shortucts for all filtered widgets. Note that on Mac OS it is
# always unnecessary to override shortcuts, hence the check below (users
# should just use the Control key instead of the Command key).
elif etype == QtCore.QEvent.ShortcutOverride and \
sys.platform != 'darwin' and \
self._control_key_down(event.modifiers()) and \
event.key() in self._shortcuts:
event.accept()
return False
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 return super(ConsoleWidget, self).eventFilter(obj, event)
epatters
* Added option (disabled by default) to ConsoleWidget for overriding global/window-level shortcuts....
r2668
epatters
Minor comment cleanup.
r2669 #---------------------------------------------------------------------------
epatters
* Added a pager with several different options to ConsoleWidget....
r2776 # 'QWidget' interface
#---------------------------------------------------------------------------
def sizeHint(self):
""" Reimplemented to suggest a size that is 80 characters wide and
25 lines high.
"""
font_metrics = QtGui.QFontMetrics(self.font)
epatters
Improved the size hint for ConsoleWidget. We now acheive a width of 80 characters, through a mixture of better margin calculation and, well, fudging a little bit.
r2882 margin = (self._control.frameWidth() +
self._control.document().documentMargin()) * 2
style = self.style()
splitwidth = style.pixelMetric(QtGui.QStyle.PM_SplitterWidth)
epatters
* Added a pager with several different options to ConsoleWidget....
r2776
epatters
Improved the size hint for ConsoleWidget. We now acheive a width of 80 characters, through a mixture of better margin calculation and, well, fudging a little bit.
r2882 # Despite my best efforts to take the various margins into account, the
# width is still coming out a bit too small, so we include a fudge
# factor of one character here.
width = font_metrics.maxWidth() * 81 + margin
width += style.pixelMetric(QtGui.QStyle.PM_ScrollBarExtent)
epatters
Made IPythonWidget and its subclasses Configurable.
r2884 if self.paging == 'hsplit':
epatters
* Added a pager with several different options to ConsoleWidget....
r2776 width = width * 2 + splitwidth
epatters
Improved the size hint for ConsoleWidget. We now acheive a width of 80 characters, through a mixture of better margin calculation and, well, fudging a little bit.
r2882 height = font_metrics.height() * 25 + margin
epatters
Made IPythonWidget and its subclasses Configurable.
r2884 if self.paging == 'vsplit':
epatters
* Added a pager with several different options to ConsoleWidget....
r2776 height = height * 2 + splitwidth
return QtCore.QSize(width, height)
#---------------------------------------------------------------------------
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 # 'ConsoleWidget' public interface
epatters
Minor comment cleanup.
r2669 #---------------------------------------------------------------------------
epatters
* Fixed bug where ConsoleWidget accepted non-ASCII characters on paste (and also rich text in 'rich' mode)...
r2762 def can_paste(self):
""" Returns whether text can be pasted from the clipboard.
"""
epatters
Improved the size hint for ConsoleWidget. We now acheive a width of 80 characters, through a mixture of better margin calculation and, well, fudging a little bit.
r2882 # Only accept text that can be ASCII encoded.
epatters
* Fixed bug where ConsoleWidget accepted non-ASCII characters on paste (and also rich text in 'rich' mode)...
r2762 if self._control.textInteractionFlags() & QtCore.Qt.TextEditable:
text = QtGui.QApplication.clipboard().text()
if not text.isEmpty():
try:
str(text)
return True
except UnicodeEncodeError:
pass
return False
epatters
Fixed bug where the banner message was syntax highlighted when the frontend connected to a new kernel.
r2842 def clear(self, keep_input=True):
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 """ Clear the console, then write a new prompt. If 'keep_input' is set,
epatters
* IPythonWidget now has IPython-style prompts that are futher stylabla via CSS...
r2715 restores the old input buffer when the new prompt is written.
epatters
* Added 'started_listening' and 'stopped_listening' signals to QtKernelManager. The FrontendWidget listens for these signals....
r2643 """
epatters
* IPythonWidget now has IPython-style prompts that are futher stylabla via CSS...
r2715 if keep_input:
epatters
* Added 'started_listening' and 'stopped_listening' signals to QtKernelManager. The FrontendWidget listens for these signals....
r2643 input_buffer = self.input_buffer
epatters
Fixed bug where the banner message was syntax highlighted when the frontend connected to a new kernel.
r2842 self._control.clear()
epatters
* Added 'started_listening' and 'stopped_listening' signals to QtKernelManager. The FrontendWidget listens for these signals....
r2643 self._show_prompt()
epatters
* IPythonWidget now has IPython-style prompts that are futher stylabla via CSS...
r2715 if keep_input:
self.input_buffer = input_buffer
epatters
* Added 'started_listening' and 'stopped_listening' signals to QtKernelManager. The FrontendWidget listens for these signals....
r2643
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 def copy(self):
""" Copy the current selected text to the clipboard.
epatters
Initial checkin of Qt frontend code.
r2602 """
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 self._control.copy()
epatters
Initial checkin of Qt frontend code.
r2602
epatters
* Refactored ConsoleWidget execution API for greater flexibility and clarity....
r2688 def execute(self, source=None, hidden=False, interactive=False):
""" Executes source or the input buffer, possibly prompting for more
input.
Parameters:
-----------
source : str, optional
The source to execute. If not specified, the input buffer will be
used. If specified and 'hidden' is False, the input buffer will be
replaced with the source before execution.
hidden : bool, optional (default False)
If set, no output will be shown and the prompt will not be modified.
In other words, it will be completely invisible to the user that
an execution has occurred.
interactive : bool, optional (default False)
Whether the console is to treat the source as having been manually
entered by the user. The effect of this parameter depends on the
subclass implementation.
epatters
* Fixed history breakage due to recent refactoring....
r2689 Raises:
-------
RuntimeError
If incomplete input is given and 'hidden' is True. In this case,
epatters
Minor cleanup and bug fix.
r2771 it is not possible to prompt for more input.
epatters
* Fixed history breakage due to recent refactoring....
r2689
epatters
* Refactored ConsoleWidget execution API for greater flexibility and clarity....
r2688 Returns:
--------
A boolean indicating whether the source was executed.
"""
epatters
* Fixed regression from last commit: syntax highlighting works robustly again....
r2866 # WARNING: The order in which things happen here is very particular, in
# large part because our syntax highlighting is fragile. If you change
# something, test carefully!
epatters
* Refactored ConsoleWidget execution API for greater flexibility and clarity....
r2688
epatters
* Fixed regression from last commit: syntax highlighting works robustly again....
r2866 # Decide what to execute.
if source is None:
source = self.input_buffer
epatters
* Refactored ConsoleWidget execution API for greater flexibility and clarity....
r2688 if not hidden:
epatters
* Fixed regression from last commit: syntax highlighting works robustly again....
r2866 # A newline is appended later, but it should be considered part
# of the input buffer.
source += '\n'
elif not hidden:
self.input_buffer = source
# Execute the source or show a continuation prompt if it is incomplete.
complete = self._is_complete(source, interactive)
if hidden:
if complete:
self._execute(source, hidden)
else:
error = 'Incomplete noninteractive input: "%s"'
raise RuntimeError(error % source)
else:
if complete:
self._append_plain_text('\n')
self._executing_input_buffer = self.input_buffer
self._executing = True
self._prompt_finished()
epatters
* Refactored ConsoleWidget execution API for greater flexibility and clarity....
r2688 # The maximum block count is only in effect during execution.
# This ensures that _prompt_pos does not become invalid due to
# text truncation.
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 self._control.document().setMaximumBlockCount(self.buffer_size)
epatters
* The ConsoleWidget now has full undo/redo support. Previously, the undo/redo history was cleared after every continuation prompt. This is no longer the case....
r2864
# Setting a positive maximum block count will automatically
# disable the undo/redo history, but just to be safe:
self._control.setUndoRedoEnabled(False)
epatters
* Fixed regression from last commit: syntax highlighting works robustly again....
r2866 self._execute(source, hidden)
else:
# Do this inside an edit block so continuation prompts are
# removed seamlessly via undo/redo.
epatters
Fixed several bugs involving the insertion of new lines. Pressing Enter in the ConsoleWidget now works as expected.
r2896 cursor = self._get_end_cursor()
epatters
* Fixed regression from last commit: syntax highlighting works robustly again....
r2866 cursor.beginEditBlock()
epatters
Fixed several bugs involving the insertion of new lines. Pressing Enter in the ConsoleWidget now works as expected.
r2896 cursor.insertText('\n')
self._insert_continuation_prompt(cursor)
self._control.moveCursor(QtGui.QTextCursor.End)
epatters
* Fixed regression from last commit: syntax highlighting works robustly again....
r2866 cursor.endEditBlock()
epatters
* The ConsoleWidget now has full undo/redo support. Previously, the undo/redo history was cleared after every continuation prompt. This is no longer the case....
r2864
epatters
* Refactored ConsoleWidget execution API for greater flexibility and clarity....
r2688 return complete
epatters
Initial checkin of Qt frontend code.
r2602
def _get_input_buffer(self):
epatters
* Added API for setting the font of a ConsoleWidget....
r2665 """ The text that the user has entered entered at the current prompt.
"""
# If we're executing, the input buffer may not even exist anymore due to
epatters
* Added undo/redo support to ConsoleWidget...
r2615 # the limit imposed by 'buffer_size'. Therefore, we store it.
if self._executing:
return self._executing_input_buffer
epatters
Initial checkin of Qt frontend code.
r2602 cursor = self._get_end_cursor()
cursor.setPosition(self._prompt_pos, QtGui.QTextCursor.KeepAnchor)
input_buffer = str(cursor.selection().toPlainText())
epatters
* Added API for setting the font of a ConsoleWidget....
r2665 # Strip out continuation prompts.
epatters
* Added 'started_listening' and 'stopped_listening' signals to QtKernelManager. The FrontendWidget listens for these signals....
r2643 return input_buffer.replace('\n' + self._continuation_prompt, '\n')
epatters
Initial checkin of Qt frontend code.
r2602
def _set_input_buffer(self, string):
epatters
* Added API for setting the font of a ConsoleWidget....
r2665 """ Replaces the text in the input buffer with 'string'.
"""
epatters
Numerous fixes to ConsoleWidget editing region maintenence code. It now impossible (or at least very difficult :) to break the input region.
r2764 # For now, it is an error to modify the input buffer during execution.
if self._executing:
raise RuntimeError("Cannot change input buffer during execution.")
epatters
Setting the input buffer now respects HTML continuation prompts.
r2717 # Remove old text.
epatters
Initial checkin of Qt frontend code.
r2602 cursor = self._get_end_cursor()
epatters
Numerous fixes to ConsoleWidget editing region maintenence code. It now impossible (or at least very difficult :) to break the input region.
r2764 cursor.beginEditBlock()
epatters
Initial checkin of Qt frontend code.
r2602 cursor.setPosition(self._prompt_pos, QtGui.QTextCursor.KeepAnchor)
epatters
Setting the input buffer now respects HTML continuation prompts.
r2717 cursor.removeSelectedText()
# Insert new text with continuation prompts.
lines = string.splitlines(True)
if lines:
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 self._append_plain_text(lines[0])
epatters
Setting the input buffer now respects HTML continuation prompts.
r2717 for i in xrange(1, len(lines)):
if self._continuation_prompt_html is None:
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 self._append_plain_text(self._continuation_prompt)
epatters
Setting the input buffer now respects HTML continuation prompts.
r2717 else:
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 self._append_html(self._continuation_prompt_html)
self._append_plain_text(lines[i])
epatters
Numerous fixes to ConsoleWidget editing region maintenence code. It now impossible (or at least very difficult :) to break the input region.
r2764 cursor.endEditBlock()
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 self._control.moveCursor(QtGui.QTextCursor.End)
epatters
Initial checkin of Qt frontend code.
r2602
input_buffer = property(_get_input_buffer, _set_input_buffer)
epatters
* Added API for setting the font of a ConsoleWidget....
r2665 def _get_font(self):
""" The base font being used by the ConsoleWidget.
"""
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 return self._control.document().defaultFont()
epatters
* Added API for setting the font of a ConsoleWidget....
r2665
def _set_font(self, font):
""" Sets the base font for the ConsoleWidget to the specified QFont.
"""
epatters
* Moved AnsiCodeProcessor to separate file, refactored its API, and added unit tests....
r2716 font_metrics = QtGui.QFontMetrics(font)
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 self._control.setTabStopWidth(self.tab_width * font_metrics.width(' '))
epatters
* Moved AnsiCodeProcessor to separate file, refactored its API, and added unit tests....
r2716
epatters
* Added API for setting the font of a ConsoleWidget....
r2665 self._completion_widget.setFont(font)
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 self._control.document().setDefaultFont(font)
epatters
Fix to ensure that the paging widget is styled appropriately.
r2779 if self._page_control:
self._page_control.document().setDefaultFont(font)
epatters
* Added API for setting the font of a ConsoleWidget....
r2665
font = property(_get_font, _set_font)
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 def paste(self):
""" Paste the contents of the clipboard into the input region.
"""
epatters
* Implemented "smart paste" for ConsoleWidget. Continuation prompts are now inserted automatically on paste....
r2763 if self._control.textInteractionFlags() & QtCore.Qt.TextEditable:
try:
text = str(QtGui.QApplication.clipboard().text())
except UnicodeEncodeError:
pass
else:
epatters
Fixed bug with ConsoleWidget smart paste.
r2787 self._insert_plain_text_into_buffer(dedent(text))
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736
def print_(self, printer):
""" Print the contents of the ConsoleWidget to the specified QPrinter.
"""
self._control.print_(printer)
def redo(self):
""" Redo the last operation. If there is no operation to redo, nothing
happens.
"""
self._control.redo()
epatters
* Added API for setting the font of a ConsoleWidget....
r2665 def reset_font(self):
""" Sets the font to the default fixed-width font for this platform.
"""
Fernando Perez
Add notes about configurability of font details and Win32 defaults.
r2858 # FIXME: font family and size should be configurable by the user.
epatters
* Added API for setting the font of a ConsoleWidget....
r2665 if sys.platform == 'win32':
epatters
Fixed several bugs involving the insertion of new lines. Pressing Enter in the ConsoleWidget now works as expected.
r2896 # FIXME: we should test whether Consolas is available and use it
Fernando Perez
Add notes about configurability of font details and Win32 defaults.
r2858 # first if it is. Consolas ships by default from Vista onwards,
# it's *vastly* more readable and prettier than Courier, and is
# often installed even on XP systems. So we should first check for
# it, and only fallback to Courier if absolutely necessary.
epatters
* Added API for setting the font of a ConsoleWidget....
r2665 name = 'Courier'
elif sys.platform == 'darwin':
name = 'Monaco'
else:
name = 'Monospace'
font = QtGui.QFont(name, QtGui.qApp.font().pointSize())
font.setStyleHint(QtGui.QFont.TypeWriter)
self._set_font(font)
epatters
* ConsoleWidget now has better support for non-GUI tab completion. Multiple matches are formatted into columns....
r2723
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 def select_all(self):
""" Selects all the text in the buffer.
"""
self._control.selectAll()
epatters
* ConsoleWidget now has better support for non-GUI tab completion. Multiple matches are formatted into columns....
r2723 def _get_tab_width(self):
""" The width (in terms of space characters) for tab characters.
"""
return self._tab_width
def _set_tab_width(self, tab_width):
""" Sets the width (in terms of space characters) for tab characters.
"""
font_metrics = QtGui.QFontMetrics(self.font)
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 self._control.setTabStopWidth(tab_width * font_metrics.width(' '))
epatters
* ConsoleWidget now has better support for non-GUI tab completion. Multiple matches are formatted into columns....
r2723
self._tab_width = tab_width
tab_width = property(_get_tab_width, _set_tab_width)
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736
def undo(self):
""" Undo the last operation. If there is no operation to undo, nothing
happens.
"""
self._control.undo()
epatters
Initial checkin of Qt frontend code.
r2602 #---------------------------------------------------------------------------
# 'ConsoleWidget' abstract interface
#---------------------------------------------------------------------------
epatters
* Refactored ConsoleWidget execution API for greater flexibility and clarity....
r2688 def _is_complete(self, source, interactive):
""" Returns whether 'source' can be executed. When triggered by an
Enter/Return key press, 'interactive' is True; otherwise, it is
False.
"""
raise NotImplementedError
def _execute(self, source, hidden):
""" Execute 'source'. If 'hidden', do not show any output.
epatters
Initial checkin of Qt frontend code.
r2602 """
raise NotImplementedError
def _prompt_started_hook(self):
""" Called immediately after a new prompt is displayed.
"""
pass
def _prompt_finished_hook(self):
""" Called immediately after a prompt is finished, i.e. when some input
will be processed and a new prompt displayed.
"""
pass
def _up_pressed(self):
""" Called when the up key is pressed. Returns whether to continue
processing the event.
"""
return True
def _down_pressed(self):
""" Called when the down key is pressed. Returns whether to continue
processing the event.
"""
return True
def _tab_pressed(self):
""" Called when the tab key is pressed. Returns whether to continue
processing the event.
"""
return False
#--------------------------------------------------------------------------
# 'ConsoleWidget' protected interface
#--------------------------------------------------------------------------
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 def _append_html(self, html):
""" Appends html at the end of the console buffer.
"""
cursor = self._get_end_cursor()
self._insert_html(cursor, html)
epatters
* IPythonWidget now has IPython-style prompts that are futher stylabla via CSS...
r2715 def _append_html_fetching_plain_text(self, html):
""" Appends 'html', then returns the plain text version of it.
"""
cursor = self._get_end_cursor()
epatters
Fixed bug with ConsoleWidget smart paste.
r2787 return self._insert_html_fetching_plain_text(cursor, html)
epatters
* IPythonWidget now has IPython-style prompts that are futher stylabla via CSS...
r2715
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 def _append_plain_text(self, text):
""" Appends plain text at the end of the console buffer, processing
ANSI codes if enabled.
"""
cursor = self._get_end_cursor()
epatters
* Added a pager with several different options to ConsoleWidget....
r2776 self._insert_plain_text(cursor, text)
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736
epatters
* IPythonWidget now has IPython-style prompts that are futher stylabla via CSS...
r2715 def _append_plain_text_keeping_prompt(self, text):
""" Writes 'text' after the current prompt, then restores the old prompt
with its old input buffer.
"""
input_buffer = self.input_buffer
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 self._append_plain_text('\n')
epatters
* IPythonWidget now has IPython-style prompts that are futher stylabla via CSS...
r2715 self._prompt_finished()
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 self._append_plain_text(text)
epatters
* IPythonWidget now has IPython-style prompts that are futher stylabla via CSS...
r2715 self._show_prompt()
self.input_buffer = input_buffer
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 def _complete_with_items(self, cursor, items):
""" Performs completion with 'items' at the specified cursor location.
"""
if len(items) == 1:
cursor.setPosition(self._control.textCursor().position(),
QtGui.QTextCursor.KeepAnchor)
cursor.insertText(items[0])
elif len(items) > 1:
if self.gui_completion:
self._completion_widget.show_items(cursor, items)
else:
text = self._format_as_columns(items)
self._append_plain_text_keeping_prompt(text)
def _control_key_down(self, modifiers):
epatters
Fixed wonky ConsoleWidget keyboard shortcuts on Mac OS.
r2671 """ Given a KeyboardModifiers flags object, return whether the Control
key is down (on Mac OS, treat the Command key as a synonym for
Control).
"""
down = bool(modifiers & QtCore.Qt.ControlModifier)
# Note: on Mac OS, ControlModifier corresponds to the Command key while
# MetaModifier corresponds to the Control key.
if sys.platform == 'darwin':
down = down ^ bool(modifiers & QtCore.Qt.MetaModifier)
return down
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736
epatters
Made IPythonWidget and its subclasses Configurable.
r2884 def _create_control(self):
epatters
Cleanup and minor UI fixes.
r2772 """ Creates and connects the underlying text widget.
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 """
epatters
Made IPythonWidget and its subclasses Configurable.
r2884 if self.kind == 'plain':
epatters
Fixed bug in ConsoleWidget where text could be dragged and dropped.
r2865 control = ConsolePlainTextEdit()
epatters
Made IPythonWidget and its subclasses Configurable.
r2884 elif self.kind == 'rich':
epatters
Fixed bug in ConsoleWidget where text could be dragged and dropped.
r2865 control = ConsoleTextEdit()
epatters
* Fixed bug where ConsoleWidget accepted non-ASCII characters on paste (and also rich text in 'rich' mode)...
r2762 control.setAcceptRichText(False)
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 control.installEventFilter(self)
epatters
* Fixed context menu breakge after previous commit....
r2737 control.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
control.customContextMenuRequested.connect(self._show_context_menu)
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 control.copyAvailable.connect(self.copy_available)
control.redoAvailable.connect(self.redo_available)
control.undoAvailable.connect(self.undo_available)
epatters
* Added support for prompt and history requests to the kernel manager and Qt console frontend....
r2844 control.setReadOnly(True)
epatters
* The ConsoleWidget now has full undo/redo support. Previously, the undo/redo history was cleared after every continuation prompt. This is no longer the case....
r2864 control.setUndoRedoEnabled(False)
epatters
Cleanup and minor UI fixes.
r2772 control.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 return control
epatters
* Added a pager with several different options to ConsoleWidget....
r2776 def _create_page_control(self):
""" Creates and connects the underlying paging widget.
"""
epatters
Fixed bug in ConsoleWidget where text could be dragged and dropped.
r2865 control = ConsolePlainTextEdit()
epatters
* Added a pager with several different options to ConsoleWidget....
r2776 control.installEventFilter(self)
control.setReadOnly(True)
epatters
* The ConsoleWidget now has full undo/redo support. Previously, the undo/redo history was cleared after every continuation prompt. This is no longer the case....
r2864 control.setUndoRedoEnabled(False)
epatters
* Added a pager with several different options to ConsoleWidget....
r2776 control.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
return control
def _event_filter_console_keypress(self, event):
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 """ Filter key events for the underlying text widget to create a
console-like interface.
"""
intercepted = False
cursor = self._control.textCursor()
position = cursor.position()
epatters
Cleanup and minor UI fixes.
r2772 key = event.key()
ctrl_down = self._control_key_down(event.modifiers())
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 alt_down = event.modifiers() & QtCore.Qt.AltModifier
shift_down = event.modifiers() & QtCore.Qt.ShiftModifier
if event.matches(QtGui.QKeySequence.Paste):
epatters
* Fixed context menu breakge after previous commit....
r2737 # Call our paste instead of the underlying text widget's.
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 self.paste()
intercepted = True
elif ctrl_down:
epatters
First cut at allowing the kernel to be restarted from the frontend.
r2851 if key == QtCore.Qt.Key_K:
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 if self._in_buffer(position):
cursor.movePosition(QtGui.QTextCursor.EndOfLine,
QtGui.QTextCursor.KeepAnchor)
epatters
Pressing Ctrl-K at the end of a line now deletes the newline, as expected.
r2886 if not cursor.hasSelection():
# Line deletion (remove continuation prompt)
cursor.movePosition(QtGui.QTextCursor.NextBlock,
QtGui.QTextCursor.KeepAnchor)
cursor.movePosition(QtGui.QTextCursor.Right,
QtGui.QTextCursor.KeepAnchor,
len(self._continuation_prompt))
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 cursor.removeSelectedText()
intercepted = True
epatters
* Added support for Ctrl-L per Fernando's request....
r2880 elif key == QtCore.Qt.Key_L:
epatters
Added comment explaining why the behavior of Ctrl-L cannot be improved, after trying and failing to do so.
r2887 # It would be better to simply move the prompt block to the top
# of the control viewport. QPlainTextEdit has a private method
# to do this (setTopBlock), but it cannot be duplicated here
# because it requires access to the QTextControl that underlies
# both QPlainTextEdit and QTextEdit. In short, this can only be
# achieved by appending newlines after the prompt, which is a
# gigantic hack and likely to cause other problems.
epatters
* Added support for Ctrl-L per Fernando's request....
r2880 self.clear()
intercepted = True
epatters
Numerous usability enhancements to the Qt console widget, particularly with regard to key bindings.
r2897 elif key == QtCore.Qt.Key_O:
if self._page_control and self._page_control.isVisible():
self._page_control.setFocus()
intercept = True
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 elif key == QtCore.Qt.Key_X:
epatters
* Added support for Ctrl-L per Fernando's request....
r2880 # FIXME: Instead of disabling cut completely, only allow it
# when safe.
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 intercepted = True
elif key == QtCore.Qt.Key_Y:
self.paste()
intercepted = True
elif alt_down:
if key == QtCore.Qt.Key_B:
self._set_cursor(self._get_word_start_cursor(position))
intercepted = True
elif key == QtCore.Qt.Key_F:
self._set_cursor(self._get_word_end_cursor(position))
intercepted = True
elif key == QtCore.Qt.Key_Backspace:
cursor = self._get_word_start_cursor(position)
cursor.setPosition(position, QtGui.QTextCursor.KeepAnchor)
cursor.removeSelectedText()
intercepted = True
elif key == QtCore.Qt.Key_D:
cursor = self._get_word_end_cursor(position)
cursor.setPosition(position, QtGui.QTextCursor.KeepAnchor)
cursor.removeSelectedText()
intercepted = True
epatters
Numerous usability enhancements to the Qt console widget, particularly with regard to key bindings.
r2897 elif key == QtCore.Qt.Key_Greater:
self._control.moveCursor(QtGui.QTextCursor.End)
intercepted = True
elif key == QtCore.Qt.Key_Less:
self._control.setTextCursor(self._get_prompt_cursor())
intercepted = True
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 else:
if key in (QtCore.Qt.Key_Return, QtCore.Qt.Key_Enter):
intercepted = True
epatters
Fixed several bugs involving the insertion of new lines. Pressing Enter in the ConsoleWidget now works as expected.
r2896 if self._in_buffer(position):
if self._reading:
self._append_plain_text('\n')
self._reading = False
if self._reading_callback:
self._reading_callback()
# If there is only whitespace after the cursor, execute.
# Otherwise, split the line with a continuation prompt.
elif not self._executing:
cursor.movePosition(QtGui.QTextCursor.End,
QtGui.QTextCursor.KeepAnchor)
if cursor.selectedText().trimmed().isEmpty():
self.execute(interactive=True)
else:
cursor.beginEditBlock()
cursor.setPosition(position)
cursor.insertText('\n')
self._insert_continuation_prompt(cursor)
# Ensure that the whole input buffer is visible.
# FIXME: This will not be usable if the input buffer
# is taller than the console widget.
self._control.moveCursor(QtGui.QTextCursor.End)
self._control.setTextCursor(cursor)
cursor.endEditBlock()
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736
elif key == QtCore.Qt.Key_Up:
if self._reading or not self._up_pressed():
intercepted = True
else:
prompt_line = self._get_prompt_cursor().blockNumber()
intercepted = cursor.blockNumber() <= prompt_line
elif key == QtCore.Qt.Key_Down:
if self._reading or not self._down_pressed():
intercepted = True
else:
end_line = self._get_end_cursor().blockNumber()
intercepted = cursor.blockNumber() == end_line
elif key == QtCore.Qt.Key_Tab:
epatters
Minor cleanup (again).
r2849 if not self._reading:
intercepted = not self._tab_pressed()
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736
elif key == QtCore.Qt.Key_Left:
intercepted = not self._in_buffer(position - 1)
elif key == QtCore.Qt.Key_Home:
start_line = cursor.blockNumber()
if start_line == self._get_prompt_cursor().blockNumber():
start_pos = self._prompt_pos
else:
epatters
Pressing Ctrl-K at the end of a line now deletes the newline, as expected.
r2886 cursor.movePosition(QtGui.QTextCursor.StartOfBlock,
QtGui.QTextCursor.KeepAnchor)
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 start_pos = cursor.position()
start_pos += len(self._continuation_prompt)
epatters
Pressing Ctrl-K at the end of a line now deletes the newline, as expected.
r2886 cursor.setPosition(position)
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 if shift_down and self._in_buffer(position):
epatters
Pressing Ctrl-K at the end of a line now deletes the newline, as expected.
r2886 cursor.setPosition(start_pos, QtGui.QTextCursor.KeepAnchor)
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 else:
epatters
Pressing Ctrl-K at the end of a line now deletes the newline, as expected.
r2886 cursor.setPosition(start_pos)
self._set_cursor(cursor)
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 intercepted = True
epatters
Numerous fixes to ConsoleWidget editing region maintenence code. It now impossible (or at least very difficult :) to break the input region.
r2764 elif key == QtCore.Qt.Key_Backspace:
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736
# Line deletion (remove continuation prompt)
len_prompt = len(self._continuation_prompt)
if not self._reading and \
cursor.columnNumber() == len_prompt and \
position != self._prompt_pos:
epatters
* The ConsoleWidget now has full undo/redo support. Previously, the undo/redo history was cleared after every continuation prompt. This is no longer the case....
r2864 cursor.beginEditBlock()
epatters
Numerous fixes to ConsoleWidget editing region maintenence code. It now impossible (or at least very difficult :) to break the input region.
r2764 cursor.movePosition(QtGui.QTextCursor.StartOfBlock,
QtGui.QTextCursor.KeepAnchor)
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 cursor.removeSelectedText()
epatters
Fixed rare bug with continuation prompt deletion.
r2785 cursor.deletePreviousChar()
epatters
* The ConsoleWidget now has full undo/redo support. Previously, the undo/redo history was cleared after every continuation prompt. This is no longer the case....
r2864 cursor.endEditBlock()
epatters
Fixed rare bug with continuation prompt deletion.
r2785 intercepted = True
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736
# Regular backwards deletion
else:
anchor = cursor.anchor()
if anchor == position:
intercepted = not self._in_buffer(position - 1)
else:
intercepted = not self._in_buffer(min(anchor, position))
elif key == QtCore.Qt.Key_Delete:
epatters
* The ConsoleWidget now has full undo/redo support. Previously, the undo/redo history was cleared after every continuation prompt. This is no longer the case....
r2864
# Line deletion (remove continuation prompt)
if not self._reading and cursor.atBlockEnd() and not \
cursor.hasSelection():
cursor.movePosition(QtGui.QTextCursor.NextBlock,
QtGui.QTextCursor.KeepAnchor)
cursor.movePosition(QtGui.QTextCursor.Right,
QtGui.QTextCursor.KeepAnchor,
len(self._continuation_prompt))
cursor.removeSelectedText()
intercepted = True
# Regular forwards deletion:
else:
anchor = cursor.anchor()
intercepted = (not self._in_buffer(anchor) or
not self._in_buffer(position))
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736
epatters
* Fixed context menu breakge after previous commit....
r2737 # Don't move the cursor if control is down to allow copy-paste using
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 # the keyboard in any part of the buffer.
if not ctrl_down:
self._keep_cursor_in_buffer()
return intercepted
epatters
* IPythonWidget now has IPython-style prompts that are futher stylabla via CSS...
r2715
epatters
* Added a pager with several different options to ConsoleWidget....
r2776 def _event_filter_page_keypress(self, event):
""" Filter key events for the paging widget to create console-like
interface.
"""
key = event.key()
epatters
Numerous usability enhancements to the Qt console widget, particularly with regard to key bindings.
r2897 ctrl_down = self._control_key_down(event.modifiers())
alt_down = event.modifiers() & QtCore.Qt.AltModifier
if ctrl_down:
if key == QtCore.Qt.Key_O:
self._control.setFocus()
intercept = True
epatters
* Added a pager with several different options to ConsoleWidget....
r2776
epatters
Numerous usability enhancements to the Qt console widget, particularly with regard to key bindings.
r2897 elif alt_down:
if key == QtCore.Qt.Key_Greater:
self._page_control.moveCursor(QtGui.QTextCursor.End)
intercepted = True
elif key == QtCore.Qt.Key_Less:
self._page_control.moveCursor(QtGui.QTextCursor.Start)
intercepted = True
elif key in (QtCore.Qt.Key_Q, QtCore.Qt.Key_Escape):
epatters
* Added a pager with several different options to ConsoleWidget....
r2776 if self._splitter:
self._page_control.hide()
else:
self.layout().setCurrentWidget(self._control)
return True
elif key in (QtCore.Qt.Key_Enter, QtCore.Qt.Key_Return):
new_event = QtGui.QKeyEvent(QtCore.QEvent.KeyPress,
epatters
Numerous usability enhancements to the Qt console widget, particularly with regard to key bindings.
r2897 QtCore.Qt.Key_PageDown,
QtCore.Qt.NoModifier)
QtGui.qApp.sendEvent(self._page_control, new_event)
return True
elif key == QtCore.Qt.Key_Backspace:
new_event = QtGui.QKeyEvent(QtCore.QEvent.KeyPress,
QtCore.Qt.Key_PageUp,
epatters
* Added a pager with several different options to ConsoleWidget....
r2776 QtCore.Qt.NoModifier)
QtGui.qApp.sendEvent(self._page_control, new_event)
return True
return False
epatters
* Fleshed out IPythonWidget's style control....
r2725 def _format_as_columns(self, items, separator=' '):
epatters
* ConsoleWidget now has better support for non-GUI tab completion. Multiple matches are formatted into columns....
r2723 """ Transform a list of strings into a single string with columns.
Parameters
----------
epatters
* Fleshed out IPythonWidget's style control....
r2725 items : sequence of strings
epatters
* ConsoleWidget now has better support for non-GUI tab completion. Multiple matches are formatted into columns....
r2723 The strings to process.
separator : str, optional [default is two spaces]
The string that separates columns.
Returns
-------
The formatted string.
"""
epatters
Replaced external module for formatting columns with adapted code.
r2724 # Note: this code is adapted from columnize 0.3.2.
# See http://code.google.com/p/pycolumnize/
epatters
Fixed regressions in the pure Python kernel.
r2867 # Calculate the number of characters available.
epatters
Cleanup and minor UI fixes.
r2772 width = self._control.viewport().width()
epatters
Improved the size hint for ConsoleWidget. We now acheive a width of 80 characters, through a mixture of better margin calculation and, well, fudging a little bit.
r2882 char_width = QtGui.QFontMetrics(self.font).maxWidth()
epatters
Fixed regressions in the pure Python kernel.
r2867 displaywidth = max(10, (width / char_width) - 1)
epatters
Replaced external module for formatting columns with adapted code.
r2724
epatters
* Fleshed out IPythonWidget's style control....
r2725 # Some degenerate cases.
epatters
Replaced external module for formatting columns with adapted code.
r2724 size = len(items)
if size == 0:
epatters
* Fleshed out IPythonWidget's style control....
r2725 return '\n'
epatters
Replaced external module for formatting columns with adapted code.
r2724 elif size == 1:
return '%s\n' % str(items[0])
# Try every row count from 1 upwards
array_index = lambda nrows, row, col: nrows*col + row
for nrows in range(1, size):
ncols = (size + nrows - 1) // nrows
colwidths = []
totwidth = -len(separator)
for col in range(ncols):
# Get max column width for this column
colwidth = 0
for row in range(nrows):
i = array_index(nrows, row, col)
if i >= size: break
x = items[i]
colwidth = max(colwidth, len(x))
colwidths.append(colwidth)
totwidth += colwidth + len(separator)
if totwidth > displaywidth:
break
if totwidth <= displaywidth:
break
# The smallest number of rows computed and the max widths for each
# column has been obtained. Now we just have to format each of the rows.
string = ''
for row in range(nrows):
texts = []
for col in range(ncols):
i = row + nrows*col
if i >= size:
texts.append('')
else:
texts.append(items[i])
while texts and not texts[-1]:
del texts[-1]
for col in range(len(texts)):
texts[col] = texts[col].ljust(colwidths[col])
epatters
* Fleshed out IPythonWidget's style control....
r2725 string += '%s\n' % str(separator.join(texts))
epatters
Replaced external module for formatting columns with adapted code.
r2724 return string
epatters
* ConsoleWidget now has better support for non-GUI tab completion. Multiple matches are formatted into columns....
r2723
epatters
* IPythonWidget now has IPython-style prompts that are futher stylabla via CSS...
r2715 def _get_block_plain_text(self, block):
""" Given a QTextBlock, return its unformatted text.
"""
cursor = QtGui.QTextCursor(block)
cursor.movePosition(QtGui.QTextCursor.StartOfBlock)
cursor.movePosition(QtGui.QTextCursor.EndOfBlock,
QtGui.QTextCursor.KeepAnchor)
return str(cursor.selection().toPlainText())
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736
def _get_cursor(self):
""" Convenience method that returns a cursor for the current position.
"""
return self._control.textCursor()
epatters
Initial checkin of Qt frontend code.
r2602
def _get_end_cursor(self):
""" Convenience method that returns a cursor for the last character.
"""
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 cursor = self._control.textCursor()
epatters
Initial checkin of Qt frontend code.
r2602 cursor.movePosition(QtGui.QTextCursor.End)
return cursor
epatters
* Tab completion now uses the correct cursor position....
r2841 def _get_input_buffer_cursor_column(self):
""" Returns the column of the cursor in the input buffer, excluding the
contribution by the prompt, or -1 if there is no such column.
"""
prompt = self._get_input_buffer_cursor_prompt()
if prompt is None:
return -1
else:
cursor = self._control.textCursor()
return cursor.columnNumber() - len(prompt)
epatters
* Implemented "smart paste" for ConsoleWidget. Continuation prompts are now inserted automatically on paste....
r2763 def _get_input_buffer_cursor_line(self):
epatters
* Tab completion now uses the correct cursor position....
r2841 """ Returns line of the input buffer that contains the cursor, or None
if there is no such line.
"""
prompt = self._get_input_buffer_cursor_prompt()
if prompt is None:
return None
else:
cursor = self._control.textCursor()
text = self._get_block_plain_text(cursor.block())
return text[len(prompt):]
def _get_input_buffer_cursor_prompt(self):
""" Returns the (plain text) prompt for line of the input buffer that
contains the cursor, or None if there is no such line.
epatters
* Implemented "smart paste" for ConsoleWidget. Continuation prompts are now inserted automatically on paste....
r2763 """
if self._executing:
return None
cursor = self._control.textCursor()
if cursor.position() >= self._prompt_pos:
if cursor.blockNumber() == self._get_prompt_cursor().blockNumber():
epatters
* Tab completion now uses the correct cursor position....
r2841 return self._prompt
epatters
* Implemented "smart paste" for ConsoleWidget. Continuation prompts are now inserted automatically on paste....
r2763 else:
epatters
* Tab completion now uses the correct cursor position....
r2841 return self._continuation_prompt
epatters
* Implemented "smart paste" for ConsoleWidget. Continuation prompts are now inserted automatically on paste....
r2763 else:
return None
epatters
Initial checkin of Qt frontend code.
r2602 def _get_prompt_cursor(self):
""" Convenience method that returns a cursor for the prompt position.
"""
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 cursor = self._control.textCursor()
epatters
Initial checkin of Qt frontend code.
r2602 cursor.setPosition(self._prompt_pos)
return cursor
def _get_selection_cursor(self, start, end):
""" Convenience method that returns a cursor with text selected between
the positions 'start' and 'end'.
"""
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 cursor = self._control.textCursor()
epatters
Initial checkin of Qt frontend code.
r2602 cursor.setPosition(start)
cursor.setPosition(end, QtGui.QTextCursor.KeepAnchor)
return cursor
def _get_word_start_cursor(self, position):
""" Find the start of the word to the left the given position. If a
sequence of non-word characters precedes the first word, skip over
them. (This emulates the behavior of bash, emacs, etc.)
"""
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 document = self._control.document()
epatters
Initial checkin of Qt frontend code.
r2602 position -= 1
epatters
Numerous fixes to ConsoleWidget editing region maintenence code. It now impossible (or at least very difficult :) to break the input region.
r2764 while position >= self._prompt_pos and \
epatters
Initial checkin of Qt frontend code.
r2602 not document.characterAt(position).isLetterOrNumber():
position -= 1
epatters
Numerous fixes to ConsoleWidget editing region maintenence code. It now impossible (or at least very difficult :) to break the input region.
r2764 while position >= self._prompt_pos and \
epatters
Initial checkin of Qt frontend code.
r2602 document.characterAt(position).isLetterOrNumber():
position -= 1
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 cursor = self._control.textCursor()
epatters
Initial checkin of Qt frontend code.
r2602 cursor.setPosition(position + 1)
return cursor
def _get_word_end_cursor(self, position):
""" Find the end of the word to the right the given position. If a
sequence of non-word characters precedes the first word, skip over
them. (This emulates the behavior of bash, emacs, etc.)
"""
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 document = self._control.document()
epatters
Initial checkin of Qt frontend code.
r2602 end = self._get_end_cursor().position()
while position < end and \
not document.characterAt(position).isLetterOrNumber():
position += 1
while position < end and \
document.characterAt(position).isLetterOrNumber():
position += 1
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 cursor = self._control.textCursor()
epatters
Initial checkin of Qt frontend code.
r2602 cursor.setPosition(position)
return cursor
epatters
Fixed several bugs involving the insertion of new lines. Pressing Enter in the ConsoleWidget now works as expected.
r2896 def _insert_continuation_prompt(self, cursor):
""" Inserts new continuation prompt using the specified cursor.
"""
if self._continuation_prompt_html is None:
self._insert_plain_text(cursor, self._continuation_prompt)
else:
self._continuation_prompt = self._insert_html_fetching_plain_text(
cursor, self._continuation_prompt_html)
epatters
Added machinery to IPythonWidget for updating the previous prompt number.
r2733 def _insert_html(self, cursor, html):
epatters
Fixed bug with ConsoleWidget smart paste.
r2787 """ Inserts HTML using the specified cursor in such a way that future
epatters
Added machinery to IPythonWidget for updating the previous prompt number.
r2733 formatting is unaffected.
"""
epatters
Numerous fixes to ConsoleWidget editing region maintenence code. It now impossible (or at least very difficult :) to break the input region.
r2764 cursor.beginEditBlock()
epatters
Added machinery to IPythonWidget for updating the previous prompt number.
r2733 cursor.insertHtml(html)
epatters
* Implemented "smart paste" for ConsoleWidget. Continuation prompts are now inserted automatically on paste....
r2763 # After inserting HTML, the text document "remembers" it's in "html
# mode", which means that subsequent calls adding plain text will result
# in unwanted formatting, lost tab characters, etc. The following code
epatters
Updated IPythonWidget to use new prompt information. Initial prompt requests are not implemented.
r2797 # hacks around this behavior, which I consider to be a bug in Qt, by
# (crudely) resetting the document's style state.
cursor.movePosition(QtGui.QTextCursor.Left,
epatters
Added machinery to IPythonWidget for updating the previous prompt number.
r2733 QtGui.QTextCursor.KeepAnchor)
epatters
* Implemented "smart paste" for ConsoleWidget. Continuation prompts are now inserted automatically on paste....
r2763 if cursor.selection().toPlainText() == ' ':
cursor.removeSelectedText()
epatters
Updated IPythonWidget to use new prompt information. Initial prompt requests are not implemented.
r2797 else:
cursor.movePosition(QtGui.QTextCursor.Right)
epatters
* Implemented "smart paste" for ConsoleWidget. Continuation prompts are now inserted automatically on paste....
r2763 cursor.insertText(' ', QtGui.QTextCharFormat())
epatters
Numerous fixes to ConsoleWidget editing region maintenence code. It now impossible (or at least very difficult :) to break the input region.
r2764 cursor.endEditBlock()
epatters
* Implemented "smart paste" for ConsoleWidget. Continuation prompts are now inserted automatically on paste....
r2763
epatters
Fixed bug with ConsoleWidget smart paste.
r2787 def _insert_html_fetching_plain_text(self, cursor, html):
""" Inserts HTML using the specified cursor, then returns its plain text
version.
"""
epatters
* Fixed bug where syntax highlighting was lost after updating a prompt with a bad number....
r2800 cursor.beginEditBlock()
cursor.removeSelectedText()
epatters
Fixed bug with ConsoleWidget smart paste.
r2787 start = cursor.position()
self._insert_html(cursor, html)
end = cursor.position()
cursor.setPosition(start, QtGui.QTextCursor.KeepAnchor)
text = str(cursor.selection().toPlainText())
epatters
* Fixed bug where syntax highlighting was lost after updating a prompt with a bad number....
r2800
epatters
Fixed bug with ConsoleWidget smart paste.
r2787 cursor.setPosition(end)
epatters
* Fixed bug where syntax highlighting was lost after updating a prompt with a bad number....
r2800 cursor.endEditBlock()
epatters
Fixed bug with ConsoleWidget smart paste.
r2787 return text
epatters
* Added a pager with several different options to ConsoleWidget....
r2776 def _insert_plain_text(self, cursor, text):
""" Inserts plain text using the specified cursor, processing ANSI codes
if enabled.
"""
cursor.beginEditBlock()
if self.ansi_codes:
for substring in self._ansi_processor.split_string(text):
epatters
Added support for ANSI erase codes. Clearing the console via ANSI escape sequences is now supported.
r2783 for action in self._ansi_processor.actions:
if action.kind == 'erase' and action.area == 'screen':
cursor.select(QtGui.QTextCursor.Document)
cursor.removeSelectedText()
epatters
* Added a pager with several different options to ConsoleWidget....
r2776 format = self._ansi_processor.get_format()
cursor.insertText(substring, format)
else:
cursor.insertText(text)
cursor.endEditBlock()
epatters
Fixed bug with ConsoleWidget smart paste.
r2787 def _insert_plain_text_into_buffer(self, text):
epatters
* Implemented "smart paste" for ConsoleWidget. Continuation prompts are now inserted automatically on paste....
r2763 """ Inserts text into the input buffer at the current cursor position,
ensuring that continuation prompts are inserted as necessary.
"""
lines = str(text).splitlines(True)
if lines:
self._keep_cursor_in_buffer()
cursor = self._control.textCursor()
cursor.beginEditBlock()
cursor.insertText(lines[0])
for line in lines[1:]:
if self._continuation_prompt_html is None:
cursor.insertText(self._continuation_prompt)
else:
epatters
Fixed bug with ConsoleWidget smart paste.
r2787 self._continuation_prompt = \
self._insert_html_fetching_plain_text(
cursor, self._continuation_prompt_html)
epatters
* Implemented "smart paste" for ConsoleWidget. Continuation prompts are now inserted automatically on paste....
r2763 cursor.insertText(line)
cursor.endEditBlock()
self._control.setTextCursor(cursor)
epatters
Added machinery to IPythonWidget for updating the previous prompt number.
r2733
epatters
The FrontendWidget now performs tab-completion more aggressively.
r2847 def _in_buffer(self, position=None):
""" Returns whether the current cursor (or, if specified, a position) is
inside the editing region.
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 """
epatters
Numerous fixes to ConsoleWidget editing region maintenence code. It now impossible (or at least very difficult :) to break the input region.
r2764 cursor = self._control.textCursor()
epatters
The FrontendWidget now performs tab-completion more aggressively.
r2847 if position is None:
position = cursor.position()
else:
cursor.setPosition(position)
epatters
Numerous fixes to ConsoleWidget editing region maintenence code. It now impossible (or at least very difficult :) to break the input region.
r2764 line = cursor.blockNumber()
prompt_line = self._get_prompt_cursor().blockNumber()
if line == prompt_line:
return position >= self._prompt_pos
elif line > prompt_line:
cursor.movePosition(QtGui.QTextCursor.StartOfBlock)
prompt_pos = cursor.position() + len(self._continuation_prompt)
return position >= prompt_pos
return False
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736
def _keep_cursor_in_buffer(self):
""" Ensures that the cursor is inside the editing region. Returns
whether the cursor was moved.
"""
epatters
The FrontendWidget now performs tab-completion more aggressively.
r2847 moved = not self._in_buffer()
if moved:
cursor = self._control.textCursor()
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 cursor.movePosition(QtGui.QTextCursor.End)
self._control.setTextCursor(cursor)
epatters
The FrontendWidget now performs tab-completion more aggressively.
r2847 return moved
epatters
* Added a pager with several different options to ConsoleWidget....
r2776
def _page(self, text):
epatters
The ConsoleWidget now only pages text if it exceeds the height of the visible window.
r2843 """ Displays text using the pager if it exceeds the height of the
visible area.
epatters
* Added a pager with several different options to ConsoleWidget....
r2776 """
epatters
Made IPythonWidget and its subclasses Configurable.
r2884 if self.paging == 'none':
epatters
* Added a pager with several different options to ConsoleWidget....
r2776 self._append_plain_text(text)
else:
epatters
The ConsoleWidget now only pages text if it exceeds the height of the visible window.
r2843 line_height = QtGui.QFontMetrics(self.font).height()
minlines = self._control.viewport().height() / line_height
if re.match("(?:[^\n]*\n){%i}" % minlines, text):
epatters
Made IPythonWidget and its subclasses Configurable.
r2884 if self.paging == 'custom':
epatters
The ConsoleWidget now only pages text if it exceeds the height of the visible window.
r2843 self.custom_page_requested.emit(text)
else:
self._page_control.clear()
cursor = self._page_control.textCursor()
self._insert_plain_text(cursor, text)
self._page_control.moveCursor(QtGui.QTextCursor.Start)
self._page_control.viewport().resize(self._control.size())
if self._splitter:
self._page_control.show()
self._page_control.setFocus()
else:
self.layout().setCurrentWidget(self._page_control)
epatters
* Added a pager with several different options to ConsoleWidget....
r2776 else:
epatters
The ConsoleWidget now only pages text if it exceeds the height of the visible window.
r2843 self._append_plain_text(text)
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736
epatters
Initial checkin of Qt frontend code.
r2602 def _prompt_started(self):
""" Called immediately after a new prompt is displayed.
"""
epatters
* Refactored ConsoleWidget execution API for greater flexibility and clarity....
r2688 # Temporarily disable the maximum block count to permit undo/redo and
# to ensure that the prompt position does not change due to truncation.
epatters
* The ConsoleWidget now has full undo/redo support. Previously, the undo/redo history was cleared after every continuation prompt. This is no longer the case....
r2864 # Because setting this property clears the undo/redo history, we only
# set it if we have to.
if self._control.document().maximumBlockCount() > 0:
self._control.document().setMaximumBlockCount(0)
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 self._control.setUndoRedoEnabled(True)
epatters
* Added undo/redo support to ConsoleWidget...
r2615
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 self._control.setReadOnly(False)
self._control.moveCursor(QtGui.QTextCursor.End)
epatters
* Added undo/redo support to ConsoleWidget...
r2615
epatters
Initial checkin of Qt frontend code.
r2602 self._executing = False
self._prompt_started_hook()
def _prompt_finished(self):
""" Called immediately after a prompt is finished, i.e. when some input
will be processed and a new prompt displayed.
"""
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 self._control.setReadOnly(True)
epatters
Initial checkin of Qt frontend code.
r2602 self._prompt_finished_hook()
epatters
Reading a line is now correctly implemented in ConsoleWidget.
r2706 def _readline(self, prompt='', callback=None):
""" Reads one line of input from the user.
Parameters
----------
prompt : str, optional
The prompt to print before reading the line.
callback : callable, optional
A callback to execute with the read line. If not specified, input is
read *synchronously* and this method does not return until it has
been read.
Returns
-------
If a callback is specified, returns nothing. Otherwise, returns the
input string with the trailing newline stripped.
epatters
Progress on raw_input.
r2705 """
epatters
Reading a line is now correctly implemented in ConsoleWidget.
r2706 if self._reading:
raise RuntimeError('Cannot read a line. Widget is already reading.')
if not callback and not self.isVisible():
# If the user cannot see the widget, this function cannot return.
epatters
* Fixed regression from last commit: syntax highlighting works robustly again....
r2866 raise RuntimeError('Cannot synchronously read a line if the widget '
epatters
Reading a line is now correctly implemented in ConsoleWidget.
r2706 'is not visible!')
epatters
Progress on raw_input.
r2705
self._reading = True
epatters
Fixed bugs with raw_input and finished and implementing InStream.
r2708 self._show_prompt(prompt, newline=False)
epatters
Reading a line is now correctly implemented in ConsoleWidget.
r2706
if callback is None:
self._reading_callback = None
while self._reading:
QtCore.QCoreApplication.processEvents()
return self.input_buffer.rstrip('\n')
else:
self._reading_callback = lambda: \
callback(self.input_buffer.rstrip('\n'))
epatters
Progress on raw_input.
r2705
epatters
* IPythonWidget now has IPython-style prompts that are futher stylabla via CSS...
r2715 def _set_continuation_prompt(self, prompt, html=False):
""" Sets the continuation prompt.
Parameters
----------
prompt : str
The prompt to show when more input is needed.
html : bool, optional (default False)
If set, the prompt will be inserted as formatted HTML. Otherwise,
the prompt will be treated as plain text, though ANSI color codes
will be handled.
"""
if html:
self._continuation_prompt_html = prompt
else:
self._continuation_prompt = prompt
self._continuation_prompt_html = None
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736
def _set_cursor(self, cursor):
""" Convenience method to set the current cursor.
"""
self._control.setTextCursor(cursor)
epatters
* IPythonWidget now has IPython-style prompts that are futher stylabla via CSS...
r2715
epatters
* Fixed context menu breakge after previous commit....
r2737 def _show_context_menu(self, pos):
""" Shows a context menu at the given QPoint (in widget coordinates).
"""
menu = QtGui.QMenu()
epatters
* Added a custom context menu to the RichIPythonWidget which allows saving plot as an images or SVG documents....
r2765 copy_action = menu.addAction('Copy', self.copy)
epatters
* Fixed context menu breakge after previous commit....
r2737 copy_action.setEnabled(self._get_cursor().hasSelection())
copy_action.setShortcut(QtGui.QKeySequence.Copy)
epatters
* Added a custom context menu to the RichIPythonWidget which allows saving plot as an images or SVG documents....
r2765 paste_action = menu.addAction('Paste', self.paste)
epatters
* Fixed bug where ConsoleWidget accepted non-ASCII characters on paste (and also rich text in 'rich' mode)...
r2762 paste_action.setEnabled(self.can_paste())
epatters
* Fixed context menu breakge after previous commit....
r2737 paste_action.setShortcut(QtGui.QKeySequence.Paste)
epatters
* Added a custom context menu to the RichIPythonWidget which allows saving plot as an images or SVG documents....
r2765 menu.addSeparator()
menu.addAction('Select All', self.select_all)
epatters
* Fixed context menu breakge after previous commit....
r2737
menu.exec_(self._control.mapToGlobal(pos))
epatters
* IPythonWidget now has IPython-style prompts that are futher stylabla via CSS...
r2715 def _show_prompt(self, prompt=None, html=False, newline=True):
epatters
Fixed bugs with raw_input and finished and implementing InStream.
r2708 """ Writes a new prompt at the end of the buffer.
Parameters
----------
prompt : str, optional
The prompt to show. If not specified, the previous prompt is used.
epatters
* IPythonWidget now has IPython-style prompts that are futher stylabla via CSS...
r2715 html : bool, optional (default False)
Only relevant when a prompt is specified. If set, the prompt will
be inserted as formatted HTML. Otherwise, the prompt will be treated
as plain text, though ANSI color codes will be handled.
epatters
Fixed bugs with raw_input and finished and implementing InStream.
r2708 newline : bool, optional (default True)
If set, a new line will be written before showing the prompt if
there is not already a newline at the end of the buffer.
"""
epatters
* IPythonWidget now has IPython-style prompts that are futher stylabla via CSS...
r2715 # Insert a preliminary newline, if necessary.
epatters
Fixed bugs with raw_input and finished and implementing InStream.
r2708 if newline:
cursor = self._get_end_cursor()
if cursor.position() > 0:
cursor.movePosition(QtGui.QTextCursor.Left,
QtGui.QTextCursor.KeepAnchor)
if str(cursor.selection().toPlainText()) != '\n':
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 self._append_plain_text('\n')
epatters
Progress on raw_input.
r2705
epatters
* IPythonWidget now has IPython-style prompts that are futher stylabla via CSS...
r2715 # Write the prompt.
epatters
* Fixed regression from last commit: syntax highlighting works robustly again....
r2866 self._append_plain_text(self._prompt_sep)
epatters
* IPythonWidget now has IPython-style prompts that are futher stylabla via CSS...
r2715 if prompt is None:
if self._prompt_html is None:
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 self._append_plain_text(self._prompt)
epatters
* IPythonWidget now has IPython-style prompts that are futher stylabla via CSS...
r2715 else:
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 self._append_html(self._prompt_html)
epatters
* IPythonWidget now has IPython-style prompts that are futher stylabla via CSS...
r2715 else:
if html:
self._prompt = self._append_html_fetching_plain_text(prompt)
self._prompt_html = prompt
else:
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 self._append_plain_text(prompt)
epatters
* IPythonWidget now has IPython-style prompts that are futher stylabla via CSS...
r2715 self._prompt = prompt
self._prompt_html = None
epatters
Progress on raw_input.
r2705
epatters
Initial checkin of Qt frontend code.
r2602 self._prompt_pos = self._get_end_cursor().position()
self._prompt_started()
class HistoryConsoleWidget(ConsoleWidget):
""" A ConsoleWidget that keeps a history of the commands that have been
executed.
"""
#---------------------------------------------------------------------------
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 # 'object' interface
epatters
Initial checkin of Qt frontend code.
r2602 #---------------------------------------------------------------------------
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 def __init__(self, *args, **kw):
super(HistoryConsoleWidget, self).__init__(*args, **kw)
epatters
Initial checkin of Qt frontend code.
r2602 self._history = []
self._history_index = 0
#---------------------------------------------------------------------------
# 'ConsoleWidget' public interface
#---------------------------------------------------------------------------
epatters
* Refactored ConsoleWidget execution API for greater flexibility and clarity....
r2688 def execute(self, source=None, hidden=False, interactive=False):
epatters
Initial checkin of Qt frontend code.
r2602 """ Reimplemented to the store history.
"""
epatters
* Fixed history breakage due to recent refactoring....
r2689 if not hidden:
history = self.input_buffer if source is None else source
epatters
* Refactored ConsoleWidget execution API for greater flexibility and clarity....
r2688
executed = super(HistoryConsoleWidget, self).execute(
source, hidden, interactive)
if executed and not hidden:
epatters
* Added support for Ctrl-L per Fernando's request....
r2880 # Save the command unless it was a blank line.
history = history.rstrip()
if history:
self._history.append(history)
self._history_index = len(self._history)
epatters
* Refactored ConsoleWidget execution API for greater flexibility and clarity....
r2688
epatters
Initial checkin of Qt frontend code.
r2602 return executed
#---------------------------------------------------------------------------
# 'ConsoleWidget' abstract interface
#---------------------------------------------------------------------------
def _up_pressed(self):
""" Called when the up key is pressed. Returns whether to continue
processing the event.
"""
prompt_cursor = self._get_prompt_cursor()
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 if self._get_cursor().blockNumber() == prompt_cursor.blockNumber():
epatters
Initial checkin of Qt frontend code.
r2602 self.history_previous()
# Go to the first line of prompt for seemless history scrolling.
cursor = self._get_prompt_cursor()
cursor.movePosition(QtGui.QTextCursor.EndOfLine)
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 self._set_cursor(cursor)
epatters
Initial checkin of Qt frontend code.
r2602
return False
return True
def _down_pressed(self):
""" Called when the down key is pressed. Returns whether to continue
processing the event.
"""
end_cursor = self._get_end_cursor()
epatters
Refactored ConsoleWidget to encapsulate, rather than inherit from, QPlainTextEdit. This permits a QTextEdit to be substituted for a QPlainTextEdit if desired. It also makes it more clear what is the public interface of ConsoleWidget.
r2736 if self._get_cursor().blockNumber() == end_cursor.blockNumber():
epatters
Initial checkin of Qt frontend code.
r2602 self.history_next()
return False
return True
#---------------------------------------------------------------------------
epatters
* Added support for prompt and history requests to the kernel manager and Qt console frontend....
r2844 # 'HistoryConsoleWidget' public interface
epatters
Initial checkin of Qt frontend code.
r2602 #---------------------------------------------------------------------------
def history_previous(self):
""" If possible, set the input buffer to the previous item in the
history.
"""
if self._history_index > 0:
self._history_index -= 1
self.input_buffer = self._history[self._history_index]
def history_next(self):
""" Set the input buffer to the next item in the history, or a blank
line if there is no subsequent item.
"""
if self._history_index < len(self._history):
self._history_index += 1
if self._history_index < len(self._history):
self.input_buffer = self._history[self._history_index]
else:
self.input_buffer = ''
epatters
* Added support for prompt and history requests to the kernel manager and Qt console frontend....
r2844
#---------------------------------------------------------------------------
# 'HistoryConsoleWidget' protected interface
#---------------------------------------------------------------------------
def _set_history(self, history):
""" Replace the current history with a sequence of history items.
"""
self._history = list(history)
self._history_index = len(self._history)