From 7cd502a8060540462bb1245dc12027cf67eb9114 Mon Sep 17 00:00:00 2001 From: serr Date: Wed, 5 Feb 2025 22:21:14 +0300 Subject: [PATCH] =?UTF-8?q?set=20num=20->=20=D0=B2=D0=BA=D0=BB=D1=8E=D1=87?= =?UTF-8?q?=D0=B8=D1=82=D1=8C=20=D0=BD=D1=83=D0=BC=D0=B5=D1=80=D0=B0=D1=86?= =?UTF-8?q?=D0=B8=D1=8E=20=D1=81=D1=82=D1=80=D0=BE=D0=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main.py | 3 ++- mvc/models.py | 14 ++++++++++++-- mvc/views.py | 38 +++++++++++++++++++++++++------------- 3 files changed, 39 insertions(+), 16 deletions(-) diff --git a/main.py b/main.py index 43d716d..9bac2d7 100644 --- a/main.py +++ b/main.py @@ -22,7 +22,8 @@ def main(): view.Render(model.displayBuffer, model.currentLine, model.currentCol, model.scrollX, model.scrollY, - model.ModeBar()) + model.ModeBar(), + model.showLineNumbers) symbolCode = view.curses_adapter.GetChar() diff --git a/mvc/models.py b/mvc/models.py index 8039b5f..76ecd07 100644 --- a/mvc/models.py +++ b/mvc/models.py @@ -14,6 +14,7 @@ class VimModel: def __init__(self, displayLinesCount: int, displayColsCount: int): self.displayLinesCount = displayLinesCount self.displayColsCount = displayColsCount + self.showLineNumbers = False self.displayBuffer = [] # буфер для хранения всех строк self.dump = [] self.currentLine = 0 # текущий индекс строки @@ -47,15 +48,22 @@ class VimModel: return modeBar def Scroll(self) -> None: + # Учитываем ширину нумерации строк (6 символов + 1 пробел) + line_number_width = 7 if self.showLineNumbers else 0 + # Вертикальная прокрутка if self.currentLine < self.scrollY: self.scrollY = self.currentLine elif self.currentLine >= self.scrollY + self.displayLinesCount - 1: self.scrollY = self.currentLine - self.displayLinesCount + 2 + # Горизонтальная прокрутка с учетом нумерации строк + # Видимая область для текста уменьшается на ширину нумерации строк + visible_text_width = self.displayColsCount - line_number_width + if self.currentCol < self.scrollX: self.scrollX = self.currentCol - elif self.currentCol >= self.scrollX + self.displayColsCount: - self.scrollX = self.currentCol - self.displayColsCount + 1 + elif self.currentCol >= self.scrollX + visible_text_width: + self.scrollX = self.currentCol - visible_text_width + 1 def InsertCommandSymbol(self, symbolCode: int) -> None: self.commandBuffer.append(chr(symbolCode)) @@ -174,6 +182,8 @@ class VimModel: return ReturnCode.SET_BASIC_MODE case "e!": self.displayBuffer = [sublist.copy() for sublist in self.dump] + case "set num": + self.showLineNumbers = not self.showLineNumbers case _: # Открывает файл filename if len(cmd) > 2 and cmd[:2] == 'o ': diff --git a/mvc/views.py b/mvc/views.py index 5538c1a..6459dbd 100644 --- a/mvc/views.py +++ b/mvc/views.py @@ -32,6 +32,8 @@ class CursesAdapter: self.cols = curses.COLS self.lines = curses.LINES curses.curs_set(1) # Make cursor visible + curses.start_color() + curses.init_pair(1, curses.COLOR_MAGENTA, curses.COLOR_BLACK) # Фиолетовый текст на черном фоне def Refresh(self) -> None: """Apply changes""" @@ -61,33 +63,43 @@ 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): + displayBuffer: list[list[str]], + currentLine: int, currentCol: int, + scrollX: int, scrollY: int, + modeBarData: str, + show_line_numbers: bool = False): """Отрисовка текущего состояния""" self.curses_adapter.screen.clear() + # Ширина нумерации строк (6 символов + 1 пробел) + line_number_width = 7 if show_line_numbers else 0 + # Отображение видимой части текста 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, '') + # Если нужно отображать номера строк, добавляем их перед текстом + if show_line_numbers: + line_number = f"{i + scrollY + 1:6} " # 6 символов на номер строки + # Выводим номер строки фиолетовым цветом + self.curses_adapter.screen.addstr(i, 0, line_number, curses.color_pair(1)) + + # Выводим текст с учетом прокрутки и ширины нумерации + visible_text_start = scrollX # Начало видимой части текста + visible_text_end = scrollX + self.curses_adapter.cols - line_number_width # Конец видимой части текста + visible_text = line[visible_text_start:visible_text_end] + self.curses_adapter.SetString(i, line_number_width, visible_text) else: self.curses_adapter.SetString(i, 0, '') # Обновление панели режима self.SetModeBar(modeBarData) - # Установка курсора с учетом прокрутки + # Установка курсора с учетом прокрутки и нумерации строк cursor_x = currentLine - scrollY - cursor_y = currentCol - scrollX + cursor_y = currentCol - scrollX + line_number_width # Проверка, чтобы курсор не вышел за пределы экрана if 0 <= cursor_x < self.curses_adapter.lines - 1 and 0 <= cursor_y < self.curses_adapter.cols: @@ -98,7 +110,7 @@ class VimView: def SetModeBar(self, modeBarData: str): """Print edit mode information panel""" if len(modeBarData) > self.curses_adapter.cols - 1: - scrollX = len(modeBarData)-self.curses_adapter.cols - self.curses_adapter.SetString(self.curses_adapter.lines - 1, 0, modeBarData[scrollX+1:]) + scrollX = len(modeBarData) - self.curses_adapter.cols + self.curses_adapter.SetString(self.curses_adapter.lines - 1, 0, modeBarData[scrollX + 1:]) else: self.curses_adapter.SetString(self.curses_adapter.lines - 1, 0, modeBarData)