From c9d258cdfc89093d671ee0e7d417b80988ec8372 Mon Sep 17 00:00:00 2001 From: serr Date: Tue, 4 Feb 2025 13:06:54 +0300 Subject: [PATCH] first --- .gitignore | 5 ++ README.md | 1 + test.py | 173 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 179 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 test.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dd6d44a --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +example.txt +boost_python312-vc143-mt-x64-1_87.dll +mystring.pyd +views.py +__pycache__ \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..82eb11b --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +Простой консольный текстовый редактор по типу вима, написанный на Python в ходе лабораторной работы по ООП. \ No newline at end of file diff --git a/test.py b/test.py new file mode 100644 index 0000000..b2c5b17 --- /dev/null +++ b/test.py @@ -0,0 +1,173 @@ +import curses + +class CursesAdapter: + def __init__(self) -> None: + self.screen = curses.initscr() + self.screen.keypad(True) + self.cols = curses.COLS + self.lines = curses.LINES + # init color system + curses.start_color() + # green color pair + curses.init_pair(1, curses.COLOR_MAGENTA, curses.COLOR_BLACK) + curses.curs_set(1) # Make cursor visible + + def Refresh(self) -> None: + """Apply changes""" + self.screen.refresh() + + def Cleanup(self) -> None: + curses.endwin() + + def SetCursor(self, x: int, y: int): + """set cursor position (x, y)""" + self.screen.move(x, y) + + def SetChar(self, x: int, y: int, code: int): + """set char position (x, y)""" + self.screen.addch(x, y, code) + + def SetString(self, x: int, y: int, data: str): + """set string begin position (x, y)""" + self.screen.addstr(x, y, data) + + def GetChar(self) -> int: + """Wait users input""" + return self.screen.getch() + + def EditModeBar(self, currentLine, totalLines, fileName): + """Print edit mode information panel""" + self.screen.addstr(self.lines - 1, 0, ' ' * (self.cols - 1)) # Очистка строки + self.screen.addstr(self.lines - 1, 0, "FILE: ") + self.screen.addstr(fileName, curses.color_pair(1)) # Имя файла + self.screen.addstr(" | MODE:") + self.screen.addstr(" EDIT", curses.color_pair(1)) + self.screen.addstr(" | LINE: ") + self.screen.addstr(str(currentLine + 1), curses.color_pair(1)) + self.screen.addstr("/") + self.screen.addstr(str(totalLines), curses.color_pair(1)) # Общее количество строк + +def main(): + adapter = CursesAdapter() + + currentCol = 0 # текущий индекс колонки + currentLine = 0 # текущий индекс строки + scrollY = 0 # вертикальная прокрутка + scrollX = 0 # горизонтальная прокрутка + displayBuffer = [] # буфер для хранения всех строк + + mode = "EDIT" + + # Загрузка файла для редактирования + file_path = "example.txt" # Укажите путь к файлу + try: + with open(file_path, "r") as file: + displayBuffer = [list(line.rstrip('\n')) for line in file.readlines()] + except FileNotFoundError: + print(f"File {file_path} not found. Starting with empty buffer.") + + while True: + # Очистка экрана + adapter.screen.clear() + + # Отображение видимой части текста + for i in range(adapter.lines - 1): + if i + scrollY < len(displayBuffer): + line = ''.join(displayBuffer[i + scrollY]) + if scrollX < len(line): + adapter.SetString(i, 0, line[scrollX:scrollX + adapter.cols]) + else: + adapter.SetString(i, 0, '') + else: + adapter.SetString(i, 0, '') + + # Отображение панели режима + adapter.EditModeBar(currentLine, len(displayBuffer), file_path) + + # Установка курсора + adapter.SetCursor(currentLine - scrollY, currentCol - scrollX) + adapter.Refresh() + + # Ожидание ввода + if mode == "EDIT": + symbolCode = adapter.GetChar() + + if symbolCode == 27: # EXIT + break + + elif symbolCode == curses.KEY_LEFT: + if currentCol > 0: + currentCol -= 1 + elif currentLine > 0: + currentLine -= 1 + currentCol = len(displayBuffer[currentLine]) + + elif symbolCode == curses.KEY_RIGHT: + if currentCol < len(displayBuffer[currentLine]): + currentCol += 1 + elif currentLine < len(displayBuffer) - 1: + currentLine += 1 + currentCol = 0 + + elif symbolCode == curses.KEY_UP: + if currentLine > 0: + currentLine -= 1 + currentCol = min(currentCol, len(displayBuffer[currentLine])) + + elif symbolCode == curses.KEY_DOWN: + if currentLine < len(displayBuffer) - 1: + currentLine += 1 + currentCol = min(currentCol, len(displayBuffer[currentLine])) + + # BACKSPACE + elif symbolCode in (127, 8): # Backspace + if currentCol > 0: # Если символ существует в текущей строке + currentCol -= 1 + del displayBuffer[currentLine][currentCol] # Удаляем символ + elif currentLine > 0: # Если текущая строка не первая + # Объединяем текущую строку с предыдущей + prev_line_length = len(displayBuffer[currentLine - 1]) + displayBuffer[currentLine - 1].extend(displayBuffer[currentLine]) + del displayBuffer[currentLine] + currentLine -= 1 + currentCol = prev_line_length # Переходим в конец предыдущей строки + + # ENTER + elif symbolCode == 10: # Enter + # Разделяем текущую строку на две части + new_line = displayBuffer[currentLine][currentCol:] + displayBuffer[currentLine] = displayBuffer[currentLine][:currentCol] + currentLine += 1 # Переходим на следующую строку + displayBuffer.insert(currentLine, new_line) # Вставляем новую строку + currentCol = 0 # Сбрасываем индекс колонки + + # Сохранение файла (Ctrl+S) + elif symbolCode == 19: # Ctrl+S + try: + with open(file_path, "w") as file: + for line in displayBuffer: + file.write(''.join(line) + '\n') + adapter.screen.addstr(adapter.lines - 1, 0, f"File {file_path} saved successfully.") + except Exception as e: + adapter.screen.addstr(adapter.lines - 1, 0, f"Error saving file: {e}") + + else: + if currentCol <= len(displayBuffer[currentLine]): # проверяем, не превышает ли индекс колонки длину строки + displayBuffer[currentLine].insert(currentCol, chr(symbolCode)) + currentCol += 1 + + # Прокрутка экрана + if currentLine < scrollY: + scrollY = currentLine + elif currentLine >= scrollY + adapter.lines - 1: + scrollY = currentLine - adapter.lines + 2 + + if currentCol < scrollX: + scrollX = currentCol + elif currentCol >= scrollX + adapter.cols: + scrollX = currentCol - adapter.cols + 1 + + adapter.Cleanup() + +if __name__ == "__main__": + main() \ No newline at end of file