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

126 lines
5.3 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.

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