сделал рендер через паттерн observer

master
serr 2025-02-10 20:57:28 +03:00
parent b72f27f1d4
commit 7b2bc07fc2
4 changed files with 70 additions and 29 deletions

View File

@ -9,7 +9,6 @@ def main():
adapter = CursesAdapter()
model, view = VimModel(adapter.lines, adapter.cols), VimView(adapter)
# start mode - navigation mode
strategy = NormalStrategy(model, view.curses_adapter)
controller = Controller(strategy)
@ -18,13 +17,11 @@ def main():
if len(sys.argv) > 1: model.LoadFile(sys.argv[1])
else: model.LoadFile("File not found but i create it"+str(tools.UnixSec())+".txt")
view.SetModel(model) # view subscribe model
while True:
view.Render(model.displayBuffer,
model.currentLine, model.currentCol,
model.scrollX, model.scrollY,
model.ModeBar(),
model.showLineNumbers)
model.notify()
symbolCode = view.curses_adapter.GetChar()
match controller.HandleInput(symbolCode):

View File

@ -23,9 +23,6 @@ class BaseStrategy(ABC):
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
@ -95,27 +92,38 @@ class NormalStrategy(BaseStrategy):
def HandleInput(self, symbolCode) -> int:
"""Обработка ввода пользователя"""
self.model.UpdateKeyLog(symbolCode)
result = self.handle_common_input(symbolCode)
if result != ReturnCode.CONTINUE:
self.model.Scroll()
return result
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_TWO_DOTS:
return ReturnCode.SET_COMMAND_MODE
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()
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_b:
self.model.ToWordStart()
case self.adapter.KEY_d:
if self.model.CombinationCheck("dd", 3): self.model.CutLine()
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_U: self.model.RecoverLine()
if self.model.CombinationCheck("yy", 3):
self.model.CopyLine()
case self.adapter.KEY_x:
self.model.DeleteNext()
case self.adapter.KEY_U:
self.model.RecoverLine()
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:
@ -124,7 +132,10 @@ class NormalStrategy(BaseStrategy):
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()
case self.adapter.KEY_PG_UP:
self.model.PageUp()
case self.adapter.KEY_PG_DOWN:
self.model.PageDown()
self.model.Scroll()
return ReturnCode.GOOD

View File

@ -1,4 +1,3 @@
import re
import tools
from enum import Enum
@ -12,6 +11,7 @@ class ReturnCode(Enum):
class VimModel:
def __init__(self, displayLinesCount: int, displayColsCount: int):
self.observers = []
self.displayLinesCount = displayLinesCount
self.displayColsCount = displayColsCount
self.showLineNumbers = True
@ -29,6 +29,16 @@ class VimModel:
self.commandBuffer = [] # буффер для команды
self.exchangeBuffer = [] # буффер обмена
def attach(self, observer):
self.observers.append(observer)
def detach(self, observer):
self.observers.remove(observer)
def notify(self):
for observer in self.observers:
observer.Update()
def InputAfterCursor(self) -> None:
self.inputAfterCursor = not self.inputAfterCursor

View File

@ -1,4 +1,6 @@
from abc import ABC, abstractmethod
import curses
import mvc.models
class CursesAdapter:
def __init__(self) -> None:
@ -32,6 +34,7 @@ class CursesAdapter:
self.screen.keypad(True)
self.cols = curses.COLS
self.lines = curses.LINES
curses.noecho()
curses.curs_set(1) # Make cursor visible
curses.start_color()
curses.init_pair(1, curses.COLOR_BLUE, curses.COLOR_BLACK) # Фиолетовый текст на черном фоне
@ -64,10 +67,30 @@ class CursesAdapter:
"""Wait users input"""
return self.screen.getch()
class Observer:
@abstractmethod
def Update(self):
pass
class VimView:
class VimView(Observer):
def __init__(self, adapter: CursesAdapter) -> None:
self.curses_adapter = adapter
self.model = None
def SetModel(self, model: mvc.models.VimModel):
self.model = model
model.attach(self)
def Update(self):
self.Render(
self.model.displayBuffer,
self.model.currentLine,
self.model.currentCol,
self.model.scrollX,
self.model.scrollY,
self.model.ModeBar(),
self.model.showLineNumbers
)
def Render(self,
displayBuffer: list[list[str]],