Extract text backend into separate module

This commit is contained in:
Darren Burns
2022-05-13 16:46:08 +01:00
parent 23cd37fa9a
commit 5f09229ffa
2 changed files with 97 additions and 95 deletions

View File

@@ -0,0 +1,95 @@
from __future__ import annotations
from dataclasses import dataclass
@dataclass
class TextEditorBackend:
content: str = ""
cursor_index: int = 0
def set_content(self, text: str):
self.content = text
def delete_back(self) -> bool:
"""Delete the character behind the cursor
Returns: True if the text content was modified. False otherwise.
"""
if self.cursor_index == 0:
return False
new_text = (
self.content[: self.cursor_index - 1] + self.content[self.cursor_index :]
)
self.content = new_text
self.cursor_index = max(0, self.cursor_index - 1)
return True
def delete_forward(self) -> bool:
"""Delete the character in front of the cursor
Returns: True if the text content was modified. False otherwise.
"""
if self.cursor_index == len(self.content):
return False
new_text = (
self.content[: self.cursor_index] + self.content[self.cursor_index + 1 :]
)
self.content = new_text
return True
def cursor_left(self) -> bool:
"""Move the cursor 1 character left in the text"""
previous_index = self.cursor_index
new_index = max(0, previous_index - 1)
self.cursor_index = new_index
return previous_index != new_index
def cursor_right(self) -> bool:
"""Move the cursor 1 character right in the text"""
previous_index = self.cursor_index
new_index = min(len(self.content), previous_index + 1)
self.cursor_index = new_index
return previous_index != new_index
def query_cursor_left(self) -> bool:
"""Check if the cursor can move 1 character left in the text"""
previous_index = self.cursor_index
new_index = max(0, previous_index - 1)
return previous_index != new_index
def query_cursor_right(self) -> bool:
"""Check if the cursor can move right"""
previous_index = self.cursor_index
new_index = min(len(self.content), previous_index + 1)
return previous_index != new_index
def cursor_text_start(self) -> bool:
if self.cursor_index == 0:
return False
self.cursor_index = 0
return True
def cursor_text_end(self) -> bool:
text_length = len(self.content)
if self.cursor_index == text_length:
return False
self.cursor_index = text_length
return True
def insert_at_cursor(self, text: str) -> bool:
new_text = (
self.content[: self.cursor_index] + text + self.content[self.cursor_index :]
)
self.content = new_text
self.cursor_index = min(len(self.content), self.cursor_index + 1)
return True
def get_range(self, start: int, end: int) -> str:
"""Return the text between 2 indices. Useful for previews/views into
a subset of the content e.g. scrollable single-line input fields"""
return self.content[start:end]

View File

@@ -1,13 +1,12 @@
from __future__ import annotations
from dataclasses import dataclass
from rich.console import RenderableType
from rich.padding import Padding
from rich.style import Style
from rich.text import Text
from textual import events
from textual._text_backend import TextEditorBackend
from textual._types import MessageTarget
from textual.app import ComposeResult
from textual.geometry import Size
@@ -16,98 +15,6 @@ from textual.message import Message
from textual.widget import Widget
@dataclass
class TextEditorBackend:
content: str = ""
cursor_index: int = 0
def set_content(self, text: str):
self.content = text
def delete_back(self) -> bool:
"""Delete the character behind the cursor
Returns: True if the text content was modified. False otherwise.
"""
if self.cursor_index == 0:
return False
new_text = (
self.content[: self.cursor_index - 1] + self.content[self.cursor_index :]
)
self.content = new_text
self.cursor_index = max(0, self.cursor_index - 1)
return True
def delete_forward(self) -> bool:
"""Delete the character in front of the cursor
Returns: True if the text content was modified. False otherwise.
"""
if self.cursor_index == len(self.content):
return False
new_text = (
self.content[: self.cursor_index] + self.content[self.cursor_index + 1 :]
)
self.content = new_text
return True
def cursor_left(self) -> bool:
"""Move the cursor 1 character left in the text"""
previous_index = self.cursor_index
new_index = max(0, previous_index - 1)
self.cursor_index = new_index
return previous_index != new_index
def cursor_right(self) -> bool:
"""Move the cursor 1 character right in the text"""
previous_index = self.cursor_index
new_index = min(len(self.content), previous_index + 1)
self.cursor_index = new_index
return previous_index != new_index
def query_cursor_left(self) -> bool:
"""Check if the cursor can move 1 character left in the text"""
previous_index = self.cursor_index
new_index = max(0, previous_index - 1)
return previous_index != new_index
def query_cursor_right(self) -> bool:
"""Check if the cursor can move right"""
previous_index = self.cursor_index
new_index = min(len(self.content), previous_index + 1)
return previous_index != new_index
def cursor_text_start(self) -> bool:
if self.cursor_index == 0:
return False
self.cursor_index = 0
return True
def cursor_text_end(self) -> bool:
text_length = len(self.content)
if self.cursor_index == text_length:
return False
self.cursor_index = text_length
return True
def insert_at_cursor(self, text: str) -> bool:
new_text = (
self.content[: self.cursor_index] + text + self.content[self.cursor_index :]
)
self.content = new_text
self.cursor_index = min(len(self.content), self.cursor_index + 1)
return True
def get_range(self, start: int, end: int) -> str:
"""Return the text between 2 indices. Useful for previews/views into
a subset of the content e.g. scrollable single-line input fields"""
return self.content[start:end]
class TextWidgetBase(Widget):
STOP_PROPAGATE = set()
@@ -184,7 +91,7 @@ class TextInput(TextWidgetBase, can_focus=True):
}
TextInput:hover {
background: $primary-darken-1;
background: $primary-darken-2;
}
TextInput:focus {