(stdscr, initial_text)
| 165 | # --- curses UI components --- |
| 166 | |
| 167 | def curses_editor(stdscr, initial_text): |
| 168 | curses.curs_set(1) |
| 169 | stdscr.clear() |
| 170 | h, w = stdscr.getmaxyx() |
| 171 | lines = initial_text.split('\n') if initial_text else [''] |
| 172 | cursor_y, cursor_x = 0, 0 |
| 173 | while True: |
| 174 | stdscr.erase() |
| 175 | title = ' Nano-like editor — Ctrl+X save, Ctrl+C cancel ' |
| 176 | stdscr.attron(curses.A_REVERSE) |
| 177 | centered_addstr(stdscr, 0, title[:w-1]) |
| 178 | stdscr.attroff(curses.A_REVERSE) |
| 179 | max_display = h - 4 |
| 180 | start = 0 |
| 181 | if cursor_y >= max_display: |
| 182 | start = cursor_y - max_display + 1 |
| 183 | for idx in range(start, min(start + max_display, len(lines))): |
| 184 | ln = lines[idx] |
| 185 | try: |
| 186 | stdscr.addstr(2 + idx - start, 2, ln[:w-4]) |
| 187 | except Exception: |
| 188 | pass |
| 189 | status = f"Ln {cursor_y+1}, Col {cursor_x+1} — Ctrl+X=save" |
| 190 | centered_addstr(stdscr, h-2, status[:w-1]) |
| 191 | try: |
| 192 | stdscr.move(2 + cursor_y - start, 2 + cursor_x) |
| 193 | except Exception: |
| 194 | pass |
| 195 | stdscr.refresh() |
| 196 | ch = stdscr.getch() |
| 197 | if ch == 24: # Ctrl+X |
| 198 | curses.curs_set(0) |
| 199 | return '\n'.join(lines) |
| 200 | elif ch in (3,): # Ctrl+C |
| 201 | curses.curs_set(0) |
| 202 | return None |
| 203 | elif ch in (curses.KEY_BACKSPACE, 127, 8): |
| 204 | if cursor_x > 0: |
| 205 | lines[cursor_y] = lines[cursor_y][:cursor_x-1] + lines[cursor_y][cursor_x:] |
| 206 | cursor_x -= 1 |
| 207 | else: |
| 208 | if cursor_y > 0: |
| 209 | prev = lines[cursor_y-1] |
| 210 | cur = lines.pop(cursor_y) |
| 211 | cursor_x = len(prev) |
| 212 | lines[cursor_y-1] = prev + cur |
| 213 | cursor_y -= 1 |
| 214 | elif ch == curses.KEY_LEFT: |
| 215 | if cursor_x > 0: |
| 216 | cursor_x -= 1 |
| 217 | elif cursor_y > 0: |
| 218 | cursor_y -= 1 |
| 219 | cursor_x = len(lines[cursor_y]) |
| 220 | elif ch == curses.KEY_RIGHT: |
| 221 | if cursor_x < len(lines[cursor_y]): |
| 222 | cursor_x += 1 |
| 223 | elif cursor_y < len(lines)-1: |
| 224 | cursor_y += 1 |
no test coverage detected