##// END OF EJS Templates
Search of getcwd and replace with getcwdu. Ignoring core/prompts.py
Search of getcwd and replace with getcwdu. Ignoring core/prompts.py

File last commit:

r4156:16703681
r4208:b4b4ede0
Show More
console_widget.py
1822 lines | 72.2 KiB | text/x-python | PythonLexer
epatters
Integrated the heart beat pausing/unpausing logic with the (Qt)KernelManager.
r3032 """ An abstract base class for console-type widgets.
Fernando Perez
Centralize Qt font selection into a generic utility....
r2986 """
#-----------------------------------------------------------------------------
# Imports
#-----------------------------------------------------------------------------
epatters
Initial checkin of Qt frontend code.
r2602 # Standard library imports
Evan Patterson
Paved the way for PySide support....
r3304 import os
epatters
Major improvements to terminal-style tab completion. Still work to be done, but a decent start.
r2919 from os.path import commonprefix
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
Evan Patterson
Paved the way for PySide support....
r3304 from unicodedata import category
epatters
Initial checkin of Qt frontend code.
r2602
# System library imports
Evan Patterson
Paved the way for PySide support....
r3304 from IPython.external.qt import QtCore, QtGui
epatters
Initial checkin of Qt frontend code.
r2602
# Local imports
epatters
Made IPythonWidget and its subclasses Configurable.
r2884 from IPython.config.configurable import Configurable
epatters
Refactored ConsoleWidget's HTML exportaton code + other minor code cleanup.
r3361 from IPython.frontend.qt.rich_text import HtmlExporter
Fernando Perez
Centralize Qt font selection into a generic utility....
r2986 from IPython.frontend.qt.util import MetaQObjectHasTraits, get_font
MinRK
qt font family/size configurable
r3972 from IPython.utils.traitlets import Bool, Enum, Int, Unicode
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
Add Emacs-style kill ring to Qt console....
r3767 from kill_ring import QtKillRing
epatters
Initial checkin of Qt frontend code.
r2602
Fernando Perez
Centralize Qt font selection into a generic utility....
r2986 #-----------------------------------------------------------------------------
Evan Patterson
Paved the way for PySide support....
r3304 # Functions
#-----------------------------------------------------------------------------
def is_letter_or_number(char):
""" Returns whether the specified unicode character is a letter or a number.
"""
cat = category(char)
return cat.startswith('L') or cat.startswith('N')
#-----------------------------------------------------------------------------
Fernando Perez
Centralize Qt font selection into a generic utility....
r2986 # Classes
#-----------------------------------------------------------------------------
epatters
Initial checkin of Qt frontend code.
r2602
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
Fixed font changes not being propagated to CallTipWidget.
r3031 #------ Configuration ------------------------------------------------------
MinRK
QtConsole now uses newapp
r3971 ansi_codes = Bool(True, config=True,
help="Whether to process ANSI escape codes."
)
buffer_size = Int(500, config=True,
help="""
The maximum number of lines of text before truncation. Specifying a
non-positive number disables text truncation (not recommended).
"""
)
gui_completion = Bool(False, config=True,
epatters
Fix ConsoleWidget unsetting execution flag when using raw_input.
r4061 help="""
Use a list widget instead of plain text output for tab completion.
"""
MinRK
QtConsole now uses newapp
r3971 )
epatters
Made IPythonWidget and its subclasses Configurable.
r2884 # NOTE: this value can only be specified during initialization.
MinRK
QtConsole now uses newapp
r3971 kind = Enum(['plain', 'rich'], default_value='plain', config=True,
help="""
epatters
Fix ConsoleWidget unsetting execution flag when using raw_input.
r4061 The type of underlying text widget to use. Valid values are 'plain',
which specifies a QPlainTextEdit, and 'rich', which specifies a
QTextEdit.
MinRK
QtConsole now uses newapp
r3971 """
)
epatters
Made IPythonWidget and its subclasses Configurable.
r2884 # NOTE: this value can only be specified during initialization.
paging = Enum(['inside', 'hsplit', 'vsplit', 'custom', 'none'],
MinRK
QtConsole now uses newapp
r3971 default_value='inside', config=True,
help="""
The type of paging to use. Valid values are:
MinRK
code updates per review of PR #454
r4021
MinRK
QtConsole now uses newapp
r3971 'inside' : The widget pages like a traditional terminal.
'hsplit' : When paging is requested, the widget is split
MinRK
code updates per review of PR #454
r4021 horizontally. The top pane contains the console, and the
bottom pane contains the paged text.
epatters
Fix ConsoleWidget unsetting execution flag when using raw_input.
r4061 'vsplit' : Similar to 'hsplit', except that a vertical splitter
used.
MinRK
QtConsole now uses newapp
r3971 'custom' : No action is taken by the widget beyond emitting a
MinRK
code updates per review of PR #454
r4021 'custom_page_requested(str)' signal.
MinRK
QtConsole now uses newapp
r3971 'none' : The text is written directly to the console.
""")
epatters
* Added option (disabled by default) to ConsoleWidget for overriding global/window-level shortcuts....
r2668
MinRK
qt font family/size configurable
r3972 font_family = Unicode(config=True,
help="""The font family to use for the console.
On OSX this defaults to Monaco, on Windows the default is
Consolas with fallback of Courier, and on other platforms
MinRK
use Monospace as default font on Linux
r3975 the default is Monospace.
MinRK
qt font family/size configurable
r3972 """)
def _font_family_default(self):
if sys.platform == 'win32':
# Consolas ships with Vista/Win7, fallback to Courier if needed
return 'Consolas'
elif sys.platform == 'darwin':
# OSX always has Monaco, no need for a fallback
return 'Monaco'
else:
MinRK
use Monospace as default font on Linux
r3975 # Monospace should always exist, no need for a fallback
return 'Monospace'
MinRK
qt font family/size configurable
r3972
font_size = Int(config=True,
help="""The font size. If unconfigured, Qt will be entrusted
with the size of the font.
""")
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
Fixed font changes not being propagated to CallTipWidget.
r3031 #------ Signals ------------------------------------------------------------
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.
Evan Patterson
Paved the way for PySide support....
r3304 copy_available = QtCore.Signal(bool)
redo_available = QtCore.Signal(bool)
undo_available = QtCore.Signal(bool)
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 # Signal emitted when paging is needed and the paging style has been
# specified as 'custom'.
Evan Patterson
Paved the way for PySide support....
r3304 custom_page_requested = QtCore.Signal(object)
epatters
* Added a pager with several different options to ConsoleWidget....
r2776
epatters
Fixed font changes not being propagated to CallTipWidget.
r3031 # Signal emitted when the font is changed.
Evan Patterson
Paved the way for PySide support....
r3304 font_changed = QtCore.Signal(QtGui.QFont)
epatters
Fixed font changes not being propagated to CallTipWidget.
r3031
#------ Protected class variables ------------------------------------------
epatters
Fix for issue 173.
r3310 # When the control key is down, these keys are mapped.
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_P : QtCore.Qt.Key_Up,
QtCore.Qt.Key_N : QtCore.Qt.Key_Down,
epatters
Added Ctrl+H and Ctrl+U shortcuts to Qt console....
r3468 QtCore.Qt.Key_H : QtCore.Qt.Key_Backspace,
epatters
Initial checkin of Qt frontend code.
r2602 QtCore.Qt.Key_D : QtCore.Qt.Key_Delete, }
epatters
Fix for issue 173.
r3310 if not sys.platform == 'darwin':
# On OS X, Ctrl-E already does the right thing, whereas End moves the
# cursor to the bottom of the buffer.
_ctrl_down_remap[QtCore.Qt.Key_E] = QtCore.Qt.Key_End
epatters
Fixed font changes not being propagated to CallTipWidget.
r3031
epatters
Fix for issue 173.
r3310 # The shortcuts defined by this widget. We need to keep track of these to
# support 'override_shortcuts' above.
epatters
* Added ability to interrupt a kernel to FrontendWidget...
r2687 _shortcuts = set(_ctrl_down_remap.keys() +
epatters
* Ctrl-G and Escape now clear the input buffer....
r2924 [ QtCore.Qt.Key_C, QtCore.Qt.Key_G, QtCore.Qt.Key_O,
QtCore.Qt.Key_V ])
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
Improve Qt console's placement of text appended before a prompt.
r4058 self._append_before_prompt_pos = 0
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
epatters
Fixed resize flicker and drag safety.
r3043 self._filter_drag = False
self._filter_resize = False
epatters
Refactored ConsoleWidget's HTML exportaton code + other minor code cleanup.
r3361 self._html_exporter = HtmlExporter(self._control)
Evan Patterson
Handle setting input buffer during execution in Qt console.
r3931 self._input_buffer_executing = ''
self._input_buffer_pending = ''
epatters
Add Emacs-style kill ring to Qt console....
r3767 self._kill_ring = QtKillRing(self._control)
epatters
Initial checkin of Qt frontend code.
r2602 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
Major improvements to terminal-style tab completion. Still work to be done, but a decent start.
r2919 self._text_completing_pos = 0
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
MinRK
HTML/XML export now single menu entry...
r3162 # Configure actions.
action = QtGui.QAction('Print', None)
action.setEnabled(True)
MinRK
print shortcut -> ctrl+shift+P if there is a collision with ctrl+P
r3193 printkey = QtGui.QKeySequence(QtGui.QKeySequence.Print)
if printkey.matches("Ctrl+P") and sys.platform != 'darwin':
epatters
Fix for issue 173.
r3310 # Only override the default if there is a collision.
epatters
Refactored ConsoleWidget's HTML exportaton code + other minor code cleanup.
r3361 # Qt ctrl = cmd on OSX, so the match gets a false positive on OSX.
MinRK
print shortcut -> ctrl+shift+P if there is a collision with ctrl+P
r3193 printkey = "Ctrl+Shift+P"
action.setShortcut(printkey)
MinRK
HTML/XML export now single menu entry...
r3162 action.triggered.connect(self.print_)
self.addAction(action)
self._print_action = action
action = QtGui.QAction('Save as HTML/XML', None)
action.setShortcut(QtGui.QKeySequence.Save)
epatters
Added an 'export_html' method back to the public interface of ConsoleWidget.
r3365 action.triggered.connect(self.export_html)
MinRK
HTML/XML export now single menu entry...
r3162 self.addAction(action)
self._export_action = action
action = QtGui.QAction('Select All', None)
action.setEnabled(True)
action.setShortcut(QtGui.QKeySequence.SelectAll)
action.triggered.connect(self.select_all)
self.addAction(action)
self._select_all_action = action
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
Made middle-click paste safe. Fixes bug reported by fperez.
r2937 # Make middle-click paste safe.
elif etype == QtCore.QEvent.MouseButtonRelease and \
event.button() == QtCore.Qt.MidButton and \
obj == self._control.viewport():
epatters
Fixed numerous bugs with tab completion, including the one recently reported by fperez.
r2939 cursor = self._control.cursorForPosition(event.pos())
epatters
Made middle-click paste safe. Fixes bug reported by fperez.
r2937 self._control.setTextCursor(cursor)
self.paste(QtGui.QClipboard.Selection)
return True
epatters
Minor bug fix to ConsoleWidget scrollbar management.
r3009 # Manually adjust the scrollbars *after* a resize event is dispatched.
epatters
Fixed resize flicker and drag safety.
r3043 elif etype == QtCore.QEvent.Resize and not self._filter_resize:
self._filter_resize = True
QtGui.qApp.sendEvent(obj, event)
self._adjust_scrollbars()
self._filter_resize = False
return True
epatters
Minor bug fix to ConsoleWidget scrollbar management.
r3009
epatters
Cmd-C will no longer interrupt the kernel in Mac OS (only Ctrl-C will do this).
r2941 # Override shortcuts for all filtered widgets.
epatters
Cleanup and minor UI fixes.
r2772 elif etype == QtCore.QEvent.ShortcutOverride and \
epatters
* Moved shutdown_kernel method from FrontendWidget to KernelManager....
r2961 self.override_shortcuts and \
epatters
Cleanup and minor UI fixes.
r2772 self._control_key_down(event.modifiers()) and \
event.key() in self._shortcuts:
event.accept()
epatters
Fixed resize flicker and drag safety.
r3043 # Ensure that drags are safe. The problem is that the drag starting
# logic, which determines whether the drag is a Copy or Move, is locked
# down in QTextControl. If the widget is editable, which it must be if
# we're not executing, the drag will be a Move. The following hack
# prevents QTextControl from deleting the text by clearing the selection
# when a drag leave event originating from this widget is dispatched.
# The fact that we have to clear the user's selection is unfortunate,
# but the alternative--trying to prevent Qt from using its hardwired
# drag logic and writing our own--is worse.
elif etype == QtCore.QEvent.DragEnter and \
obj == self._control.viewport() and \
event.source() == self._control.viewport():
self._filter_drag = True
elif etype == QtCore.QEvent.DragLeave and \
obj == self._control.viewport() and \
self._filter_drag:
cursor = self._control.textCursor()
cursor.clearSelection()
self._control.setTextCursor(cursor)
self._filter_drag = False
epatters
ConsoleWidget now supports drag and drop.
r3042 # Ensure that drops are safe.
elif etype == QtCore.QEvent.Drop and obj == self._control.viewport():
cursor = self._control.cursorForPosition(event.pos())
if self._in_buffer(cursor.position()):
Evan Patterson
Paved the way for PySide support....
r3304 text = event.mimeData().text()
epatters
Fixed bug reported by fperez and removed code with duplicated functionality.
r3048 self._insert_plain_text_into_buffer(cursor, text)
epatters
ConsoleWidget now supports drag and drop.
r3042
# Qt is expecting to get something here--drag and drop occurs in its
# own event loop. Send a DragLeave event to end it.
QtGui.qApp.sendEvent(obj, QtGui.QDragLeaveEvent())
epatters
* Added "smart copy" support to FrontendWidget and ConsoleWidget. Tabs are expanded and prompts are stripped....
r2971 return 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 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
Font width calculation fix for certain Mac OS systems.
r2935 # Note 1: 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.
# Note 2: QFontMetrics.maxWidth is not used here or anywhere else due
# to a Qt bug on certain Mac OS systems where it returns 0.
width = font_metrics.width(' ') * 81 + margin
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 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
* Added support to KernelManager for starting a subset of the four channels....
r2994 def can_copy(self):
""" Returns whether text can be copied to the clipboard.
"""
return self._control.textCursor().hasSelection()
epatters
* Added Cut support to ConsoleWidget....
r2990 def can_cut(self):
""" Returns whether text can be cut to the clipboard.
"""
cursor = self._control.textCursor()
return (cursor.hasSelection() and
self._in_buffer(cursor.anchor()) and
self._in_buffer(cursor.position()))
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.
"""
if self._control.textInteractionFlags() & QtCore.Qt.TextEditable:
Evan Patterson
Paved the way for PySide support....
r3304 return bool(QtGui.QApplication.clipboard().text())
epatters
* Fixed bug where ConsoleWidget accepted non-ASCII characters on paste (and also rich text in 'rich' mode)...
r2762 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
Cleaned up frontend-level kernel restart logic.
r3033 """ Clear the console.
Parameters:
-----------
keep_input : bool, optional (default True)
If set, restores the old input buffer if a new prompt is written.
epatters
* Added 'started_listening' and 'stopped_listening' signals to QtKernelManager. The FrontendWidget listens for these signals....
r2643 """
epatters
Cleaned up frontend-level kernel restart logic.
r3033 if self._executing:
self._control.clear()
else:
if keep_input:
input_buffer = self.input_buffer
self._control.clear()
self._show_prompt()
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):
epatters
* Added "smart copy" support to FrontendWidget and ConsoleWidget. Tabs are expanded and prompts are stripped....
r2971 """ Copy the currently 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
* Added Cut support to ConsoleWidget....
r2990 def cut(self):
""" Copy the currently selected text to the clipboard and delete it
if it's inside the input buffer.
"""
self.copy()
if self.can_cut():
self._control.textCursor().removeSelectedText()
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')
Evan Patterson
Handle setting input buffer during execution in Qt console.
r3931 self._input_buffer_executing = self.input_buffer
epatters
* Fixed regression from last commit: syntax highlighting works robustly again....
r2866 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
Form feeds are now properly supported by ConsoleWidget.
r3006 # Perform actual execution.
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)
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
Fixed scrolling bugs when using rich text mode. (Work around probable bug in Qt.)
r2914 # Do not do this inside the edit block. It works as expected
# when using a QPlainTextEdit control, but does not have an
# effect when using a QTextEdit. I believe this is a Qt bug.
self._control.moveCursor(QtGui.QTextCursor.End)
epatters
* Refactored ConsoleWidget execution API for greater flexibility and clarity....
r2688 return complete
epatters
Initial checkin of Qt frontend code.
r2602
epatters
Added an 'export_html' method back to the public interface of ConsoleWidget.
r3365 def export_html(self):
""" Shows a dialog to export HTML/XML in various formats.
"""
self._html_exporter.export()
epatters
Fix ConsoleWidget unsetting execution flag when using raw_input.
r4061 def _get_input_buffer(self, force=False):
epatters
* Added API for setting the font of a ConsoleWidget....
r2665 """ The text that the user has entered entered at the current prompt.
Evan Patterson
Handle setting input buffer during execution in Qt console.
r3931
If the console is currently executing, the text that is executing will
always be returned.
epatters
* Added API for setting the font of a ConsoleWidget....
r2665 """
# 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.
epatters
Fix ConsoleWidget unsetting execution flag when using raw_input.
r4061 if self._executing and not force:
Evan Patterson
Handle setting input buffer during execution in Qt console.
r3931 return self._input_buffer_executing
epatters
* Added undo/redo support to ConsoleWidget...
r2615
epatters
Initial checkin of Qt frontend code.
r2602 cursor = self._get_end_cursor()
cursor.setPosition(self._prompt_pos, QtGui.QTextCursor.KeepAnchor)
Evan Patterson
Paved the way for PySide support....
r3304 input_buffer = cursor.selection().toPlainText()
epatters
Initial checkin of Qt frontend code.
r2602
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):
Evan Patterson
Handle setting input buffer during execution in Qt console.
r3931 """ Sets the text in the input buffer.
If the console is currently executing, this call has no *immediate*
effect. When the execution is finished, the input buffer will be updated
appropriately.
epatters
* Added API for setting the font of a ConsoleWidget....
r2665 """
Evan Patterson
Handle setting input buffer during execution in Qt console.
r3931 # If we're executing, store the text for later.
epatters
Numerous fixes to ConsoleWidget editing region maintenence code. It now impossible (or at least very difficult :) to break the input region.
r2764 if self._executing:
Evan Patterson
Handle setting input buffer during execution in Qt console.
r3931 self._input_buffer_pending = string
return
epatters
Numerous fixes to ConsoleWidget editing region maintenence code. It now impossible (or at least very difficult :) to break the input region.
r2764
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.
epatters
Fixed bug reported by fperez and removed code with duplicated functionality.
r3048 self._insert_plain_text_into_buffer(self._get_prompt_cursor(), string)
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
epatters
Fixed font changes not being propagated to CallTipWidget.
r3031 self.font_changed.emit(font)
epatters
* Added API for setting the font of a ConsoleWidget....
r2665 font = property(_get_font, _set_font)
epatters
Made middle-click paste safe. Fixes bug reported by fperez.
r2937 def paste(self, mode=QtGui.QClipboard.Clipboard):
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 """ Paste the contents of the clipboard into the input region.
epatters
Made middle-click paste safe. Fixes bug reported by fperez.
r2937
Parameters:
-----------
mode : QClipboard::Mode, optional [default QClipboard::Clipboard]
Controls which part of the system clipboard is used. This can be
used to access the selection clipboard in X11 and the Find buffer
in Mac OS. By default, the regular clipboard is used.
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
* Implemented "smart paste" for ConsoleWidget. Continuation prompts are now inserted automatically on paste....
r2763 if self._control.textInteractionFlags() & QtCore.Qt.TextEditable:
epatters
Fixed bug reported by fperez and removed code with duplicated functionality.
r3048 # Make sure the paste is safe.
self._keep_cursor_in_buffer()
cursor = self._control.textCursor()
epatters
First pass at unicode support in ConsoleWidget....
r3029 # Remove any trailing newline, which confuses the GUI and forces the
# user to backspace.
Evan Patterson
Paved the way for PySide support....
r3304 text = QtGui.QApplication.clipboard().text(mode).rstrip()
epatters
Fixed bug reported by fperez and removed code with duplicated functionality.
r3048 self._insert_plain_text_into_buffer(cursor, 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
Mark Voorhies
Add printing support....
r3091 def print_(self, printer = 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 """ Print the contents of the ConsoleWidget to the specified QPrinter.
"""
MinRK
HTML/XML export now single menu entry...
r3162 if (not printer):
Mark Voorhies
Add printing support....
r3091 printer = QtGui.QPrinter()
if(QtGui.QPrintDialog(printer).exec_() != QtGui.QDialog.Accepted):
return
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.print_(printer)
epatters
ConsoleWidget now manually controls the vertical scrollbar....
r3001 def prompt_to_top(self):
""" Moves the prompt to the top of the viewport.
"""
if not self._executing:
epatters
Fixed more issues with ConsoleWidget scrollbar management.
r3017 prompt_cursor = self._get_prompt_cursor()
if self._get_cursor().blockNumber() < prompt_cursor.blockNumber():
self._set_cursor(prompt_cursor)
self._set_top_cursor(prompt_cursor)
epatters
ConsoleWidget now manually controls the vertical scrollbar....
r3001
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 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.
"""
if sys.platform == 'win32':
Fernando Perez
Centralize Qt font selection into a generic utility....
r2986 # Consolas ships with Vista/Win7, fallback to Courier if needed
MinRK
qt font family/size configurable
r3972 fallback = 'Courier'
epatters
* Added API for setting the font of a ConsoleWidget....
r2665 elif sys.platform == 'darwin':
MinRK
qt font family/size configurable
r3972 # OSX always has Monaco
fallback = 'Monaco'
epatters
* Added API for setting the font of a ConsoleWidget....
r2665 else:
MinRK
use Monospace as default font on Linux
r3975 # Monospace should always exist
MinRK
qt font family/size configurable
r3972 fallback = 'Monospace'
font = get_font(self.font_family, fallback)
if self.font_size:
font.setPointSize(self.font_size)
else:
font.setPointSize(QtGui.qApp.font().pointSize())
epatters
* Added API for setting the font of a ConsoleWidget....
r2665 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
Fernando Perez
Add Ctrl-+/- to increase/decrease font size....
r3081 def change_font_size(self, delta):
"""Change the font size by the specified amount (in points).
"""
font = self.font
Martin Spacek
don't set point size less than 1 in ConsoleWidget - this was raising Qt errors...
r3922 size = max(font.pointSize() + delta, 1) # minimum 1 point
font.setPointSize(size)
Fernando Perez
Add Ctrl-+/- to increase/decrease font size....
r3081 self._set_font(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 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
epatters
Add 'history_lock' setting to Qt console....
r3728 def _up_pressed(self, shift_modifier):
epatters
Initial checkin of Qt frontend code.
r2602 """ Called when the up key is pressed. Returns whether to continue
processing the event.
"""
return True
epatters
Add 'history_lock' setting to Qt console....
r3728 def _down_pressed(self, shift_modifier):
epatters
Initial checkin of Qt frontend code.
r2602 """ 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
First cut at safe appending in the Qt console.
r4056 def _append_custom(self, insert, input, before_prompt=False):
""" A low-level method for appending content to the end of the buffer.
If 'before_prompt' is enabled, the content will be inserted before the
current prompt, if there is one.
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
First cut at safe appending in the Qt console.
r4056 # Determine where to insert the content.
cursor = self._control.textCursor()
if before_prompt and not self._executing:
epatters
Improve Qt console's placement of text appended before a prompt.
r4058 cursor.setPosition(self._append_before_prompt_pos)
epatters
First cut at safe appending in the Qt console.
r4056 else:
cursor.movePosition(QtGui.QTextCursor.End)
start_pos = cursor.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
First cut at safe appending in the Qt console.
r4056 # Perform the insertion.
result = insert(cursor, input)
# Adjust the prompt position if we have inserted before it. This is safe
# because buffer truncation is disabled when not executing.
if before_prompt and not self._executing:
epatters
Improve Qt console's placement of text appended before a prompt.
r4058 diff = cursor.position() - start_pos
self._append_before_prompt_pos += diff
self._prompt_pos += diff
epatters
First cut at safe appending in the Qt console.
r4056
return result
epatters
* IPythonWidget now has IPython-style prompts that are futher stylabla via CSS...
r2715
epatters
First cut at safe appending in the Qt console.
r4056 def _append_html(self, html, before_prompt=False):
""" Appends HTML at the end of the console 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 """
epatters
First cut at safe appending in the Qt console.
r4056 self._append_custom(self._insert_html, html, before_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
epatters
First cut at safe appending in the Qt console.
r4056 def _append_html_fetching_plain_text(self, html, before_prompt=False):
""" Appends HTML, then returns the plain text version of it.
epatters
* IPythonWidget now has IPython-style prompts that are futher stylabla via CSS...
r2715 """
epatters
First cut at safe appending in the Qt console.
r4056 return self._append_custom(self._insert_html_fetching_plain_text,
html, before_prompt)
epatters
* IPythonWidget now has IPython-style prompts that are futher stylabla via CSS...
r2715
epatters
First cut at safe appending in the Qt console.
r4056 def _append_plain_text(self, text, before_prompt=False):
""" Appends plain text, processing ANSI codes if enabled.
"""
self._append_custom(self._insert_plain_text, text, before_prompt)
epatters
* IPythonWidget now has IPython-style prompts that are futher stylabla via CSS...
r2715
epatters
Fixed numerous bugs with tab completion, including the one recently reported by fperez.
r2939 def _cancel_text_completion(self):
""" If text completion is progress, cancel it.
"""
if self._text_completing_pos:
self._clear_temporary_buffer()
self._text_completing_pos = 0
epatters
Major improvements to terminal-style tab completion. Still work to be done, but a decent start.
r2919 def _clear_temporary_buffer(self):
""" Clears the "temporary text" buffer, i.e. all the text following
the prompt region.
"""
epatters
Fixed numerous bugs with tab completion, including the one recently reported by fperez.
r2939 # Select and remove all text below the input buffer.
epatters
Major improvements to terminal-style tab completion. Still work to be done, but a decent start.
r2919 cursor = self._get_prompt_cursor()
epatters
Fixed numerous bugs with tab completion, including the one recently reported by fperez.
r2939 prompt = self._continuation_prompt.lstrip()
while cursor.movePosition(QtGui.QTextCursor.NextBlock):
temp_cursor = QtGui.QTextCursor(cursor)
temp_cursor.select(QtGui.QTextCursor.BlockUnderCursor)
Evan Patterson
Paved the way for PySide support....
r3304 text = temp_cursor.selection().toPlainText().lstrip()
epatters
Fixed numerous bugs with tab completion, including the one recently reported by fperez.
r2939 if not text.startswith(prompt):
break
else:
# We've reached the end of the input buffer and no text follows.
return
cursor.movePosition(QtGui.QTextCursor.Left) # Grab the newline.
cursor.movePosition(QtGui.QTextCursor.End,
QtGui.QTextCursor.KeepAnchor)
cursor.removeSelectedText()
# After doing this, we have no choice but to clear the undo/redo
# history. Otherwise, the text is not "temporary" at all, because it
# can be recalled with undo/redo. Unfortunately, Qt does not expose
# fine-grained control to the undo/redo system.
if self._control.isUndoRedoEnabled():
self._control.setUndoRedoEnabled(False)
self._control.setUndoRedoEnabled(True)
epatters
Major improvements to terminal-style tab completion. Still work to be done, but a decent start.
r2919
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.
"""
epatters
Fixed numerous bugs with tab completion, including the one recently reported by fperez.
r2939 self._cancel_text_completion()
epatters
Major improvements to terminal-style tab completion. Still work to be done, but a decent start.
r2919
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 len(items) == 1:
cursor.setPosition(self._control.textCursor().position(),
QtGui.QTextCursor.KeepAnchor)
cursor.insertText(items[0])
epatters
Major improvements to terminal-style tab completion. Still work to be done, but a decent start.
r2919
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 len(items) > 1:
epatters
Major improvements to terminal-style tab completion. Still work to be done, but a decent start.
r2919 current_pos = self._control.textCursor().position()
prefix = commonprefix(items)
if prefix:
cursor.setPosition(current_pos, QtGui.QTextCursor.KeepAnchor)
cursor.insertText(prefix)
current_pos = cursor.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 self.gui_completion:
epatters
Major improvements to terminal-style tab completion. Still work to be done, but a decent start.
r2919 cursor.movePosition(QtGui.QTextCursor.Left, n=len(prefix))
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.show_items(cursor, items)
else:
epatters
Major improvements to terminal-style tab completion. Still work to be done, but a decent start.
r2919 cursor.beginEditBlock()
self._append_plain_text('\n')
epatters
Changed the default completion style to text. Text completion now uses the pager.
r2917 self._page(self._format_as_columns(items))
epatters
Major improvements to terminal-style tab completion. Still work to be done, but a decent start.
r2919 cursor.endEditBlock()
cursor.setPosition(current_pos)
self._control.moveCursor(QtGui.QTextCursor.End)
self._control.setTextCursor(cursor)
self._text_completing_pos = current_pos
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 Cut support to ConsoleWidget....
r2990 def _context_menu_make(self, pos):
""" Creates a context menu for the given QPoint (in widget coordinates).
"""
MinRK
HTML/XML export now single menu entry...
r3162 menu = QtGui.QMenu(self)
epatters
* Added Cut support to ConsoleWidget....
r2990
cut_action = menu.addAction('Cut', self.cut)
cut_action.setEnabled(self.can_cut())
cut_action.setShortcut(QtGui.QKeySequence.Cut)
copy_action = menu.addAction('Copy', self.copy)
copy_action.setEnabled(self.can_copy())
copy_action.setShortcut(QtGui.QKeySequence.Copy)
paste_action = menu.addAction('Paste', self.paste)
paste_action.setEnabled(self.can_paste())
paste_action.setShortcut(QtGui.QKeySequence.Paste)
menu.addSeparator()
MinRK
HTML/XML export now single menu entry...
r3162 menu.addAction(self._select_all_action)
menu.addSeparator()
menu.addAction(self._export_action)
menu.addAction(self._print_action)
epatters
* Added Cut support to ConsoleWidget....
r2990 return menu
MinRK
command should not be aliased to control by default
r3163 def _control_key_down(self, modifiers, include_command=False):
epatters
Fixed wonky ConsoleWidget keyboard shortcuts on Mac OS.
r2671 """ Given a KeyboardModifiers flags object, return whether the Control
epatters
Cmd-C will no longer interrupt the kernel in Mac OS (only Ctrl-C will do this).
r2941 key is down.
epatters
Fixed wonky ConsoleWidget keyboard shortcuts on Mac OS.
r2671
epatters
Cmd-C will no longer interrupt the kernel in Mac OS (only Ctrl-C will do this).
r2941 Parameters:
-----------
include_command : bool, optional (default True)
Whether to treat the Command key as a (mutually exclusive) synonym
for Control when in Mac OS.
"""
# Note that on Mac OS, ControlModifier corresponds to the Command key
# while MetaModifier corresponds to the Control key.
epatters
Fixed wonky ConsoleWidget keyboard shortcuts on Mac OS.
r2671 if sys.platform == 'darwin':
epatters
Cmd-C will no longer interrupt the kernel in Mac OS (only Ctrl-C will do this).
r2941 down = include_command and (modifiers & QtCore.Qt.ControlModifier)
return bool(down) ^ bool(modifiers & QtCore.Qt.MetaModifier)
else:
return bool(modifiers & QtCore.Qt.ControlModifier)
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 middle-click paste safe. Fixes bug reported by fperez.
r2937 # Create the underlying control.
epatters
Made IPythonWidget and its subclasses Configurable.
r2884 if self.kind == 'plain':
epatters
* Added "smart copy" support to FrontendWidget and ConsoleWidget. Tabs are expanded and prompts are stripped....
r2971 control = QtGui.QPlainTextEdit()
epatters
Made IPythonWidget and its subclasses Configurable.
r2884 elif self.kind == 'rich':
epatters
* Added "smart copy" support to FrontendWidget and ConsoleWidget. Tabs are expanded and prompts are stripped....
r2971 control = QtGui.QTextEdit()
epatters
* Fixed bug where ConsoleWidget accepted non-ASCII characters on paste (and also rich text in 'rich' mode)...
r2762 control.setAcceptRichText(False)
epatters
Made middle-click paste safe. Fixes bug reported by fperez.
r2937
# Install event filters. The filter on the viewport is needed for
epatters
* Added "smart copy" support to FrontendWidget and ConsoleWidget. Tabs are expanded and prompts are stripped....
r2971 # mouse events and drag events.
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
Made middle-click paste safe. Fixes bug reported by fperez.
r2937 control.viewport().installEventFilter(self)
# Connect signals.
epatters
Major improvements to terminal-style tab completion. Still work to be done, but a decent start.
r2919 control.cursorPositionChanged.connect(self._cursor_position_changed)
epatters
ConsoleWidget now manually controls the vertical scrollbar....
r3001 control.customContextMenuRequested.connect(
self._custom_context_menu_requested)
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
Made middle-click paste safe. Fixes bug reported by fperez.
r2937
epatters
ConsoleWidget now manually controls the vertical scrollbar....
r3001 # Hijack the document size change signal to prevent Qt from adjusting
# the viewport's scrollbar. We are relying on an implementation detail
# of Q(Plain)TextEdit here, which is potentially dangerous, but without
# this functionality we cannot create a nice terminal interface.
layout = control.document().documentLayout()
layout.documentSizeChanged.disconnect()
layout.documentSizeChanged.connect(self._adjust_scrollbars)
epatters
Made middle-click paste safe. Fixes bug reported by fperez.
r2937 # Configure the control.
epatters
Work around Qt bug where input method is disabled sometimes in QPlainTextEdit....
r3765 control.setAttribute(QtCore.Qt.WA_InputMethodEnabled, True)
epatters
Made middle-click paste safe. Fixes bug reported by fperez.
r2937 control.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
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
Added support for HTML paging and HTML page payloads.
r3014 if self.kind == 'plain':
control = QtGui.QPlainTextEdit()
elif self.kind == 'rich':
control = QtGui.QTextEdit()
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
epatters
Added support for Ctrl-Enter (unconditionally enter a newline) to ConsoleWidget....
r2985 #------ Special sequences ----------------------------------------------
epatters
* Added "smart copy" support to FrontendWidget and ConsoleWidget. Tabs are expanded and prompts are stripped....
r2971 if event.matches(QtGui.QKeySequence.Copy):
self.copy()
intercepted = True
epatters
* Added Cut support to ConsoleWidget....
r2990 elif event.matches(QtGui.QKeySequence.Cut):
self.cut()
intercepted = True
epatters
* Added "smart copy" support to FrontendWidget and ConsoleWidget. Tabs are expanded and prompts are stripped....
r2971 elif event.matches(QtGui.QKeySequence.Paste):
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
epatters
Added support for Ctrl-Enter (unconditionally enter a newline) to ConsoleWidget....
r2985 #------ Special modifier logic -----------------------------------------
elif key in (QtCore.Qt.Key_Return, QtCore.Qt.Key_Enter):
intercepted = True
# Special handling when tab completing in text mode.
self._cancel_text_completion()
if self._in_buffer(position):
if self._reading:
self._append_plain_text('\n')
self._reading = False
if self._reading_callback:
self._reading_callback()
epatters
Pressing Enter now always executes when the input buffer has one line.
r3021 # If the input buffer is a single line or there is only
# whitespace after the cursor, execute. Otherwise, split the
# line with a continuation prompt.
epatters
Added support for Ctrl-Enter (unconditionally enter a newline) to ConsoleWidget....
r2985 elif not self._executing:
cursor.movePosition(QtGui.QTextCursor.End,
QtGui.QTextCursor.KeepAnchor)
Evan Patterson
Paved the way for PySide support....
r3304 at_end = len(cursor.selectedText().strip()) == 0
epatters
Pressing Enter now always executes when the input buffer has one line.
r3021 single_line = (self._get_end_cursor().blockNumber() ==
self._get_prompt_cursor().blockNumber())
if (at_end or shift_down or single_line) and not ctrl_down:
epatters
Added support for Ctrl-Enter (unconditionally enter a newline) to ConsoleWidget....
r2985 self.execute(interactive = not shift_down)
else:
# Do this inside an edit block for clean undo/redo.
cursor.beginEditBlock()
cursor.setPosition(position)
cursor.insertText('\n')
self._insert_continuation_prompt(cursor)
cursor.endEditBlock()
# 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)
#------ Control/Cmd modifier -------------------------------------------
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 ctrl_down:
epatters
* Ctrl-G and Escape now clear the input buffer....
r2924 if key == QtCore.Qt.Key_G:
self._keyboard_quit()
intercepted = True
elif 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
Add Emacs-style kill ring to Qt console....
r3767 self._kill_ring.kill_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
* Added support for Ctrl-L per Fernando's request....
r2880 elif key == QtCore.Qt.Key_L:
epatters
ConsoleWidget now manually controls the vertical scrollbar....
r3001 self.prompt_to_top()
epatters
* Added support for Ctrl-L per Fernando's request....
r2880 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()
Fernando Perez
Add Ctrl-+/- to increase/decrease font size....
r3081 intercepted = True
epatters
Numerous usability enhancements to the Qt console widget, particularly with regard to key bindings.
r2897
epatters
Added Ctrl+H and Ctrl+U shortcuts to Qt console....
r3468 elif key == QtCore.Qt.Key_U:
if self._in_buffer(position):
start_line = cursor.blockNumber()
if start_line == self._get_prompt_cursor().blockNumber():
offset = len(self._prompt)
else:
offset = len(self._continuation_prompt)
cursor.movePosition(QtGui.QTextCursor.StartOfBlock,
QtGui.QTextCursor.KeepAnchor)
cursor.movePosition(QtGui.QTextCursor.Right,
QtGui.QTextCursor.KeepAnchor, offset)
epatters
Add Emacs-style kill ring to Qt console....
r3767 self._kill_ring.kill_cursor(cursor)
epatters
Added Ctrl+H and Ctrl+U shortcuts to Qt console....
r3468 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 elif key == QtCore.Qt.Key_Y:
epatters
Add Emacs-style kill ring to Qt console....
r3767 self._keep_cursor_in_buffer()
self._kill_ring.yank()
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
Fixed bugs reported by minrk involving deletion of the input prompt.
r2936 elif key in (QtCore.Qt.Key_Backspace, QtCore.Qt.Key_Delete):
Martin Spacek
add Ctrl+Backspace and Ctrl+Del keybindings to delete to start and end of current word
r4156 if key == QtCore.Qt.Key_Backspace:
cursor = self._get_word_start_cursor(position)
else: # key == QtCore.Qt.Key_Delete
cursor = self._get_word_end_cursor(position)
cursor.setPosition(position, QtGui.QTextCursor.KeepAnchor)
self._kill_ring.kill_cursor(cursor)
epatters
Fixed bugs reported by minrk involving deletion of the input prompt.
r2936 intercepted = True
Martin Spacek
add Ctrl+= to keybinding to increase font size in qt widget
r3924 elif key in (QtCore.Qt.Key_Plus, QtCore.Qt.Key_Equal):
Fernando Perez
Add Ctrl-+/- to increase/decrease font size....
r3081 self.change_font_size(1)
intercepted = True
elif key == QtCore.Qt.Key_Minus:
self.change_font_size(-1)
intercepted = True
Martin Spacek
make Ctrl+0 reset font size in qt widget
r3923 elif key == QtCore.Qt.Key_0:
self.reset_font()
intercepted = True
epatters
Added support for Ctrl-Enter (unconditionally enter a newline) to ConsoleWidget....
r2985 #------ Alt modifier ---------------------------------------------------
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 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
epatters
Add Emacs-style kill ring to Qt console....
r3767 elif key == QtCore.Qt.Key_Y:
self._kill_ring.rotate()
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 elif key == QtCore.Qt.Key_Backspace:
cursor = self._get_word_start_cursor(position)
cursor.setPosition(position, QtGui.QTextCursor.KeepAnchor)
epatters
Add Emacs-style kill ring to Qt console....
r3767 self._kill_ring.kill_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
elif key == QtCore.Qt.Key_D:
cursor = self._get_word_end_cursor(position)
cursor.setPosition(position, QtGui.QTextCursor.KeepAnchor)
epatters
Add Emacs-style kill ring to Qt console....
r3767 self._kill_ring.kill_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
Fixed bugs reported by minrk involving deletion of the input prompt.
r2936 elif key == QtCore.Qt.Key_Delete:
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
Added support for Ctrl-Enter (unconditionally enter a newline) to ConsoleWidget....
r2985 #------ No modifiers ---------------------------------------------------
epatters
* Ctrl-G and Escape now clear the input buffer....
r2924
epatters
Added support for Ctrl-Enter (unconditionally enter a newline) to ConsoleWidget....
r2985 else:
MinRK
fixed some cursor selection behavior
r3082 if shift_down:
epatters
Added Ctrl+H and Ctrl+U shortcuts to Qt console....
r3468 anchormode = QtGui.QTextCursor.KeepAnchor
MinRK
fixed some cursor selection behavior
r3082 else:
epatters
Added Ctrl+H and Ctrl+U shortcuts to Qt console....
r3468 anchormode = QtGui.QTextCursor.MoveAnchor
MinRK
fixed some cursor selection behavior
r3082
epatters
Added support for Ctrl-Enter (unconditionally enter a newline) to ConsoleWidget....
r2985 if key == QtCore.Qt.Key_Escape:
epatters
* Ctrl-G and Escape now clear the input buffer....
r2924 self._keyboard_quit()
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 elif key == QtCore.Qt.Key_Up:
epatters
Add 'history_lock' setting to Qt console....
r3728 if self._reading or not self._up_pressed(shift_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 intercepted = True
else:
prompt_line = self._get_prompt_cursor().blockNumber()
intercepted = cursor.blockNumber() <= prompt_line
elif key == QtCore.Qt.Key_Down:
epatters
Add 'history_lock' setting to Qt console....
r3728 if self._reading or not self._down_pressed(shift_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 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:
epatters
The Left and Right arrow keys now traverse the input buffer as expected.
r3016
# Move to the previous line
line, col = cursor.blockNumber(), cursor.columnNumber()
if line > self._get_prompt_cursor().blockNumber() and \
col == len(self._continuation_prompt):
MinRK
fixed some cursor selection behavior
r3082 self._control.moveCursor(QtGui.QTextCursor.PreviousBlock,
epatters
Added Ctrl+H and Ctrl+U shortcuts to Qt console....
r3468 mode=anchormode)
MinRK
fixed some cursor selection behavior
r3082 self._control.moveCursor(QtGui.QTextCursor.EndOfBlock,
epatters
Added Ctrl+H and Ctrl+U shortcuts to Qt console....
r3468 mode=anchormode)
epatters
The Left and Right arrow keys now traverse the input buffer as expected.
r3016 intercepted = True
# Regular left movement
else:
intercepted = not self._in_buffer(position - 1)
elif key == QtCore.Qt.Key_Right:
original_block_number = cursor.blockNumber()
MinRK
fixed some cursor selection behavior
r3082 cursor.movePosition(QtGui.QTextCursor.Right,
mode=anchormode)
epatters
The Left and Right arrow keys now traverse the input buffer as expected.
r3016 if cursor.blockNumber() != original_block_number:
cursor.movePosition(QtGui.QTextCursor.Right,
MinRK
fixed some cursor selection behavior
r3082 n=len(self._continuation_prompt),
mode=anchormode)
epatters
The Left and Right arrow keys now traverse the input buffer as expected.
r3016 self._set_cursor(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
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)
epatters
Fixed bugs reported by minrk involving deletion of the input prompt.
r2936 line, col = cursor.blockNumber(), cursor.columnNumber()
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 not self._reading and \
epatters
Fixed bugs reported by minrk involving deletion of the input prompt.
r2936 col == len(self._continuation_prompt) and \
line > self._get_prompt_cursor().blockNumber():
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)
epatters
Fixed bugs reported by minrk involving deletion of the input prompt.
r2936 if not self._reading and self._in_buffer(position) and \
cursor.atBlockEnd() and not cursor.hasSelection():
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.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 bug where Cmd-C would clear the selection on Mac OS.
r3308 # Don't move the cursor if Control/Cmd is pressed to allow copy-paste
# using the keyboard in any part of the buffer.
if not self._control_key_down(event.modifiers(), include_command=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 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
Font width calculation fix for certain Mac OS systems.
r2935 char_width = QtGui.QFontMetrics(self.font).width(' ')
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:
epatters
First pass at unicode support in ConsoleWidget....
r3029 return '%s\n' % items[0]
epatters
Replaced external module for formatting columns with adapted code.
r2724
# 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
First pass at unicode support in ConsoleWidget....
r3029 string += '%s\n' % 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)
Evan Patterson
Paved the way for PySide support....
r3304 return 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
Removed use of hard tabs in FrontendWidget and implemented "smart" backspace.
r3022 """ Returns the text of the line of the input buffer that contains the
cursor, or None if there is no such line.
epatters
* Tab completion now uses the correct cursor position....
r2841 """
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 \
Evan Patterson
Paved the way for PySide support....
r3304 not is_letter_or_number(document.characterAt(position)):
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 \
Evan Patterson
Paved the way for PySide support....
r3304 is_letter_or_number(document.characterAt(position)):
epatters
Initial checkin of Qt frontend code.
r2602 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 \
Evan Patterson
Paved the way for PySide support....
r3304 not is_letter_or_number(document.characterAt(position)):
epatters
Initial checkin of Qt frontend code.
r2602 position += 1
while position < end and \
Evan Patterson
Paved the way for PySide support....
r3304 is_letter_or_number(document.characterAt(position)):
epatters
Initial checkin of Qt frontend code.
r2602 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)
Evan Patterson
Paved the way for PySide support....
r3304 text = 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 scroll sequences and form feeds to AnsiCodeProcessor....
r2998 for act in self._ansi_processor.actions:
epatters
Form feeds are now properly supported by ConsoleWidget.
r3006
# Unlike real terminal emulators, we don't distinguish
# between the screen and the scrollback buffer. A screen
# erase request clears everything.
if act.action == 'erase' and act.area == 'screen':
epatters
Added support for ANSI erase codes. Clearing the console via ANSI escape sequences is now supported.
r2783 cursor.select(QtGui.QTextCursor.Document)
cursor.removeSelectedText()
epatters
Form feeds are now properly supported by ConsoleWidget.
r3006
# Simulate a form feed by scrolling just past the last line.
elif act.action == 'scroll' and act.unit == 'page':
cursor.insertText('\n')
cursor.endEditBlock()
self._set_top_cursor(cursor)
cursor.joinPreviousEditBlock()
cursor.deletePreviousChar()
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 reported by fperez and removed code with duplicated functionality.
r3048 def _insert_plain_text_into_buffer(self, cursor, text):
""" Inserts text into the input buffer using the specified cursor (which
must be in the input buffer), ensuring that continuation prompts are
inserted as necessary.
epatters
* Implemented "smart paste" for ConsoleWidget. Continuation prompts are now inserted automatically on paste....
r2763 """
Evan Patterson
Paved the way for PySide support....
r3304 lines = text.splitlines(True)
epatters
* Implemented "smart paste" for ConsoleWidget. Continuation prompts are now inserted automatically on paste....
r2763 if lines:
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()
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
* Ctrl-G and Escape now clear the input buffer....
r2924
def _keyboard_quit(self):
""" Cancels the current editing task ala Ctrl-G in Emacs.
"""
if self._text_completing_pos:
epatters
Fixed numerous bugs with tab completion, including the one recently reported by fperez.
r2939 self._cancel_text_completion()
epatters
* Ctrl-G and Escape now clear the input buffer....
r2924 else:
self.input_buffer = ''
epatters
* Added a pager with several different options to ConsoleWidget....
r2776
epatters
Added support for HTML paging and HTML page payloads.
r3014 def _page(self, text, html=False):
epatters
Fixed more issues with ConsoleWidget scrollbar management.
r3017 """ Displays text using the pager if it exceeds the height of the
viewport.
epatters
Added support for HTML paging and HTML page payloads.
r3014
Parameters:
-----------
html : bool, optional (default False)
If set, the text will be interpreted as HTML instead of plain text.
"""
line_height = QtGui.QFontMetrics(self.font).height()
minlines = self._control.viewport().height() / line_height
epatters
Fixed more issues with ConsoleWidget scrollbar management.
r3017 if self.paging != 'none' and \
re.match("(?:[^\n]*\n){%i}" % minlines, text):
epatters
Added support for HTML paging and HTML page payloads.
r3014 if self.paging == 'custom':
self.custom_page_requested.emit(text)
else:
self._page_control.clear()
cursor = self._page_control.textCursor()
if html:
self._insert_html(cursor, text)
epatters
The ConsoleWidget now only pages text if it exceeds the height of the visible window.
r2843 else:
self._insert_plain_text(cursor, text)
epatters
Added support for HTML paging and HTML page payloads.
r3014 self._page_control.moveCursor(QtGui.QTextCursor.Start)
epatters
The ConsoleWidget now only pages text if it exceeds the height of the visible window.
r2843
epatters
Added support for HTML paging and HTML page payloads.
r3014 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)
elif html:
self._append_plain_html(text)
else:
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
ConsoleWidget now manually controls the vertical scrollbar....
r3001 def _prompt_finished(self):
""" Called immediately after a prompt is finished, i.e. when some input
will be processed and a new prompt displayed.
"""
self._control.setReadOnly(True)
self._prompt_finished_hook()
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
Form feeds are now properly supported by ConsoleWidget.
r3006 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
Work around Qt bug where input method is disabled sometimes in QPlainTextEdit....
r3765 # Work around bug in QPlainTextEdit: input method is not re-enabled
# when read-only is disabled.
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)
epatters
Work around Qt bug where input method is disabled sometimes in QPlainTextEdit....
r3765 self._control.setAttribute(QtCore.Qt.WA_InputMethodEnabled, True)
epatters
Fix ConsoleWidget unsetting execution flag when using raw_input.
r4061 if not self._reading:
self._executing = False
epatters
Initial checkin of Qt frontend code.
r2602 self._prompt_started_hook()
Evan Patterson
Handle setting input buffer during execution in Qt console.
r3931 # If the input buffer has changed while executing, load it.
if self._input_buffer_pending:
self.input_buffer = self._input_buffer_pending
self._input_buffer_pending = ''
self._control.moveCursor(QtGui.QTextCursor.End)
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()
epatters
Fix ConsoleWidget unsetting execution flag when using raw_input.
r4061 return self._get_input_buffer(force=True).rstrip('\n')
epatters
Reading a line is now correctly implemented in ConsoleWidget.
r2706
else:
self._reading_callback = lambda: \
epatters
Fix ConsoleWidget unsetting execution flag when using raw_input.
r4061 callback(self._get_input_buffer(force=True).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
Form feeds are now properly supported by ConsoleWidget.
r3006 def _set_top_cursor(self, cursor):
""" Scrolls the viewport so that the specified cursor is at the top.
"""
scrollbar = self._control.verticalScrollBar()
scrollbar.setValue(scrollbar.maximum())
original_cursor = self._control.textCursor()
self._control.setTextCursor(cursor)
self._control.ensureCursorVisible()
self._control.setTextCursor(original_cursor)
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
Improve Qt console's placement of text appended before a prompt.
r4058 # Save the current end position to support _append*(before_prompt=True).
cursor = self._get_end_cursor()
self._append_before_prompt_pos = cursor.position()
epatters
* IPythonWidget now has IPython-style prompts that are futher stylabla via CSS...
r2715 # Insert a preliminary newline, if necessary.
epatters
Improve Qt console's placement of text appended before a prompt.
r4058 if newline and cursor.position() > 0:
cursor.movePosition(QtGui.QTextCursor.Left,
QtGui.QTextCursor.KeepAnchor)
if cursor.selection().toPlainText() != '\n':
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()
epatters
Major improvements to terminal-style tab completion. Still work to be done, but a decent start.
r2919 #------ Signal handlers ----------------------------------------------------
epatters
ConsoleWidget now manually controls the vertical scrollbar....
r3001 def _adjust_scrollbars(self):
""" Expands the vertical scrollbar beyond the range set by Qt.
"""
# This code is adapted from _q_adjustScrollbars in qplaintextedit.cpp
# and qtextedit.cpp.
document = self._control.document()
scrollbar = self._control.verticalScrollBar()
viewport_height = self._control.viewport().height()
if isinstance(self._control, QtGui.QPlainTextEdit):
epatters
Fixed bug with scrollbar adjustment when buffer size exceeds maximumBlockCount.
r3007 maximum = max(0, document.lineCount() - 1)
epatters
ConsoleWidget now manually controls the vertical scrollbar....
r3001 step = viewport_height / self._control.fontMetrics().lineSpacing()
else:
epatters
Fixed bug with scrollbar adjustment when buffer size exceeds maximumBlockCount.
r3007 # QTextEdit does not do line-based layout and blocks will not in
# general have the same height. Therefore it does not make sense to
# attempt to scroll in line height increments.
maximum = document.size().height()
epatters
ConsoleWidget now manually controls the vertical scrollbar....
r3001 step = viewport_height
epatters
Fixed bug with scrollbar adjustment when buffer size exceeds maximumBlockCount.
r3007 diff = maximum - scrollbar.maximum()
scrollbar.setRange(0, maximum)
epatters
ConsoleWidget now manually controls the vertical scrollbar....
r3001 scrollbar.setPageStep(step)
epatters
Refactored ConsoleWidget's HTML exportaton code + other minor code cleanup.
r3361
epatters
Fixed bug with scrollbar adjustment when buffer size exceeds maximumBlockCount.
r3007 # Compensate for undesirable scrolling that occurs automatically due to
# maximumBlockCount() text truncation.
epatters
Fixed more issues with ConsoleWidget scrollbar management.
r3017 if diff < 0 and document.blockCount() == document.maximumBlockCount():
epatters
Fixed bug with scrollbar adjustment when buffer size exceeds maximumBlockCount.
r3007 scrollbar.setValue(scrollbar.value() + diff)
epatters
ConsoleWidget now manually controls the vertical scrollbar....
r3001
epatters
Major improvements to terminal-style tab completion. Still work to be done, but a decent start.
r2919 def _cursor_position_changed(self):
""" Clears the temporary buffer based on the cursor position.
"""
if self._text_completing_pos:
document = self._control.document()
if self._text_completing_pos < document.characterCount():
cursor = self._control.textCursor()
pos = cursor.position()
text_cursor = self._control.textCursor()
text_cursor.setPosition(self._text_completing_pos)
if pos < self._text_completing_pos or \
cursor.blockNumber() > text_cursor.blockNumber():
self._clear_temporary_buffer()
self._text_completing_pos = 0
else:
self._clear_temporary_buffer()
self._text_completing_pos = 0
epatters
ConsoleWidget now manually controls the vertical scrollbar....
r3001
def _custom_context_menu_requested(self, pos):
""" Shows a context menu at the given QPoint (in widget coordinates).
"""
menu = self._context_menu_make(pos)
menu.exec_(self._control.mapToGlobal(pos))