Skip to content
Prev Previous commit
Next Next commit
Allow buffers to be read-only.
  • Loading branch information
jonathanslenders committed Aug 12, 2015
commit 45136a0541428e4e06dc1490e9e1be880ecdffd6
19 changes: 18 additions & 1 deletion prompt_toolkit/buffer.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,16 @@
import tempfile

__all__ = (
'EditReadOnlyBuffer',
'AcceptAction',
'Buffer',
'indent',
'unindent',
)

class EditReadOnlyBuffer(Exception):
" Attempt editing of read-only buffer. "


class AcceptAction(object):
"""
Expand Down Expand Up @@ -169,13 +173,14 @@ class Buffer(object):
def __init__(self, completer=None, history=None, validator=None, tempfile_suffix='',
is_multiline=Never(), complete_while_typing=Never(),
enable_history_search=Never(), initial_document=None,
accept_action=AcceptAction.RETURN_DOCUMENT,
accept_action=AcceptAction.RETURN_DOCUMENT, read_only=False,
on_text_changed=None, on_text_insert=None, on_cursor_position_changed=None):

# Accept both filters and booleans as input.
enable_history_search = to_simple_filter(enable_history_search)
is_multiline = to_simple_filter(is_multiline)
complete_while_typing = to_simple_filter(complete_while_typing)
read_only = to_simple_filter(read_only)

# Validate input.
assert completer is None or isinstance(completer, Completer)
Expand All @@ -193,6 +198,7 @@ def __init__(self, completer=None, history=None, validator=None, tempfile_suffix
self.is_multiline = is_multiline
self.complete_while_typing = complete_while_typing
self.enable_history_search = enable_history_search
self.read_only = read_only

#: The command buffer history.
# Note that we shouldn't use a lazy 'or' here. bool(history) could be
Expand Down Expand Up @@ -277,6 +283,10 @@ def text(self, value):
assert isinstance(value, six.text_type), 'Got %r' % value
assert self.cursor_position <= len(value)

# Don't allow editing of read-only buffers.
if self.read_only():
raise EditReadOnlyBuffer()

changed = self._set_text(value)

if changed:
Expand Down Expand Up @@ -350,6 +360,10 @@ def document(self, value):
"""
assert isinstance(value, Document)

# Don't allow editing of read-only buffers.
if self.read_only():
raise EditReadOnlyBuffer()

# Set text and cursor position first.
text_changed = self._set_text(value.text)
cursor_position_changed = self._set_cursor_position(value.cursor_position)
Expand Down Expand Up @@ -1001,6 +1015,9 @@ def open_in_editor(self):
"""
Open code in editor.
"""
if self.read_only():
raise EditReadOnlyBuffer()

# Write to temporary file
descriptor, filename = tempfile.mkstemp(self.tempfile_suffix)
os.write(descriptor, self.text.encode('utf-8'))
Expand Down
15 changes: 11 additions & 4 deletions prompt_toolkit/key_binding/input_processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from __future__ import unicode_literals
from ..keys import Keys
from ..utils import Callback
from prompt_toolkit.buffer import EditReadOnlyBuffer

import weakref

Expand Down Expand Up @@ -171,10 +172,16 @@ def _call_handler(self, handler, key_sequence=None):
arg = self.arg
self.arg = None

event = Event(weakref.ref(self), arg=arg, key_sequence=key_sequence,
previous_key_sequence=self._previous_key_sequence)
handler.call(event)
self._registry.on_handler_called.fire(event)
try:
event = Event(weakref.ref(self), arg=arg, key_sequence=key_sequence,
previous_key_sequence=self._previous_key_sequence)
handler.call(event)
self._registry.on_handler_called.fire(event)

except EditReadOnlyBuffer:
# When a key binding does an attempt to change a buffer which is read-only,
# we can just silently ignore that.
pass

self._previous_key_sequence = key_sequence

Expand Down