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