VIM-like-text-editor/mvc/models.py

168 lines
7.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

from enum import Enum
class ReturnCode(Enum):
GOOD = -101
EXIT_CODE = -100
SET_BASIC_MODE = -99
SET_COMMAND_MODE = -98
SET_EDIT_MODE = -97
CONTINUE = -96
class VimModel:
def __init__(self, displayLines: int, displayCols: int):
self.displayLines = displayLines
self.displayCols = displayCols
self.displayBuffer = [] # буфер для хранения всех строк
self.currentLine = 0 # текущий индекс строки
self.currentCol = 0 # текущий индекс колонки
self.scrollY = 0 # вертикальная прокрутка
self.scrollX = 0 # горизонтальная прокрутка
self.file_path = "" # путь к файлу
self.mode = ""
self.commandBuffer = [] # буффер для команды
def ModeBar(self) -> str:
modeBar = f"MODE: {self.mode} | FILE: {self.file_path} | LINE: {self.currentLine+1}/{len(self.displayBuffer)}"
if self.mode == "COMMAND":
modeBar += f" | COMMAND BUFFER: {''.join(self.commandBuffer)}"
return modeBar
def Scroll(self, displayLines: int, displayCols: int) -> None:
if self.currentLine < self.scrollY:
self.scrollY = self.currentLine
elif self.currentLine >= self.scrollY + displayLines - 1:
self.scrollY = self.currentLine - displayLines + 2
if self.currentCol < self.scrollX:
self.scrollX = self.currentCol
elif self.currentCol >= self.scrollX + displayCols:
self.scrollX = self.currentCol - displayCols + 1
def InsertCommandSymbol(self, symbolCode: int) -> None:
self.commandBuffer.append(chr(symbolCode))
def InsertSymbol(self, symbolCode: int) -> None:
if self.currentCol <= len(self.displayBuffer[self.currentLine]): # проверяем, не превышает ли индекс колонки длину строки
self.displayBuffer[self.currentLine].insert(self.currentCol, chr(symbolCode))
self.currentCol += 1
def MoveToPositionWithScroll(self, position: int) -> None:
"""
Перемещает курсор в указанную позицию в текущей строке
и корректирует прокрутку, если это необходимо.
"""
line_length = len(self.displayBuffer[self.currentLine])
self.currentCol = max(0, min(position, line_length))
# Корректируем прокрутку, если курсор выходит за пределы видимой области
if self.currentCol < self.scrollX:
self.scrollX = self.currentCol # Прокрутка влево
elif self.currentCol >= self.scrollX + self.displayCols:
self.scrollX = self.currentCol - self.displayCols + 1 # Прокрутка вправо
def EnterCommand(self):
"""Обработка введенной команды"""
cmd = ''.join(self.commandBuffer)
self.commandBuffer.clear()
match cmd:
case "$":
self.MoveToPositionWithScroll(len(self.displayBuffer[self.currentLine])) # Перемещение в конец строки
return ReturnCode.GOOD
case "^" | "0":
self.MoveToPositionWithScroll(0) # Перемещение в начало строки
return ReturnCode.GOOD
case "q":
return ReturnCode.EXIT_CODE
case "i":
return ReturnCode.SET_EDIT_MODE
case "S":
self.MoveToPositionWithScroll(0)
self.displayBuffer[self.currentLine] = []
return ReturnCode.SET_EDIT_MODE
case "RIGHT":
self.MoveToPositionWithScroll(self.currentCol + 1)
return ReturnCode.GOOD
case "LEFT":
self.MoveToPositionWithScroll(self.currentCol - 1)
return ReturnCode.GOOD
case "UP":
if self.currentLine > 0:
self.currentLine -= 1
if self.currentCol > len(self.displayBuffer[self.currentLine]):
self.MoveToPositionWithScroll(len(self.displayBuffer[self.currentLine]))
return ReturnCode.GOOD
case "DOWN":
if self.currentLine < len(self.displayBuffer) - 1:
self.currentLine += 1
if self.currentCol > len(self.displayBuffer[self.currentLine]):
self.MoveToPositionWithScroll(len(self.displayBuffer[self.currentLine]))
return ReturnCode.GOOD
def Enter(self) -> None:
# Разделяем текущую строку на две части
new_line = self.displayBuffer[self.currentLine][self.currentCol:]
self.displayBuffer[self.currentLine] = self.displayBuffer[self.currentLine][:self.currentCol]
self.currentLine += 1 # Переходим на следующую строку
self.displayBuffer.insert(self.currentLine, new_line) # Вставляем новую строку
self.currentCol = 0 # Сбрасываем индекс колонки
def BackspaceCommand(self) -> None:
if len(self.commandBuffer) > 0:
self.commandBuffer.pop()
def Backspace(self) -> None:
if self.currentCol > 0: # Если символ существует в текущей строке
self.currentCol -= 1
del self.displayBuffer[self.currentLine][self.currentCol] # Удаляем символ
elif self.currentLine > 0: # Если текущая строка не первая
# Объединяем текущую строку с предыдущей
prev_line_length = len(self.displayBuffer[self.currentLine - 1])
self.displayBuffer[self.currentLine - 1].extend(self.displayBuffer[self.currentLine])
del self.displayBuffer[self.currentLine]
self.currentLine -= 1
self.currentCol = prev_line_length # Переходим в конец предыдущей строки
def MoveLeft(self) -> None:
if self.currentCol > 0:
self.currentCol -= 1
elif self.currentLine > 0:
self.currentLine -= 1
self.currentCol = len(self.displayBuffer[self.currentLine])
def MoveRight(self) -> None:
if self.currentCol < len(self.displayBuffer[self.currentLine]):
self.currentCol += 1
elif self.currentLine < len(self.displayBuffer) - 1:
self.currentLine += 1
self.currentCol = 0
def MoveUp(self) -> None:
if self.currentLine > 0:
self.currentLine -= 1
self.currentCol = min(self.currentCol, len(self.displayBuffer[self.currentLine]))
def MoveDown(self) -> None:
if self.currentLine < len(self.displayBuffer) - 1:
self.currentLine += 1
self.currentCol = min(self.currentCol, len(self.displayBuffer[self.currentLine]))
def LoadFile(self, file_path) -> None:
"""Загрузка файла для редактирования"""
self.file_path = file_path
try:
with open(file_path, "r") as file:
self.displayBuffer = [list(line.rstrip('\n')) for line in file.readlines()]
except FileNotFoundError:
print(f"File {file_path} not found. Starting with empty buffer.")
self.displayBuffer = []
def SaveFile(self) -> None:
"""Сохранение файла"""
try:
with open(self.file_path, "w") as file:
for line in self.displayBuffer:
file.write(''.join(line) + '\n')
print(f"File {self.file_path} saved successfully.")
except Exception as e:
print(f"Error saving file: {str(e)}")