python curses как создать меню выбора файлов и директорий?
пытаюсь сделать простейшее меню для выбора файлов и перемещения по директориям но из-за моей неопытности прошу помощи.
- я хочу сделать вывод папок и файлов(большие директории просто не отгружаются и curses выдает исключения)
- нормальное открытие папок(при попытке открыть некоторые папки curses бросает исключение addstr поэтому даже непонятно изза чего ошибка)
- скроллинг(крутит за рамки вывода)
- корневая директория(..) может появится даже там где назад уже просто некуда переходить
- переход по папкам мне кажется неудачным возможно можно сделать это более правильным способом подскажите как можно исправить эти недочёты?
import curses
import os
class FileExplorer:
def __init__(self, stdscr):
self.stdscr = stdscr
self.current_dir = os.getcwd()
self.menu = os.listdir(self.current_dir)
self.menu.insert(0, "..")
self.current_row = 0
self.start_row = 0
self.end_row = min(len(self.menu), curses.LINES - 1)
def draw_menu(self):
self.stdscr.clear()
h, w = self.stdscr.getmaxyx()
for idx, row in enumerate(self.menu[self.start_row:self.end_row]):
x = w // 2 - len(row) // 2
y = h // 2 - len(self.menu) // 2 + idx
if idx + self.start_row == self.current_row:
self.stdscr.attron(curses.color_pair(1))
self.stdscr.addstr(y, x, row)
self.stdscr.attroff(curses.color_pair(1))
else:
self.stdscr.addstr(y, x, row)
self.stdscr.refresh()
def handle_input(self):
key = self.stdscr.getch()
if key in [curses.KEY_UP, ord('k')]:
self.current_row -= 1
self.current_row %= len(self.menu)
self.scroll_up()
elif key in [curses.KEY_DOWN, ord('j')]:
self.current_row += 1
self.current_row %= len(self.menu)
self.scroll_down()
elif key == curses.KEY_PPAGE: # Page Up
self.scroll_up()
elif key == curses.KEY_NPAGE: # Page Down
self.scroll_down()
elif key in [curses.KEY_ENTER, 10, 13]:
selected_item = self.menu[self.current_row]
path = os.path.join(self.current_dir, selected_item)
if selected_item == "..":
self.current_dir = os.path.dirname(self.current_dir)
elif os.path.isdir(path):
self.current_dir = path
self.menu = os.listdir(self.current_dir)
self.menu.insert(0, "..")
self.current_row = 0
self.scroll_to_top()
return True
def scroll_up(self):
if self.current_row < self.start_row:
self.start_row = self.current_row
self.end_row = self.start_row + curses.LINES - 1
elif self.current_row == self.start_row:
self.start_row -= 1
self.end_row -= 1
def scroll_down(self):
if self.current_row > self.end_row - 1:
self.end_row = self.current_row + 1
self.start_row = self.end_row - curses.LINES + 1
elif self.current_row == self.end_row - 1:
self.start_row += 1
self.end_row += 1
def scroll_to_top(self):
self.start_row = 0
self.end_row = min(len(self.menu), curses.LINES - 1)
def run(self):
curses.curs_set(0)
self.stdscr.keypad(1)
while True:
self.draw_menu()
if not self.handle_input():
break
def main(stdscr):
curses.use_default_colors()
curses.init_pair(1, curses.COLOR_BLACK, curses.COLOR_WHITE)
explorer = FileExplorer(stdscr)
explorer.run()
if __name__ == '__main__':
curses.wrapper(main)