1"""
2Key bindings for auto suggestion (for fish-style auto suggestion).
3"""
4
5from __future__ import annotations
6
7import re
8
9from prompt_toolkit.application.current import get_app
10from prompt_toolkit.filters import Condition, emacs_mode
11from prompt_toolkit.key_binding.key_bindings import KeyBindings
12from prompt_toolkit.key_binding.key_processor import KeyPressEvent
13
14__all__ = [
15 "load_auto_suggest_bindings",
16]
17
18E = KeyPressEvent
19
20
21def load_auto_suggest_bindings() -> KeyBindings:
22 """
23 Key bindings for accepting auto suggestion text.
24
25 (This has to come after the Vi bindings, because they also have an
26 implementation for the "right arrow", but we really want the suggestion
27 binding when a suggestion is available.)
28 """
29 key_bindings = KeyBindings()
30 handle = key_bindings.add
31
32 @Condition
33 def suggestion_available() -> bool:
34 app = get_app()
35 return (
36 app.current_buffer.suggestion is not None
37 and len(app.current_buffer.suggestion.text) > 0
38 and app.current_buffer.document.is_cursor_at_the_end
39 )
40
41 @handle("c-f", filter=suggestion_available)
42 @handle("c-e", filter=suggestion_available)
43 @handle("right", filter=suggestion_available)
44 def _accept(event: E) -> None:
45 """
46 Accept suggestion.
47 """
48 b = event.current_buffer
49 suggestion = b.suggestion
50
51 if suggestion:
52 b.insert_text(suggestion.text)
53
54 @handle("escape", "f", filter=suggestion_available & emacs_mode)
55 def _fill(event: E) -> None:
56 """
57 Fill partial suggestion.
58 """
59 b = event.current_buffer
60 suggestion = b.suggestion
61
62 if suggestion:
63 t = re.split(r"([^\s/]+(?:\s+|/))", suggestion.text)
64 b.insert_text(next(x for x in t if x))
65
66 return key_bindings