import tools from abc import ABC, abstractmethod from mvc.views import CursesAdapter from mvc.models import VimModel, ReturnCode def isAscii(symbolCode: int) -> bool: return 32 <= symbolCode <= 126 class BaseStrategy(ABC): def __init__(self, model: VimModel, adapter: CursesAdapter, mode: str): self.model = model self.adapter = adapter self.mode = model.mode = mode def handle_common_input(self, symbolCode: int) -> int: """Обработка общих для всех стратегий действий""" match symbolCode: case self.adapter.KEY_ESCAPE: return ReturnCode.SET_BASIC_MODE case self.adapter.KEY_LEFT: self.model.MoveLeft() case self.adapter.KEY_RIGHT: self.model.MoveRight() case self.adapter.KEY_UP: self.model.MoveUp() case self.adapter.KEY_DOWN: self.model.MoveDown() case self.adapter.KEY_CTRL_S: self.model.SaveFile() case _: return ReturnCode.CONTINUE # Не обрабатываем, передаем дальше self.model.Scroll() return ReturnCode.GOOD @abstractmethod def HandleInput(self, symbolCode: int) -> int: pass class Controller: def __init__(self, strategy: BaseStrategy): self.strategy = strategy def SetStrategy(self, strategy: BaseStrategy): self.strategy = strategy def HandleInput(self, symbolCode: int): return self.strategy.HandleInput(symbolCode) class CommandStrategy(BaseStrategy): """Режим ввода команд""" def __init__(self, model: VimModel, adapter: CursesAdapter): super().__init__(model, adapter, mode="COMMAND") def HandleInput(self, symbolCode) -> int: """Обработка ввода пользователя""" result = self.handle_common_input(symbolCode) if result != ReturnCode.CONTINUE: return result returnCode = ReturnCode.GOOD match symbolCode: case self.adapter.KEY_ENTER: returnCode = self.model.EnterCommand() case self.adapter.KEY_BACKSPACE_1 | self.adapter.KEY_BACKSPACE_2: self.model.BackspaceCommand() case _: if not isAscii(symbolCode): return ReturnCode.GOOD self.model.InsertCommandSymbol(symbolCode) self.model.Scroll() return returnCode class EditStrategy(BaseStrategy): """Режим редактирования""" def __init__(self, model: VimModel, adapter: CursesAdapter): super().__init__(model, adapter, mode="EDIT") def HandleInput(self, symbolCode) -> int: """Обработка ввода пользователя""" result = self.handle_common_input(symbolCode) if result != ReturnCode.CONTINUE: return result match symbolCode: case self.adapter.KEY_ENTER: self.model.Enter() case self.adapter.KEY_BACKSPACE_1 | self.adapter.KEY_BACKSPACE_2: self.model.Backspace() case _: if not isAscii(symbolCode): return ReturnCode.GOOD self.model.InsertSymbol(symbolCode) self.model.Scroll() return ReturnCode.GOOD class NormalStrategy(BaseStrategy): """Режим навигации""" def __init__(self, model: VimModel, adapter: CursesAdapter): super().__init__(model, adapter, mode="NORMAL") def HandleInput(self, symbolCode) -> int: """Обработка ввода пользователя""" self.model.UpdateKeyLog(symbolCode) match symbolCode: case self.adapter.KEY_TWO_DOTS: return ReturnCode.SET_COMMAND_MODE case self.adapter.KEY_LEFT: self.model.MoveLeft() case self.adapter.KEY_RIGHT: self.model.MoveRight() case self.adapter.KEY_UP: self.model.MoveUp() case self.adapter.KEY_DOWN: self.model.MoveDown() case self.adapter.KEY_CTRL_S: self.model.SaveFile() case self.adapter.KEY_NULL | self.adapter.KEY_XOR: self.model.ToLineStart() case self.adapter.KEY_DOLLAR: self.model.ToLineEnd() case self.adapter.KEY_p: self.model.Paste() case self.adapter.KEY_w: if self.model.CombinationCheck("diw", 3): self.model.DeleteWord() elif self.model.CombinationCheck("yw", 3): self.model.CopyWord() else: self.model.ToWordEnd() case self.adapter.KEY_b: self.model.ToWordStart() case self.adapter.KEY_d: if self.model.CombinationCheck("dd", 3): self.model.CutLine() case self.adapter.KEY_y: if self.model.CombinationCheck("yy", 3): self.model.CopyLine() case self.adapter.KEY_x: self.model.DeleteNext() case self.adapter.KEY_G: num, ind = tools.ExtracrtNumBeforeLastKey(''.join([chr(item[0]) for item in self.model.keyLog])) if num != None and ind != None: self.model.MoveToLine(num) else: self.model.ToFileEnd() case self.adapter.KEY_g: if self.model.CombinationCheck("gg", 3): self.model.ToFileStart() case self.adapter.KEY_PG_UP: self.model.PageUp() case self.adapter.KEY_PG_DOWN: self.model.PageDown() self.model.Scroll() return ReturnCode.GOOD