пофиксил баги с переходом в конец/начало длинных строк + удаления длинной строки когда scrollX большой
parent
6012c2f690
commit
94bbccde99
10
main.py
10
main.py
|
@ -1,13 +1,15 @@
|
||||||
from mvc.models import VimModel
|
from mvc.models import VimModel
|
||||||
from mvc.views import VimView
|
from mvc.views import VimView, CursesAdapter
|
||||||
from mvc.controllers import Controller, ReturnCode
|
from mvc.controllers import Controller, ReturnCode
|
||||||
from mvc.controllers import EditStrategy, CommandStrategy, NormalStrategy
|
from mvc.controllers import EditStrategy, CommandStrategy, NormalStrategy
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
model, view = VimModel(), VimView()
|
adapter = CursesAdapter()
|
||||||
|
model = VimModel(adapter.lines, adapter.cols)
|
||||||
|
view = VimView(adapter)
|
||||||
|
|
||||||
# начальный режим - редактирование
|
# start mode - navigation mode
|
||||||
strategy = NormalStrategy(model, view.curses_adapter)
|
strategy = NormalStrategy(model, adapter)
|
||||||
controller = Controller(strategy)
|
controller = Controller(strategy)
|
||||||
|
|
||||||
# Загрузка файла для редактирования
|
# Загрузка файла для редактирования
|
||||||
|
|
|
@ -9,7 +9,9 @@ class ReturnCode(Enum):
|
||||||
CONTINUE = -96
|
CONTINUE = -96
|
||||||
|
|
||||||
class VimModel:
|
class VimModel:
|
||||||
def __init__(self):
|
def __init__(self, displayLines: int, displayCols: int):
|
||||||
|
self.displayLines = displayLines
|
||||||
|
self.displayCols = displayCols
|
||||||
self.displayBuffer = [] # буфер для хранения всех строк
|
self.displayBuffer = [] # буфер для хранения всех строк
|
||||||
self.currentLine = 0 # текущий индекс строки
|
self.currentLine = 0 # текущий индекс строки
|
||||||
self.currentCol = 0 # текущий индекс колонки
|
self.currentCol = 0 # текущий индекс колонки
|
||||||
|
@ -44,19 +46,59 @@ class VimModel:
|
||||||
self.displayBuffer[self.currentLine].insert(self.currentCol, chr(symbolCode))
|
self.displayBuffer[self.currentLine].insert(self.currentCol, chr(symbolCode))
|
||||||
self.currentCol += 1
|
self.currentCol += 1
|
||||||
|
|
||||||
|
def MoveToLineStart(self) -> None:
|
||||||
|
"""Переместить курсор в начало строки и сбросить прокрутку"""
|
||||||
|
self.currentCol = 0
|
||||||
|
self.scrollX = 0 # Сброс горизонтальной прокрутки
|
||||||
|
|
||||||
|
def MoveToLineEnd(self) -> None:
|
||||||
|
"""Переместить курсор в конец строки с учетом прокрутки"""
|
||||||
|
line_length = len(self.displayBuffer[self.currentLine])
|
||||||
|
self.currentCol = line_length
|
||||||
|
|
||||||
|
# Если строка длиннее экрана, корректируем прокрутку
|
||||||
|
if line_length > self.displayCols:
|
||||||
|
self.scrollX = max(0, line_length - self.displayCols + 1)
|
||||||
|
|
||||||
def EnterCommand(self):
|
def EnterCommand(self):
|
||||||
|
"""Обработка введенной команды"""
|
||||||
cmd = ''.join(self.commandBuffer)
|
cmd = ''.join(self.commandBuffer)
|
||||||
self.commandBuffer.clear()
|
self.commandBuffer.clear()
|
||||||
match cmd:
|
match cmd:
|
||||||
case "$":
|
case "$":
|
||||||
self.currentCol = len(self.displayBuffer[self.currentLine])
|
self.MoveToLineEnd() # Перемещение в конец строки
|
||||||
|
return ReturnCode.GOOD
|
||||||
|
case "^" | "0":
|
||||||
|
self.MoveToLineStart() # Перемещение в начало строки
|
||||||
return ReturnCode.GOOD
|
return ReturnCode.GOOD
|
||||||
case "q":
|
case "q":
|
||||||
return ReturnCode.EXIT_CODE
|
return ReturnCode.EXIT_CODE
|
||||||
|
case "i":
|
||||||
|
return ReturnCode.SET_EDIT_MODE
|
||||||
case "S":
|
case "S":
|
||||||
self.currentCol = 0
|
self.MoveToLineStart()
|
||||||
self.displayBuffer[self.currentLine] = []
|
self.displayBuffer[self.currentLine] = []
|
||||||
return ReturnCode.SET_EDIT_MODE
|
return ReturnCode.SET_EDIT_MODE
|
||||||
|
case "RIGHT":
|
||||||
|
if self.currentCol < len(self.displayBuffer[self.currentLine]):
|
||||||
|
self.currentCol += 1
|
||||||
|
return ReturnCode.GOOD
|
||||||
|
case "LEFT":
|
||||||
|
if self.currentCol > 0:
|
||||||
|
self.currentCol -= 1
|
||||||
|
return ReturnCode.GOOD
|
||||||
|
case "UP":
|
||||||
|
if self.currentLine > 0:
|
||||||
|
self.currentLine -= 1
|
||||||
|
if self.currentCol > len(self.displayBuffer[self.currentLine]):
|
||||||
|
self.currentCol = 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.currentCol = len(self.displayBuffer[self.currentLine])
|
||||||
|
return ReturnCode.GOOD
|
||||||
|
|
||||||
def Enter(self) -> None:
|
def Enter(self) -> None:
|
||||||
# Разделяем текущую строку на две части
|
# Разделяем текущую строку на две части
|
||||||
|
|
79
mvc/views.py
79
mvc/views.py
|
@ -1,39 +1,5 @@
|
||||||
import curses
|
import curses
|
||||||
|
|
||||||
class VimView:
|
|
||||||
def __init__(self) -> None:
|
|
||||||
self.curses_adapter = CursesAdapter()
|
|
||||||
|
|
||||||
def Render(self,
|
|
||||||
displayBuffer: list[list[str]],
|
|
||||||
currentLine: int, currentCol: int,
|
|
||||||
scrollX: int, scrollY: int,
|
|
||||||
modeBarData: str):
|
|
||||||
"""Отрисовка текущего состояния"""
|
|
||||||
|
|
||||||
self.curses_adapter.screen.clear()
|
|
||||||
|
|
||||||
# display visible part of text
|
|
||||||
for i in range(self.curses_adapter.lines - 1):
|
|
||||||
if i + scrollY < len(displayBuffer):
|
|
||||||
line = ''.join(displayBuffer[i + scrollY])
|
|
||||||
if scrollX < len(line):
|
|
||||||
self.curses_adapter.SetString(i, 0, line[scrollX:scrollX + self.curses_adapter.cols])
|
|
||||||
else:
|
|
||||||
self.curses_adapter.SetString(i, 0, '')
|
|
||||||
else:
|
|
||||||
self.curses_adapter.SetString(i, 0, '')
|
|
||||||
|
|
||||||
# update mode bar
|
|
||||||
self.SetModeBar(modeBarData)
|
|
||||||
# update cursor
|
|
||||||
self.curses_adapter.SetCursor(currentLine - scrollY, currentCol - scrollX)
|
|
||||||
self.curses_adapter.Refresh()
|
|
||||||
|
|
||||||
def SetModeBar(self, modeBarData: str):
|
|
||||||
"""Print edit mode information panel"""
|
|
||||||
self.curses_adapter.SetString(self.curses_adapter.lines - 1, 0, modeBarData)
|
|
||||||
|
|
||||||
class CursesAdapter:
|
class CursesAdapter:
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.KEY_LEFT = curses.KEY_LEFT
|
self.KEY_LEFT = curses.KEY_LEFT
|
||||||
|
@ -79,4 +45,47 @@ class CursesAdapter:
|
||||||
|
|
||||||
def GetChar(self) -> int:
|
def GetChar(self) -> int:
|
||||||
"""Wait users input"""
|
"""Wait users input"""
|
||||||
return self.screen.getch()
|
return self.screen.getch()
|
||||||
|
|
||||||
|
|
||||||
|
class VimView:
|
||||||
|
def __init__(self, adapter: CursesAdapter) -> None:
|
||||||
|
self.curses_adapter = adapter
|
||||||
|
|
||||||
|
|
||||||
|
def Render(self,
|
||||||
|
displayBuffer: list[list[str]],
|
||||||
|
currentLine: int, currentCol: int,
|
||||||
|
scrollX: int, scrollY: int,
|
||||||
|
modeBarData: str):
|
||||||
|
"""Отрисовка текущего состояния"""
|
||||||
|
|
||||||
|
self.curses_adapter.screen.clear()
|
||||||
|
|
||||||
|
# Отображение видимой части текста
|
||||||
|
for i in range(self.curses_adapter.lines - 1):
|
||||||
|
if i + scrollY < len(displayBuffer):
|
||||||
|
line = ''.join(displayBuffer[i + scrollY])
|
||||||
|
if scrollX < len(line):
|
||||||
|
self.curses_adapter.SetString(i, 0, line[scrollX:scrollX + self.curses_adapter.cols])
|
||||||
|
else:
|
||||||
|
self.curses_adapter.SetString(i, 0, '')
|
||||||
|
else:
|
||||||
|
self.curses_adapter.SetString(i, 0, '')
|
||||||
|
|
||||||
|
# Обновление панели режима
|
||||||
|
self.SetModeBar(modeBarData)
|
||||||
|
|
||||||
|
# Установка курсора с учетом прокрутки
|
||||||
|
cursor_x = currentLine - scrollY
|
||||||
|
cursor_y = currentCol - scrollX
|
||||||
|
|
||||||
|
# Проверка, чтобы курсор не вышел за пределы экрана
|
||||||
|
if 0 <= cursor_x < self.curses_adapter.lines - 1 and 0 <= cursor_y < self.curses_adapter.cols:
|
||||||
|
self.curses_adapter.SetCursor(cursor_x, cursor_y)
|
||||||
|
|
||||||
|
self.curses_adapter.Refresh()
|
||||||
|
|
||||||
|
def SetModeBar(self, modeBarData: str):
|
||||||
|
"""Print edit mode information panel"""
|
||||||
|
self.curses_adapter.SetString(self.curses_adapter.lines - 1, 0, modeBarData)
|
||||||
|
|
Loading…
Reference in New Issue