1from __future__ import unicode_literals
2
3from .buffer import Buffer, AcceptAction
4from .buffer_mapping import BufferMapping
5from .clipboard import Clipboard, InMemoryClipboard
6from .enums import DEFAULT_BUFFER, EditingMode
7from .filters import CLIFilter, to_cli_filter
8from .key_binding.bindings.basic import load_basic_bindings
9from .key_binding.bindings.emacs import load_emacs_bindings
10from .key_binding.bindings.vi import load_vi_bindings
11from .key_binding.registry import BaseRegistry
12from .key_binding.defaults import load_key_bindings
13from .layout import Window
14from .layout.containers import Container
15from .layout.controls import BufferControl
16from .styles import DEFAULT_STYLE, Style
17import six
18
19__all__ = (
20    'AbortAction',
21    'Application',
22)
23
24
25class AbortAction(object):
26    """
27    Actions to take on an Exit or Abort exception.
28    """
29    RETRY = 'retry'
30    RAISE_EXCEPTION = 'raise-exception'
31    RETURN_NONE = 'return-none'
32
33    _all = (RETRY, RAISE_EXCEPTION, RETURN_NONE)
34
35
36class Application(object):
37    """
38    Application class to be passed to a
39    :class:`~prompt_toolkit.interface.CommandLineInterface`.
40
41    This contains all customizable logic that is not I/O dependent.
42    (So, what is independent of event loops, input and output.)
43
44    This way, such an :class:`.Application` can run easily on several
45    :class:`~prompt_toolkit.interface.CommandLineInterface` instances, each
46    with a different I/O backends. that runs for instance over telnet, SSH or
47    any other I/O backend.
48
49    :param layout: A :class:`~prompt_toolkit.layout.containers.Container` instance.
50    :param buffer: A :class:`~prompt_toolkit.buffer.Buffer` instance for the default buffer.
51    :param initial_focussed_buffer: Name of the buffer that is focussed during start-up.
52    :param key_bindings_registry:
53        :class:`~prompt_toolkit.key_binding.registry.BaseRegistry` instance for
54        the key bindings.
55    :param clipboard: :class:`~prompt_toolkit.clipboard.base.Clipboard` to use.
56    :param on_abort: What to do when Control-C is pressed.
57    :param on_exit: What to do when Control-D is pressed.
58    :param use_alternate_screen: When True, run the application on the alternate screen buffer.
59    :param get_title: Callable that returns the current title to be displayed in the terminal.
60    :param erase_when_done: (bool) Clear the application output when it finishes.
61    :param reverse_vi_search_direction: Normally, in Vi mode, a '/' searches
62        forward and a '?' searches backward. In readline mode, this is usually
63        reversed.
64
65    Filters:
66
67    :param mouse_support: (:class:`~prompt_toolkit.filters.CLIFilter` or
68        boolean). When True, enable mouse support.
69    :param paste_mode: :class:`~prompt_toolkit.filters.CLIFilter` or boolean.
70    :param ignore_case: :class:`~prompt_toolkit.filters.CLIFilter` or boolean.
71    :param editing_mode: :class:`~prompt_toolkit.enums.EditingMode`.
72
73    Callbacks (all of these should accept a
74    :class:`~prompt_toolkit.interface.CommandLineInterface` object as input.)
75
76    :param on_input_timeout: Called when there is no input for x seconds.
77                    (Fired when any eventloop.onInputTimeout is fired.)
78    :param on_start: Called when reading input starts.
79    :param on_stop: Called when reading input ends.
80    :param on_reset: Called during reset.
81    :param on_buffer_changed: Called when the content of a buffer has been changed.
82    :param on_initialize: Called after the
83        :class:`~prompt_toolkit.interface.CommandLineInterface` initializes.
84    :param on_render: Called right after rendering.
85    :param on_invalidate: Called when the UI has been invalidated.
86    """
87    def __init__(self, layout=None, buffer=None, buffers=None,
88                 initial_focussed_buffer=DEFAULT_BUFFER,
89                 style=None,
90                 key_bindings_registry=None, clipboard=None,
91                 on_abort=AbortAction.RAISE_EXCEPTION, on_exit=AbortAction.RAISE_EXCEPTION,
92                 use_alternate_screen=False, mouse_support=False,
93                 get_title=None,
94
95                 paste_mode=False, ignore_case=False, editing_mode=EditingMode.EMACS,
96                 erase_when_done=False,
97                 reverse_vi_search_direction=False,
98
99                 on_input_timeout=None, on_start=None, on_stop=None,
100                 on_reset=None, on_initialize=None, on_buffer_changed=None,
101                 on_render=None, on_invalidate=None):
102
103        paste_mode = to_cli_filter(paste_mode)
104        ignore_case = to_cli_filter(ignore_case)
105        mouse_support = to_cli_filter(mouse_support)
106        reverse_vi_search_direction = to_cli_filter(reverse_vi_search_direction)
107
108        assert layout is None or isinstance(layout, Container)
109        assert buffer is None or isinstance(buffer, Buffer)
110        assert buffers is None or isinstance(buffers, (dict, BufferMapping))
111        assert key_bindings_registry is None or isinstance(key_bindings_registry, BaseRegistry)
112        assert clipboard is None or isinstance(clipboard, Clipboard)
113        assert on_abort in AbortAction._all
114        assert on_exit in AbortAction._all
115        assert isinstance(use_alternate_screen, bool)
116        assert get_title is None or callable(get_title)
117        assert isinstance(paste_mode, CLIFilter)
118        assert isinstance(ignore_case, CLIFilter)
119        assert isinstance(editing_mode, six.string_types)
120        assert on_input_timeout is None or callable(on_input_timeout)
121        assert style is None or isinstance(style, Style)
122        assert isinstance(erase_when_done, bool)
123
124        assert on_start is None or callable(on_start)
125        assert on_stop is None or callable(on_stop)
126        assert on_reset is None or callable(on_reset)
127        assert on_buffer_changed is None or callable(on_buffer_changed)
128        assert on_initialize is None or callable(on_initialize)
129        assert on_render is None or callable(on_render)
130        assert on_invalidate is None or callable(on_invalidate)
131
132        self.layout = layout or Window(BufferControl())
133
134        # Make sure that the 'buffers' dictionary is a BufferMapping.
135        # NOTE: If no buffer is given, we create a default Buffer, with IGNORE as
136        #       default accept_action. This is what makes sense for most users
137        #       creating full screen applications. Doing nothing is the obvious
138        #       default. Those creating a REPL would use the shortcuts module that
139        #       passes in RETURN_DOCUMENT.
140        self.buffer = buffer or Buffer(accept_action=AcceptAction.IGNORE)
141        if not buffers or not isinstance(buffers, BufferMapping):
142            self.buffers = BufferMapping(buffers, initial=initial_focussed_buffer)
143        else:
144            self.buffers = buffers
145
146        if buffer:
147            self.buffers[DEFAULT_BUFFER] = buffer
148
149        self.initial_focussed_buffer = initial_focussed_buffer
150
151        self.style = style or DEFAULT_STYLE
152
153        if key_bindings_registry is None:
154            key_bindings_registry = load_key_bindings()
155
156        if get_title is None:
157            get_title = lambda: None
158
159        self.key_bindings_registry = key_bindings_registry
160        self.clipboard = clipboard or InMemoryClipboard()
161        self.on_abort = on_abort
162        self.on_exit = on_exit
163        self.use_alternate_screen = use_alternate_screen
164        self.mouse_support = mouse_support
165        self.get_title = get_title
166
167        self.paste_mode = paste_mode
168        self.ignore_case = ignore_case
169        self.editing_mode = editing_mode
170        self.erase_when_done = erase_when_done
171        self.reverse_vi_search_direction = reverse_vi_search_direction
172
173        def dummy_handler(cli):
174            " Dummy event handler. "
175
176        self.on_input_timeout = on_input_timeout or dummy_handler
177        self.on_start = on_start or dummy_handler
178        self.on_stop = on_stop or dummy_handler
179        self.on_reset = on_reset or dummy_handler
180        self.on_initialize = on_initialize or dummy_handler
181        self.on_buffer_changed = on_buffer_changed or dummy_handler
182        self.on_render = on_render or dummy_handler
183        self.on_invalidate = on_invalidate or dummy_handler
184
185        # List of 'extra' functions to execute before a CommandLineInterface.run.
186        # Note: It's important to keep this here, and not in the
187        #       CommandLineInterface itself. shortcuts.run_application creates
188        #       a new Application instance everytime. (Which is correct, it
189        #       could be that we want to detach from one IO backend and attach
190        #       the UI on a different backend.) But important is to keep as
191        #       much state as possible between runs.
192        self.pre_run_callables = []
193