| from __future__ import annotations |
|
|
| from abc import ABC, abstractmethod |
| from enum import Enum |
| from typing import TYPE_CHECKING, Any, Callable, Union |
|
|
| from prompt_toolkit.enums import EditingMode |
| from prompt_toolkit.key_binding.vi_state import InputMode |
|
|
| if TYPE_CHECKING: |
| from .application import Application |
|
|
| __all__ = [ |
| "CursorShape", |
| "CursorShapeConfig", |
| "SimpleCursorShapeConfig", |
| "ModalCursorShapeConfig", |
| "DynamicCursorShapeConfig", |
| "to_cursor_shape_config", |
| ] |
|
|
|
|
| class CursorShape(Enum): |
| |
| |
| |
| |
| |
| |
| |
| |
| _NEVER_CHANGE = "_NEVER_CHANGE" |
|
|
| BLOCK = "BLOCK" |
| BEAM = "BEAM" |
| UNDERLINE = "UNDERLINE" |
| BLINKING_BLOCK = "BLINKING_BLOCK" |
| BLINKING_BEAM = "BLINKING_BEAM" |
| BLINKING_UNDERLINE = "BLINKING_UNDERLINE" |
|
|
|
|
| class CursorShapeConfig(ABC): |
| @abstractmethod |
| def get_cursor_shape(self, application: Application[Any]) -> CursorShape: |
| """ |
| Return the cursor shape to be used in the current state. |
| """ |
|
|
|
|
| AnyCursorShapeConfig = Union[CursorShape, CursorShapeConfig, None] |
|
|
|
|
| class SimpleCursorShapeConfig(CursorShapeConfig): |
| """ |
| Always show the given cursor shape. |
| """ |
|
|
| def __init__(self, cursor_shape: CursorShape = CursorShape._NEVER_CHANGE) -> None: |
| self.cursor_shape = cursor_shape |
|
|
| def get_cursor_shape(self, application: Application[Any]) -> CursorShape: |
| return self.cursor_shape |
|
|
|
|
| class ModalCursorShapeConfig(CursorShapeConfig): |
| """ |
| Show cursor shape according to the current input mode. |
| """ |
|
|
| def get_cursor_shape(self, application: Application[Any]) -> CursorShape: |
| if application.editing_mode == EditingMode.VI: |
| if application.vi_state.input_mode in { |
| InputMode.NAVIGATION, |
| }: |
| return CursorShape.BLOCK |
| if application.vi_state.input_mode in { |
| InputMode.INSERT, |
| InputMode.INSERT_MULTIPLE, |
| }: |
| return CursorShape.BEAM |
| if application.vi_state.input_mode in { |
| InputMode.REPLACE, |
| InputMode.REPLACE_SINGLE, |
| }: |
| return CursorShape.UNDERLINE |
| elif application.editing_mode == EditingMode.EMACS: |
| |
| return CursorShape.BEAM |
|
|
| |
| return CursorShape.BLOCK |
|
|
|
|
| class DynamicCursorShapeConfig(CursorShapeConfig): |
| def __init__( |
| self, get_cursor_shape_config: Callable[[], AnyCursorShapeConfig] |
| ) -> None: |
| self.get_cursor_shape_config = get_cursor_shape_config |
|
|
| def get_cursor_shape(self, application: Application[Any]) -> CursorShape: |
| return to_cursor_shape_config(self.get_cursor_shape_config()).get_cursor_shape( |
| application |
| ) |
|
|
|
|
| def to_cursor_shape_config(value: AnyCursorShapeConfig) -> CursorShapeConfig: |
| """ |
| Take a `CursorShape` instance or `CursorShapeConfig` and turn it into a |
| `CursorShapeConfig`. |
| """ |
| if value is None: |
| return SimpleCursorShapeConfig() |
|
|
| if isinstance(value, CursorShape): |
| return SimpleCursorShapeConfig(value) |
|
|
| return value |
|
|