Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/prompt_toolkit/cursor_shapes.py: 64%
45 statements
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-20 06:09 +0000
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-20 06:09 +0000
1from __future__ import annotations
3from abc import ABC, abstractmethod
4from enum import Enum
5from typing import TYPE_CHECKING, Any, Callable, Union
7from prompt_toolkit.enums import EditingMode
8from prompt_toolkit.key_binding.vi_state import InputMode
10if TYPE_CHECKING:
11 from .application import Application
13__all__ = [
14 "CursorShape",
15 "CursorShapeConfig",
16 "SimpleCursorShapeConfig",
17 "ModalCursorShapeConfig",
18 "DynamicCursorShapeConfig",
19 "to_cursor_shape_config",
20]
23class CursorShape(Enum):
24 # Default value that should tell the output implementation to never send
25 # cursor shape escape sequences. This is the default right now, because
26 # before this `CursorShape` functionality was introduced into
27 # prompt_toolkit itself, people had workarounds to send cursor shapes
28 # escapes into the terminal, by monkey patching some of prompt_toolkit's
29 # internals. We don't want the default prompt_toolkit implementation to
30 # interfere with that. E.g., IPython patches the `ViState.input_mode`
31 # property. See: https://github.com/ipython/ipython/pull/13501/files
32 _NEVER_CHANGE = "_NEVER_CHANGE"
34 BLOCK = "BLOCK"
35 BEAM = "BEAM"
36 UNDERLINE = "UNDERLINE"
37 BLINKING_BLOCK = "BLINKING_BLOCK"
38 BLINKING_BEAM = "BLINKING_BEAM"
39 BLINKING_UNDERLINE = "BLINKING_UNDERLINE"
42class CursorShapeConfig(ABC):
43 @abstractmethod
44 def get_cursor_shape(self, application: Application[Any]) -> CursorShape:
45 """
46 Return the cursor shape to be used in the current state.
47 """
50AnyCursorShapeConfig = Union[CursorShape, CursorShapeConfig, None]
53class SimpleCursorShapeConfig(CursorShapeConfig):
54 """
55 Always show the given cursor shape.
56 """
58 def __init__(self, cursor_shape: CursorShape = CursorShape._NEVER_CHANGE) -> None:
59 self.cursor_shape = cursor_shape
61 def get_cursor_shape(self, application: Application[Any]) -> CursorShape:
62 return self.cursor_shape
65class ModalCursorShapeConfig(CursorShapeConfig):
66 """
67 Show cursor shape according to the current input mode.
68 """
70 def get_cursor_shape(self, application: Application[Any]) -> CursorShape:
71 if application.editing_mode == EditingMode.VI:
72 if application.vi_state.input_mode == InputMode.INSERT:
73 return CursorShape.BEAM
74 if application.vi_state.input_mode == InputMode.REPLACE:
75 return CursorShape.UNDERLINE
77 # Default
78 return CursorShape.BLOCK
81class DynamicCursorShapeConfig(CursorShapeConfig):
82 def __init__(
83 self, get_cursor_shape_config: Callable[[], AnyCursorShapeConfig]
84 ) -> None:
85 self.get_cursor_shape_config = get_cursor_shape_config
87 def get_cursor_shape(self, application: Application[Any]) -> CursorShape:
88 return to_cursor_shape_config(self.get_cursor_shape_config()).get_cursor_shape(
89 application
90 )
93def to_cursor_shape_config(value: AnyCursorShapeConfig) -> CursorShapeConfig:
94 """
95 Take a `CursorShape` instance or `CursorShapeConfig` and turn it into a
96 `CursorShapeConfig`.
97 """
98 if value is None:
99 return SimpleCursorShapeConfig()
101 if isinstance(value, CursorShape):
102 return SimpleCursorShapeConfig(value)
104 return value