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

1from __future__ import annotations 

2 

3from abc import ABC, abstractmethod 

4from enum import Enum 

5from typing import TYPE_CHECKING, Any, Callable, Union 

6 

7from prompt_toolkit.enums import EditingMode 

8from prompt_toolkit.key_binding.vi_state import InputMode 

9 

10if TYPE_CHECKING: 

11 from .application import Application 

12 

13__all__ = [ 

14 "CursorShape", 

15 "CursorShapeConfig", 

16 "SimpleCursorShapeConfig", 

17 "ModalCursorShapeConfig", 

18 "DynamicCursorShapeConfig", 

19 "to_cursor_shape_config", 

20] 

21 

22 

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" 

33 

34 BLOCK = "BLOCK" 

35 BEAM = "BEAM" 

36 UNDERLINE = "UNDERLINE" 

37 BLINKING_BLOCK = "BLINKING_BLOCK" 

38 BLINKING_BEAM = "BLINKING_BEAM" 

39 BLINKING_UNDERLINE = "BLINKING_UNDERLINE" 

40 

41 

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 """ 

48 

49 

50AnyCursorShapeConfig = Union[CursorShape, CursorShapeConfig, None] 

51 

52 

53class SimpleCursorShapeConfig(CursorShapeConfig): 

54 """ 

55 Always show the given cursor shape. 

56 """ 

57 

58 def __init__(self, cursor_shape: CursorShape = CursorShape._NEVER_CHANGE) -> None: 

59 self.cursor_shape = cursor_shape 

60 

61 def get_cursor_shape(self, application: Application[Any]) -> CursorShape: 

62 return self.cursor_shape 

63 

64 

65class ModalCursorShapeConfig(CursorShapeConfig): 

66 """ 

67 Show cursor shape according to the current input mode. 

68 """ 

69 

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 

76 

77 # Default 

78 return CursorShape.BLOCK 

79 

80 

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 

86 

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 ) 

91 

92 

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() 

100 

101 if isinstance(value, CursorShape): 

102 return SimpleCursorShapeConfig(value) 

103 

104 return value