[Python-modules-commits] [prompt-toolkit] 01/06: Import prompt-toolkit_1.0.0.orig.tar.gz
Scott Kitterman
kitterman at moszumanska.debian.org
Mon May 23 20:59:44 UTC 2016
This is an automated email from the git hooks/post-receive script.
kitterman pushed a commit to branch master
in repository prompt-toolkit.
commit 0db2578045eda5318a12fbb910c74d05cec02991
Author: Scott Kitterman <scott at kitterman.com>
Date: Mon May 23 16:34:41 2016 -0400
Import prompt-toolkit_1.0.0.orig.tar.gz
---
CHANGELOG | 93 +-
PKG-INFO | 8 +-
README.rst | 6 +-
examples/clock-input.py | 7 +-
examples/full-screen-layout.py | 8 +-
examples/switch-between-vi-emacs.py | 15 +-
prompt_toolkit.egg-info/PKG-INFO | 8 +-
prompt_toolkit.egg-info/SOURCES.txt | 3 +
prompt_toolkit/__init__.py | 2 +-
prompt_toolkit/application.py | 60 +-
prompt_toolkit/buffer.py | 96 +-
.../contrib/regular_languages/compiler.py | 1 +
prompt_toolkit/document.py | 218 +++-
prompt_toolkit/enums.py | 6 +
prompt_toolkit/eventloop/asyncio_posix.py | 4 +
prompt_toolkit/eventloop/posix.py | 4 +
prompt_toolkit/eventloop/posix_utils.py | 44 +-
prompt_toolkit/filters/cli.py | 118 ++
prompt_toolkit/filters/types.py | 39 +-
prompt_toolkit/input.py | 13 +-
prompt_toolkit/interface.py | 53 +-
prompt_toolkit/key_binding/bindings/basic.py | 85 +-
prompt_toolkit/key_binding/bindings/emacs.py | 105 +-
prompt_toolkit/key_binding/bindings/scroll.py | 1 +
prompt_toolkit/key_binding/bindings/vi.py | 986 ++++++++------
prompt_toolkit/key_binding/digraphs.py | 1378 ++++++++++++++++++++
prompt_toolkit/key_binding/input_processor.py | 48 +-
prompt_toolkit/key_binding/manager.py | 59 +-
prompt_toolkit/key_binding/registry.py | 3 -
prompt_toolkit/key_binding/vi_state.py | 28 +-
prompt_toolkit/keys.py | 1 +
prompt_toolkit/layout/containers.py | 159 ++-
prompt_toolkit/layout/controls.py | 9 +-
prompt_toolkit/layout/lexers.py | 12 +-
prompt_toolkit/layout/margins.py | 3 +-
prompt_toolkit/layout/menus.py | 27 +-
prompt_toolkit/layout/processors.py | 23 +-
prompt_toolkit/layout/toolbars.py | 10 +-
prompt_toolkit/mouse_events.py | 7 +-
prompt_toolkit/output.py | 41 +
prompt_toolkit/renderer.py | 2 +
prompt_toolkit/selection.py | 6 +-
prompt_toolkit/shortcuts.py | 25 +-
prompt_toolkit/styles/__init__.py | 1 +
prompt_toolkit/styles/defaults.py | 10 +-
prompt_toolkit/styles/from_dict.py | 7 +-
prompt_toolkit/styles/utils.py | 45 +
prompt_toolkit/terminal/vt100_input.py | 3 +
prompt_toolkit/terminal/vt100_output.py | 2 +-
prompt_toolkit/terminal/win32_input.py | 5 +-
prompt_toolkit/terminal/win32_output.py | 1 +
prompt_toolkit/utils.py | 105 +-
setup.cfg | 4 +-
tests/cli_tests.py | 183 +++
tests/run_tests.py | 1 +
55 files changed, 3400 insertions(+), 791 deletions(-)
diff --git a/CHANGELOG b/CHANGELOG
index ac06351..dcde93e 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,13 +1,92 @@
CHANGELOG
=========
-About the version numbering:
- As long as the version number starts with a zero, we allow backwards
- incompatible changes between each release. This is required order to move
- forward. However, we do our best to keep it to a minimum and ensure
- backwards-compatibility in the most used public APIs.
- When the library stabilizes, which is hopefully very soon, we will switch
- to a <breaking>.<feature>.<fix> style of numbering.
+1.0.0: 2016-05-05
+-----------------
+
+Fixes:
+- Adjust minimum completion menu width to match UIControl and Window class.
+- Bugfix regarding weakref in InputProcessor.
+- Fix for pypy3: bug in WeakValueDictionary.
+- Correctly handle '0' key binding in Vi mode.
+- Also load Vi bindings by default in Application if no registry has been given.
+- Only go into selection mode if the current buffer is not empty.
+- Close PipeInput after usage.
+- Only use 16 colors in (Emacs) eterm-color.
+- Bugfix in "xP Vi key binding.
+- Bugfix in Vi { and } key binding.
+- Fix: use correct token for Scrollbar in MultiColumnCompletionMenuControl.
+- Handle negative values in translate_row_col_to_index.
+- Handle decomposed unicode characters.
+- Fixed Window.always_hide_cursor. (Parameter was ignored.)
+- Fix in zz Vi key binding. (When render info is not available.)
+- Fix in Document.get_cursor_up_position. (When an argument is given.)
+
+New features:
+- Separated `load_mouse_bindings`.
+- Refactoring/simplification of the key bindings: better use of filters and
+ CLI.editing_mode.
+- Added DummyOutput class and a few unit tests that test the whole CLI.
+- Use the bisect module in Document._line_start_indexes instead of a custom
+ binary search. This should improve the performance.
+- Stay in the same column when doing multiple up/down movements.
+- Visual improvements:
+ * Implemented cursorcolumn, cursorline and colorcolumn.
+ * Only reserve menu space when `complete_while_typing=True` or when there are
+ completions to be displayed.
+ * Support for chaining tokens for combined styles. SelectedText will now
+ reverse the colors from the highlighting by default. Style
+ `Token.SelectedText` to set a fixed foreground/background.
+ Also for SearchMatch, we now use combined tokens.
+ * Support for dark gray on Windows.
+ * Default token for SystemToolbar and SearchToolbar.
+ * Display selection also on empty lines.
+- Emacs key bindings improved:
+ * Recognize + handle ControlDelete key.
+ * Implemented meta-* and control-backslash key bindings.
+- Vi key bindings improved:
+ * Handle inclusive and linewise motions properly.
+ * Fix g_ motion off by one character, and don't work when cursor is in
+ the trailing whitespace part of line.
+ * Make a(/a)/i(/i)/... motions. Find enclosing brackets instead of the next
+ bracket.
+ * Update N% motion according to vim behaviors.
+ * Fix | motion off by one character.
+ * ge/gE motions go to end of previous word, not start.
+ * Added Vi 'gm' key binding.
+ * Implemented 'gq' key binding in Vi mode. (Reshape text.)
+ * Vi operator/text object separation for key bindings.
+ * Added 'ap' (auto-paragraph) text object.
+ * Implemented Vi digraphs. ControlK will now insert a digraph.
+ * Implemented vi tilde_operator.
+ * Support named registers.
+ * Vi < and > key bindings became operators.
+ * Text objects and motions are now separate bindings.
+ * Improved copy/paste in Vi mode.
+
+Backwards-incompatible changes:
+- Don't reset the current buffer anymore by default in
+ CommandLineInterface.run(). Passing `reset_current_buffer=True` is now
+ required.
+- Renamed MouseEventTypes to MouseEventType for consistency. The old name is
+ still valid, but deprecated.
+- Refactoring of Callbacks. All events should now receive one argument, which
+ is the sender. (Furter, Callback was renamed to Event.) This is mostly used
+ internally.
+- Moved on_invalidate callback from CommandLineInterface to Application
+- Renamed `PipeInput.send` to `PipeInput.send_text`. (Old deprecated name is
+ still kept as a valid alias.)
+- Renamed SimpleLexer.default_token to SimpleLexer.token. (+
+ backwards-compatibility.)
+- Refactoring of the filters: `ViStateFilter` has been deprecated. (Should not
+ be used anymore.) Use the filters, as defined in prompt_toolkit.filters.
+- `editing_mode` is now a property of `CommandLineInterface`. This is replacing
+ the `vi_mode` parameter in `KeyBindingManager`.
+- The default accept_action for the default Buffer in Application now becomes
+ IGNORE. This is a much more sensible default. Pass RETURN_DOCUMENT to get
+ the previous behaviour,
+- Always expect an EventLoop instance in CommandLineInterface. Creating it in
+ __init__ caused a memory leak.
0.60: 2016-03-14
diff --git a/PKG-INFO b/PKG-INFO
index 128f1a9..5bd2723 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: prompt_toolkit
-Version: 0.60
+Version: 1.0.0
Summary: Library for building powerful interactive command lines in Python
Home-page: https://github.com/jonathanslenders/python-prompt-toolkit
Author: Jonathan Slenders
@@ -42,7 +42,7 @@ Description: Python Prompt Toolkit
- Advanced code completion.
- Both Emacs and Vi key bindings. (Similar to readline.)
- Reverse and forward incremental search.
- - Runs on all Python versions from 2.6 up to 3.4.
+ - Runs on all Python versions from 2.6 up to 3.5.
- Works well with Unicode double width characters. (Chinese input.)
- Selecting text for copy/paste. (Both Emacs and Vi style.)
- Support for `bracketed paste <https://cirw.in/blog/bracketed-paste>`_.
@@ -122,7 +122,7 @@ Description: Python Prompt Toolkit
- `pgcli <http://pgcli.com/>`_: Postgres client.
- `mycli <http://mycli.net>`_: MySql client.
- `wharfee <http://wharfee.com/>`_: A Docker command line.
- - `xonsh <http://xonsh.org/>`_: A Python-ish, BASHwards-compatible shell.
+ - `xonsh <http://xon.sh/>`_: A Python-ish, BASHwards-compatible shell.
- `saws <https://github.com/donnemartin/saws>`_: A Supercharged AWS Command Line Interface.
- `cycli <https://github.com/nicolewhite/cycli>`_: A Command Line Interface for Cypher.
- `crash <https://github.com/crate/crash>`_: Crate command line client.
@@ -130,6 +130,8 @@ Description: Python Prompt Toolkit
- `aws-shell <https://github.com/awslabs/aws-shell>`_: An integrated shell for working with the AWS CLI.
- `softlayer-python <https://github.com/softlayer/softlayer-python>`_: A command-line interface to manage various SoftLayer products and services.
- `ipython <http://github.com/ipython/ipython/>`_: The IPython REPL
+ - `click-repl <https://github.com/click-contrib/click-repl>`_: Subcommand REPL for click apps.
+ - `haxor-news <https://github.com/donnemartin/haxor-news>`_: A Hacker News CLI.
Full screen applications:
diff --git a/README.rst b/README.rst
index ce28b6a..d6a797b 100644
--- a/README.rst
+++ b/README.rst
@@ -34,7 +34,7 @@ Some features:
- Advanced code completion.
- Both Emacs and Vi key bindings. (Similar to readline.)
- Reverse and forward incremental search.
-- Runs on all Python versions from 2.6 up to 3.4.
+- Runs on all Python versions from 2.6 up to 3.5.
- Works well with Unicode double width characters. (Chinese input.)
- Selecting text for copy/paste. (Both Emacs and Vi style.)
- Support for `bracketed paste <https://cirw.in/blog/bracketed-paste>`_.
@@ -114,7 +114,7 @@ Shells:
- `pgcli <http://pgcli.com/>`_: Postgres client.
- `mycli <http://mycli.net>`_: MySql client.
- `wharfee <http://wharfee.com/>`_: A Docker command line.
-- `xonsh <http://xonsh.org/>`_: A Python-ish, BASHwards-compatible shell.
+- `xonsh <http://xon.sh/>`_: A Python-ish, BASHwards-compatible shell.
- `saws <https://github.com/donnemartin/saws>`_: A Supercharged AWS Command Line Interface.
- `cycli <https://github.com/nicolewhite/cycli>`_: A Command Line Interface for Cypher.
- `crash <https://github.com/crate/crash>`_: Crate command line client.
@@ -122,6 +122,8 @@ Shells:
- `aws-shell <https://github.com/awslabs/aws-shell>`_: An integrated shell for working with the AWS CLI.
- `softlayer-python <https://github.com/softlayer/softlayer-python>`_: A command-line interface to manage various SoftLayer products and services.
- `ipython <http://github.com/ipython/ipython/>`_: The IPython REPL
+- `click-repl <https://github.com/click-contrib/click-repl>`_: Subcommand REPL for click apps.
+- `haxor-news <https://github.com/donnemartin/haxor-news>`_: A Hacker News CLI.
Full screen applications:
diff --git a/examples/clock-input.py b/examples/clock-input.py
index 8d2ff24..33e826b 100755
--- a/examples/clock-input.py
+++ b/examples/clock-input.py
@@ -10,7 +10,6 @@ from prompt_toolkit.layout.controls import BufferControl
from prompt_toolkit.layout.processors import BeforeInput
from prompt_toolkit.shortcuts import create_eventloop
from prompt_toolkit.token import Token
-from prompt_toolkit.utils import Callback
import datetime
import time
@@ -45,13 +44,13 @@ def main():
cli.eventloop.run_in_executor(run)
- def on_read_end(cli):
+ def on_read_stop(cli):
done[0] = True
app = Application(
layout=Window(BufferControl(input_processors=[BeforeInput(_clock_tokens)])),
- on_start=Callback(on_read_start),
- on_stop=Callback(on_read_end))
+ on_start=on_read_start,
+ on_stop=on_read_stop)
cli = CommandLineInterface(application=app, eventloop=eventloop)
diff --git a/examples/full-screen-layout.py b/examples/full-screen-layout.py
index 696079e..6883d28 100755
--- a/examples/full-screen-layout.py
+++ b/examples/full-screen-layout.py
@@ -113,13 +113,17 @@ manager = KeyBindingManager() # Start with the `KeyBindingManager`.
# `eager=True` to all key bindings, but do it when it conflicts with another
# existing key binding, and you definitely want to override that behaviour.
+ at manager.registry.add_binding(Keys.ControlC, eager=True)
@manager.registry.add_binding(Keys.ControlQ, eager=True)
def _(event):
"""
- Pressing Ctrl-Q will exit the user interface.
+ Pressing Ctrl-Q or Ctrl-C will exit the user interface.
Setting a return value means: quit the event loop that drives the user
interface and return this value from the `CommandLineInterface.run()` call.
+
+ Note that Ctrl-Q does not work on all terminals. Sometimes it requires
+ executing `stty -ixon`.
"""
event.cli.set_return_value(None)
@@ -137,7 +141,7 @@ buffers={
# Now we add an event handler that captures change events to the buffer on the
# left. If the text changes over there, we'll update the buffer on the right.
-def default_buffer_changed():
+def default_buffer_changed(cli):
"""
When the buffer on the left (DEFAULT_BUFFER) changes, update the buffer on
the right. We just reverse the text.
diff --git a/examples/switch-between-vi-emacs.py b/examples/switch-between-vi-emacs.py
index 4791f73..8ba11ac 100755
--- a/examples/switch-between-vi-emacs.py
+++ b/examples/switch-between-vi-emacs.py
@@ -4,26 +4,25 @@ Example that displays how to switch between Emacs and Vi input mode.
"""
from prompt_toolkit import prompt
-from prompt_toolkit.filters import Condition
+from prompt_toolkit.enums import EditingMode
from prompt_toolkit.key_binding.manager import KeyBindingManager
from prompt_toolkit.keys import Keys
from prompt_toolkit.styles import style_from_dict
from prompt_toolkit.token import Token
def run():
- vi_mode_enabled = False
-
# Create a set of key bindings that have Vi mode enabled if the
# ``vi_mode_enabled`` is True..
- manager = KeyBindingManager.for_prompt(
- enable_vi_mode=Condition(lambda cli: vi_mode_enabled))
+ manager = KeyBindingManager.for_prompt()
# Add an additional key binding for toggling this flag.
@manager.registry.add_binding(Keys.F4)
def _(event):
" Toggle between Emacs and Vi mode. "
- nonlocal vi_mode_enabled
- vi_mode_enabled = not vi_mode_enabled
+ if event.cli.editing_mode == EditingMode.VI:
+ event.cli.editing_mode = EditingMode.EMACS
+ else:
+ event.cli.editing_mode = EditingMode.VI
# Add a bottom toolbar to display the status.
style = style_from_dict({
@@ -32,7 +31,7 @@ def run():
def get_bottom_toolbar_tokens(cli):
" Display the current input mode. "
- text = 'Vi' if vi_mode_enabled else 'Emacs'
+ text = 'Vi' if cli.editing_mode == EditingMode.VI else 'Emacs'
return [
(Token.Toolbar, ' [F4] %s ' % text)
]
diff --git a/prompt_toolkit.egg-info/PKG-INFO b/prompt_toolkit.egg-info/PKG-INFO
index ba464f9..bd517f6 100644
--- a/prompt_toolkit.egg-info/PKG-INFO
+++ b/prompt_toolkit.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: prompt-toolkit
-Version: 0.60
+Version: 1.0.0
Summary: Library for building powerful interactive command lines in Python
Home-page: https://github.com/jonathanslenders/python-prompt-toolkit
Author: Jonathan Slenders
@@ -42,7 +42,7 @@ Description: Python Prompt Toolkit
- Advanced code completion.
- Both Emacs and Vi key bindings. (Similar to readline.)
- Reverse and forward incremental search.
- - Runs on all Python versions from 2.6 up to 3.4.
+ - Runs on all Python versions from 2.6 up to 3.5.
- Works well with Unicode double width characters. (Chinese input.)
- Selecting text for copy/paste. (Both Emacs and Vi style.)
- Support for `bracketed paste <https://cirw.in/blog/bracketed-paste>`_.
@@ -122,7 +122,7 @@ Description: Python Prompt Toolkit
- `pgcli <http://pgcli.com/>`_: Postgres client.
- `mycli <http://mycli.net>`_: MySql client.
- `wharfee <http://wharfee.com/>`_: A Docker command line.
- - `xonsh <http://xonsh.org/>`_: A Python-ish, BASHwards-compatible shell.
+ - `xonsh <http://xon.sh/>`_: A Python-ish, BASHwards-compatible shell.
- `saws <https://github.com/donnemartin/saws>`_: A Supercharged AWS Command Line Interface.
- `cycli <https://github.com/nicolewhite/cycli>`_: A Command Line Interface for Cypher.
- `crash <https://github.com/crate/crash>`_: Crate command line client.
@@ -130,6 +130,8 @@ Description: Python Prompt Toolkit
- `aws-shell <https://github.com/awslabs/aws-shell>`_: An integrated shell for working with the AWS CLI.
- `softlayer-python <https://github.com/softlayer/softlayer-python>`_: A command-line interface to manage various SoftLayer products and services.
- `ipython <http://github.com/ipython/ipython/>`_: The IPython REPL
+ - `click-repl <https://github.com/click-contrib/click-repl>`_: Subcommand REPL for click apps.
+ - `haxor-news <https://github.com/donnemartin/haxor-news>`_: A Hacker News CLI.
Full screen applications:
diff --git a/prompt_toolkit.egg-info/SOURCES.txt b/prompt_toolkit.egg-info/SOURCES.txt
index c8a5061..0c45d30 100644
--- a/prompt_toolkit.egg-info/SOURCES.txt
+++ b/prompt_toolkit.egg-info/SOURCES.txt
@@ -112,6 +112,7 @@ prompt_toolkit/filters/cli.py
prompt_toolkit/filters/types.py
prompt_toolkit/filters/utils.py
prompt_toolkit/key_binding/__init__.py
+prompt_toolkit/key_binding/digraphs.py
prompt_toolkit/key_binding/input_processor.py
prompt_toolkit/key_binding/manager.py
prompt_toolkit/key_binding/registry.py
@@ -140,12 +141,14 @@ prompt_toolkit/styles/base.py
prompt_toolkit/styles/defaults.py
prompt_toolkit/styles/from_dict.py
prompt_toolkit/styles/from_pygments.py
+prompt_toolkit/styles/utils.py
prompt_toolkit/terminal/__init__.py
prompt_toolkit/terminal/conemu_output.py
prompt_toolkit/terminal/vt100_input.py
prompt_toolkit/terminal/vt100_output.py
prompt_toolkit/terminal/win32_input.py
prompt_toolkit/terminal/win32_output.py
+tests/cli_tests.py
tests/contrib_tests.py
tests/filter_tests.py
tests/run_tests.py
diff --git a/prompt_toolkit/__init__.py b/prompt_toolkit/__init__.py
index d4d23b5..04c1450 100644
--- a/prompt_toolkit/__init__.py
+++ b/prompt_toolkit/__init__.py
@@ -19,4 +19,4 @@ from .shortcuts import prompt
# Don't forget to update in `docs/conf.py`!
-__version__ = '0.60'
+__version__ = '1.0.0'
diff --git a/prompt_toolkit/application.py b/prompt_toolkit/application.py
index c23fa1f..f47a033 100644
--- a/prompt_toolkit/application.py
+++ b/prompt_toolkit/application.py
@@ -3,16 +3,17 @@ from __future__ import unicode_literals
from .buffer import Buffer, AcceptAction
from .buffer_mapping import BufferMapping
from .clipboard import Clipboard, InMemoryClipboard
-from .enums import DEFAULT_BUFFER
+from .enums import DEFAULT_BUFFER, EditingMode
from .filters import CLIFilter, to_cli_filter
from .key_binding.bindings.basic import load_basic_bindings
from .key_binding.bindings.emacs import load_emacs_bindings
+from .key_binding.bindings.vi import load_vi_bindings
from .key_binding.registry import Registry
from .layout import Window
from .layout.containers import Container
from .layout.controls import BufferControl
from .styles import DEFAULT_STYLE, Style
-from .utils import Callback
+import six
__all__ = (
'AbortAction',
@@ -62,8 +63,10 @@ class Application(object):
boolean). When True, enable mouse support.
:param paste_mode: :class:`~prompt_toolkit.filters.CLIFilter` or boolean.
:param ignore_case: :class:`~prompt_toolkit.filters.CLIFilter` or boolean.
+ :param editing_mode: :class:`~prompt_toolkit.enums.EditingMode`.
- Callbacks:
+ Callbacks (all of these should accept a
+ :class:`~prompt_toolkit.interface.CommandLineInterface` object as input.)
:param on_input_timeout: Called when there is no input for x seconds.
(Fired when any eventloop.onInputTimeout is fired.)
@@ -74,6 +77,7 @@ class Application(object):
:param on_initialize: Called after the
:class:`~prompt_toolkit.interface.CommandLineInterface` initializes.
:param on_render: Called right after rendering.
+ :param on_invalidate: Called when the UI has been invalidated.
"""
def __init__(self, layout=None, buffer=None, buffers=None,
initial_focussed_buffer=DEFAULT_BUFFER,
@@ -83,10 +87,11 @@ class Application(object):
use_alternate_screen=False, mouse_support=False,
get_title=None,
- paste_mode=False, ignore_case=False,
+ paste_mode=False, ignore_case=False, editing_mode=EditingMode.EMACS,
on_input_timeout=None, on_start=None, on_stop=None,
- on_reset=None, on_initialize=None, on_buffer_changed=None, on_render=None):
+ on_reset=None, on_initialize=None, on_buffer_changed=None,
+ on_render=None, on_invalidate=None):
paste_mode = to_cli_filter(paste_mode)
ignore_case = to_cli_filter(ignore_case)
@@ -103,18 +108,27 @@ class Application(object):
assert get_title is None or callable(get_title)
assert isinstance(paste_mode, CLIFilter)
assert isinstance(ignore_case, CLIFilter)
- assert on_start is None or isinstance(on_start, Callback)
- assert on_stop is None or isinstance(on_stop, Callback)
- assert on_reset is None or isinstance(on_reset, Callback)
- assert on_buffer_changed is None or isinstance(on_buffer_changed, Callback)
- assert on_initialize is None or isinstance(on_initialize, Callback)
- assert on_render is None or isinstance(on_render, Callback)
+ assert isinstance(editing_mode, six.string_types)
+ assert on_input_timeout is None or callable(on_input_timeout)
assert style is None or isinstance(style, Style)
+ assert on_start is None or callable(on_start)
+ assert on_stop is None or callable(on_stop)
+ assert on_reset is None or callable(on_reset)
+ assert on_buffer_changed is None or callable(on_buffer_changed)
+ assert on_initialize is None or callable(on_initialize)
+ assert on_render is None or callable(on_render)
+ assert on_invalidate is None or callable(on_invalidate)
+
self.layout = layout or Window(BufferControl())
# Make sure that the 'buffers' dictionary is a BufferMapping.
- self.buffer = buffer or Buffer(accept_action=AcceptAction.RETURN_DOCUMENT)
+ # NOTE: If no buffer is given, we create a default Buffer, with IGNORE as
+ # default accept_action. This is what makes sense for most users
+ # creating full screen applications. Doing nothing is the obvious
+ # default. Those creating a REPL would use the shortcuts module that
+ # passes in RETURN_DOCUMENT.
+ self.buffer = buffer or Buffer(accept_action=AcceptAction.IGNORE)
if not buffers or not isinstance(buffers, BufferMapping):
self.buffers = BufferMapping(buffers, initial=initial_focussed_buffer)
else:
@@ -131,6 +145,7 @@ class Application(object):
key_bindings_registry = Registry()
load_basic_bindings(key_bindings_registry)
load_emacs_bindings(key_bindings_registry)
+ load_vi_bindings(key_bindings_registry)
if get_title is None:
get_title = lambda: None
@@ -145,11 +160,16 @@ class Application(object):
self.paste_mode = paste_mode
self.ignore_case = ignore_case
-
- self.on_input_timeout = on_input_timeout or Callback()
- self.on_start = on_start or Callback()
- self.on_stop = on_stop or Callback()
- self.on_reset = on_reset or Callback()
- self.on_initialize = on_initialize or Callback()
- self.on_buffer_changed = on_buffer_changed or Callback()
- self.on_render = on_render or Callback()
+ self.editing_mode = editing_mode
+
+ def dummy_handler(cli):
+ " Dummy event handler. "
+
+ self.on_input_timeout = on_input_timeout or dummy_handler
+ self.on_start = on_start or dummy_handler
+ self.on_stop = on_stop or dummy_handler
+ self.on_reset = on_reset or dummy_handler
+ self.on_initialize = on_initialize or dummy_handler
+ self.on_buffer_changed = on_buffer_changed or dummy_handler
+ self.on_render = on_render or dummy_handler
+ self.on_invalidate = on_invalidate or dummy_handler
diff --git a/prompt_toolkit/buffer.py b/prompt_toolkit/buffer.py
index 0dc26c6..29dac07 100644
--- a/prompt_toolkit/buffer.py
+++ b/prompt_toolkit/buffer.py
@@ -13,13 +13,14 @@ from .filters import to_simple_filter
from .history import History, InMemoryHistory
from .search_state import SearchState
from .selection import SelectionType, SelectionState
-from .utils import Callback
+from .utils import Event
from .cache import FastDictCache
from .validation import ValidationError
from six.moves import range
import os
+import re
import six
import subprocess
import tempfile
@@ -30,6 +31,7 @@ __all__ = (
'Buffer',
'indent',
'unindent',
+ 'reshape_text',
)
@@ -161,9 +163,9 @@ class Buffer(object):
Events:
- :param on_text_changed: Callback instance or None.
- :param on_text_insert: Callback instance or None.
- :param on_cursor_position_changed: Callback instance or None.
+ :param on_text_changed: When the buffer text changes. (Callable on None.)
+ :param on_text_insert: When new text is inserted. (Callable on None.)
+ :param on_cursor_position_changed: When the cursor moves. (Callable on None.)
Filters:
@@ -199,9 +201,9 @@ class Buffer(object):
assert completer is None or isinstance(completer, Completer)
assert auto_suggest is None or isinstance(auto_suggest, AutoSuggest)
assert history is None or isinstance(history, History)
- assert on_text_changed is None or isinstance(on_text_changed, Callback)
- assert on_text_insert is None or isinstance(on_text_insert, Callback)
- assert on_cursor_position_changed is None or isinstance(on_cursor_position_changed, Callback)
+ assert on_text_changed is None or callable(on_text_changed)
+ assert on_text_insert is None or callable(on_text_insert)
+ assert on_cursor_position_changed is None or callable(on_cursor_position_changed)
self.completer = completer
self.auto_suggest = auto_suggest
@@ -215,6 +217,9 @@ class Buffer(object):
self.enable_history_search = enable_history_search
self.read_only = read_only
+ # Text width. (For wrapping, used by the Vi 'gq' operator.)
+ self.text_width = 0
+
#: The command buffer history.
# Note that we shouldn't use a lazy 'or' here. bool(history) could be
# False when empty.
@@ -223,9 +228,9 @@ class Buffer(object):
self.__cursor_position = 0
# Events
- self.on_text_changed = on_text_changed or Callback()
- self.on_text_insert = on_text_insert or Callback()
- self.on_cursor_position_changed = on_cursor_position_changed or Callback()
+ self.on_text_changed = Event(self, on_text_changed)
+ self.on_text_insert = Event(self, on_text_insert)
+ self.on_cursor_position_changed = Event(self, on_cursor_position_changed)
# Document cache. (Avoid creating new Document instances.)
self._document_cache = FastDictCache(Document, size=10)
@@ -251,6 +256,9 @@ class Buffer(object):
# State of the selection.
self.selection_state = None
+ # When doing consecutive up/down movements, prefer to stay at this column.
+ self.preferred_column = None
+
# State of complete browser
self.complete_state = None # For interactive completion through Ctrl-N/Ctrl-P.
@@ -362,6 +370,7 @@ class Buffer(object):
self.complete_state = None
self.selection_state = None
self.suggestion = None
+ self.preferred_column = None
# fire 'on_text_changed' event.
self.on_text_changed.fire()
@@ -371,6 +380,10 @@ class Buffer(object):
self.validation_error = None
self.complete_state = None
+ # Unset preferred_column. (Will be set after the cursor movement, if
+ # required.)
+ self.preferred_column = None
+
# Note that the cursor position can change if we have a selection the
# new position of the cursor determines the end of the selection.
@@ -494,11 +507,21 @@ class Buffer(object):
def cursor_up(self, count=1):
""" (for multiline edit). Move cursor to the previous line. """
- self.cursor_position += self.document.get_cursor_up_position(count=count)
+ original_column = self.preferred_column or self.document.cursor_position_col
+ self.cursor_position += self.document.get_cursor_up_position(
+ count=count, preferred_column=original_column)
+
+ # Remember the original column for the next up/down movement.
+ self.preferred_column = original_column
def cursor_down(self, count=1):
""" (for multiline edit). Move cursor to the next line. """
- self.cursor_position += self.document.get_cursor_down_position(count=count)
+ original_column = self.preferred_column or self.document.cursor_position_col
+ self.cursor_position += self.document.get_cursor_down_position(
+ count=count, preferred_column=original_column)
+
+ # Remember the original column for the next up/down movement.
+ self.preferred_column = original_column
def auto_up(self, count=1):
"""
@@ -508,7 +531,7 @@ class Buffer(object):
if self.complete_state:
self.complete_previous(count=count)
elif self.document.cursor_position_row > 0:
- self.cursor_position += self.document.get_cursor_up_position(count=count)
+ self.cursor_up(count=count)
elif not self.selection_state:
self.history_backward(count=count)
@@ -520,7 +543,7 @@ class Buffer(object):
if self.complete_state:
self.complete_next(count=count)
elif self.document.cursor_position_row < self.document.line_count - 1:
- self.cursor_position += self.document.get_cursor_down_position(count=count)
+ self.cursor_down(count=count)
elif not self.selection_state:
self.history_forward(count=count)
@@ -1171,3 +1194,48 @@ def unindent(buffer, from_row, to_row, count=1):
# Go to the start of the line.
buffer.cursor_position += buffer.document.get_start_of_line_position(after_whitespace=True)
+
+
+def reshape_text(buffer, from_row, to_row):
+ """
+ Reformat text, taking the width into account.
+ `to_row` is included.
+ (Vi 'gq' operator.)
+ """
+ lines = buffer.text.splitlines(True)
+ lines_before = lines[:from_row]
+ lines_after = lines[to_row + 1:]
+ lines_to_reformat = lines[from_row:to_row + 1]
+
+ if lines_to_reformat:
+ # Take indentation from the first line.
+ length = re.search(r'^\s*', lines_to_reformat[0]).end()
+ indent = lines_to_reformat[0][:length].replace('\n', '')
+
+ # Now, take all the 'words' from the lines to be reshaped.
+ words = ''.join(lines_to_reformat).split()
+
+ # And reshape.
+ width = (buffer.text_width or 80) - len(indent)
+ reshaped_text = [indent]
+ current_width = 0
+ for w in words:
+ if current_width:
+ if len(w) + current_width + 1 > width:
+ reshaped_text.append('\n')
+ reshaped_text.append(indent)
+ current_width = 0
+ else:
+ reshaped_text.append(' ')
+ current_width += 1
+
+ reshaped_text.append(w)
+ current_width += len(w)
+
+ if reshaped_text[-1] != '\n':
+ reshaped_text.append('\n')
+
+ # Apply result.
+ buffer.document = Document(
+ text=''.join(lines_before + reshaped_text + lines_after),
+ cursor_position=len(''.join(lines_before + reshaped_text)))
diff --git a/prompt_toolkit/contrib/regular_languages/compiler.py b/prompt_toolkit/contrib/regular_languages/compiler.py
index 1e50fcf..01476bf 100644
--- a/prompt_toolkit/contrib/regular_languages/compiler.py
+++ b/prompt_toolkit/contrib/regular_languages/compiler.py
@@ -41,6 +41,7 @@ Partial matches are possible::
from __future__ import unicode_literals
import re
+from six.moves import range
from .regex_parser import Any, Sequence, Regex, Variable, Repeat, Lookahead
from .regex_parser import parse_regex, tokenize_regex
diff --git a/prompt_toolkit/document.py b/prompt_toolkit/document.py
index 60b9e51..ed9b056 100644
--- a/prompt_toolkit/document.py
+++ b/prompt_toolkit/document.py
@@ -3,11 +3,12 @@ The `Document` that implements all the text operations/querying.
"""
from __future__ import unicode_literals
+import bisect
import re
import six
import string
import weakref
-from six.moves import range
+from six.moves import range, map
from .selection import SelectionType, SelectionState
from .clipboard import ClipboardData
@@ -99,7 +100,17 @@ class Document(object):
# Cache for lines/indexes. (Shared with other Document instances that
# contain the same text.
- self._cache = _text_to_document_cache.setdefault(self.text, _DocumentCache())
+ try:
+ self._cache = _text_to_document_cache[self.text]
+ except KeyError:
+ self._cache = _DocumentCache()
+ _text_to_document_cache[self.text] = self._cache
+
+ # XX: For some reason, above, we can't use 'WeakValueDictionary.setdefault'.
+ # This fails in Pypy3. `self._cache` becomes None, because that's what
+ # 'setdefault' returns.
+ # self._cache = _text_to_document_cache.setdefault(self.text, _DocumentCache())
+ # assert self._cache
def __repr__(self):
return '%s(%r, %r)' % (self.__class__.__name__, self.text, self.cursor_position)
@@ -125,12 +136,14 @@ class Document(object):
@property
def current_line_before_cursor(self):
""" Text from the start of the line until the cursor. """
- return self.text_before_cursor.rsplit('\n', 1)[-1]
+ _, _, text = self.text_before_cursor.rpartition('\n')
+ return text
@property
def current_line_after_cursor(self):
""" Text from the cursor until the end of the line. """
- return self.text_after_cursor.split('\n', 1)[0]
+ text, _, _ = self.text_after_cursor.partition('\n')
+ return text
@property
def lines(self):
@@ -248,24 +261,8 @@ class Document(object):
"""
indexes = self._line_start_indexes
- # Special case: 'index' appears after the last line.
- if index >= indexes[-1]:
- return len(indexes) - 1, indexes[-1]
-
- # Binary search for the closest index.
- a, b = 0, len(indexes) - 1
-
- while a != b:
- mid = (a + b) // 2
-
- if indexes[mid] <= index and indexes[mid + 1] > index:
- return mid, indexes[mid]
- elif indexes[mid] <= index:
- a = mid
- else:
- b = mid
-
- return a, indexes[a]
+ pos = bisect.bisect_right(indexes, index) - 1
+ return pos, indexes[pos]
def translate_index_to_position(self, index):
"""
@@ -283,15 +280,21 @@ class Document(object):
"""
Given a (row, col) tuple, return the corresponding index.
(Row and col params are 0-based.)
+
+ Negative row/col values are turned into zero.
"""
try:
result = self._line_start_indexes[row]
line = self.lines[row]
except IndexError:
- result = self._line_start_indexes[-1]
- line = self.lines[-1]
+ if row < 0:
+ result = self._line_start_indexes[0]
+ line = self.lines[0]
+ else:
+ result = self._line_start_indexes[-1]
+ line = self.lines[-1]
- result += min(col, len(line))
+ result += max(0, min(col, len(line)))
# Keep in range. (len(self.text) is included, because the cursor can be
# right after the end of the text as well.)
@@ -502,7 +505,7 @@ class Document(object):
def find_previous_word_beginning(self, count=1, WORD=False):
"""
Return an index relative to the cursor position pointing to the start
- of the next word. Return `None` if nothing was found.
+ of the previous word. Return `None` if nothing was found.
"""
regex = _FIND_BIG_WORD_RE if WORD else _FIND_WORD_RE
iterator = regex.finditer(self.text_before_cursor[::-1])
@@ -514,6 +517,27 @@ class Document(object):
except StopIteration:
pass
+ def find_previous_word_ending(self, count=1, WORD=False):
+ """
+ Return an index relative to the cursor position pointing to the end
+ of the previous word. Return `None` if nothing was found.
+ """
+ text_before_cursor = self.text_after_cursor[:1] + self.text_before_cursor[::-1]
+
+ regex = _FIND_BIG_WORD_RE if WORD else _FIND_WORD_RE
+ iterator = regex.finditer(text_before_cursor)
+
+ try:
+ for i, match in enumerate(iterator):
+ # Take first match, unless it's the word on which we're right now.
+ if i == 0 and match.start(1) == 0:
+ count += 1
+
+ if i + 1 == count:
+ return -match.start(1) + 1
+ except StopIteration:
+ pass
+
def find_next_matching_line(self, match_func, count=1):
"""
Look downwards for empty lines.
@@ -560,73 +584,105 @@ class Document(object):
"""
return min(count, len(self.current_line_after_cursor))
- def get_cursor_up_position(self, count=1):
+ def get_cursor_up_position(self, count=1, preferred_column=None):
"""
Return the relative cursor position (character index) where we would be if the
user pressed the arrow-up button.
+
+ :param preferred_column: When given, go to this column instead of
+ staying at the current column.
"""
assert count >= 1
- if self.cursor_position_row > 0:
- return self.translate_row_col_to_index(
- self.cursor_position_row - count, self.cursor_position_col) - self.cursor_position
- else:
- return 0
+ column = self.cursor_position_col if preferred_column is None else preferred_column
- def get_cursor_down_position(self, count=1):
+ return self.translate_row_col_to_index(
+ max(0, self.cursor_position_row - count), column) - self.cursor_position
+
+ def get_cursor_down_position(self, count=1, preferred_column=None):
"""
Return the relative cursor position (character index) where we would be if the
user pressed the arrow-down button.
+
+ :param preferred_column: When given, go to this column instead of
+ staying at the current column.
"""
assert count >= 1
+ column = self.cursor_position_col if preferred_column is None else preferred_column
+
return self.translate_row_col_to_index(
- self.cursor_position_row + count, self.cursor_position_col) - self.cursor_position
+ self.cursor_position_row + count, column) - self.cursor_position
- def find_matching_bracket_position(self, start_pos=None, end_pos=None):
+ def find_enclosing_bracket_right(self, left_ch, right_ch, end_pos=None):
"""
- Return relative cursor position of matching [, (, { or < bracket.
+ Find the right bracket enclosing current position. Return the relative
+ position to the cursor position.
- When `start_pos` or `end_pos` are given. Don't look past the positions.
+ When `end_pos` is given, don't look past the position.
"""
+ if self.current_char == right_ch:
+ return 0
+
+ if end_pos is None:
+ end_pos = len(self.text)
+ else:
+ end_pos = min(len(self.text), end_pos)
+
stack = 1
- # Start/end limit.
+ # Look forward.
+ for i in range(self.cursor_position + 1, end_pos):
+ c = self.text[i]
+
+ if c == left_ch:
+ stack += 1
+ elif c == right_ch:
+ stack -= 1
+
+ if stack == 0:
+ return i - self.cursor_position
+
+ def find_enclosing_bracket_left(self, left_ch, right_ch, start_pos=None):
+ """
+ Find the left bracket enclosing current position. Return the relative
+ position to the cursor position.
+
+ When `start_pos` is given, don't look past the position.
+ """
+ if self.current_char == left_ch:
+ return 0
+
if start_pos is None:
start_pos = 0
else:
start_pos = max(0, start_pos)
- if end_pos is None:
- end_pos = len(self.text)
- else:
- end_pos = min(len(self.text), end_pos)
+ stack = 1
- # Look for a match.
- for A, B in '()', '[]', '{}', '<>':
- # Look forward.
- if self.current_char == A:
- for i in range(self.cursor_position + 1, end_pos):
- c = self.text[i]
+ # Look backward.
+ for i in range(self.cursor_position - 1, start_pos - 1, -1):
... 5736 lines suppressed ...
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/prompt-toolkit.git
More information about the Python-modules-commits
mailing list