Add picker, refine things
This commit is contained in:
parent
511cd81acb
commit
74d64c9a47
4 changed files with 78 additions and 9 deletions
5
code.py
5
code.py
|
|
@ -1,5 +1,6 @@
|
|||
import editor
|
||||
import picker, editor
|
||||
try:
|
||||
editor.edit("code.py")
|
||||
filename = picker.pick_file()
|
||||
editor.edit(filename)
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
|
|
|
|||
2
dang.py
2
dang.py
|
|
@ -98,7 +98,7 @@ def wrapper(func, *args, **kwds):
|
|||
stdscr = Screen()
|
||||
try:
|
||||
_nonblocking()
|
||||
func(stdscr, *args, **kwds)
|
||||
return func(stdscr, *args, **kwds)
|
||||
finally:
|
||||
_blocking()
|
||||
stdscr.move(LINES-1, 0)
|
||||
|
|
|
|||
23
editor.py
23
editor.py
|
|
@ -1,4 +1,5 @@
|
|||
import dang as curses
|
||||
import os
|
||||
import sys
|
||||
import gc
|
||||
|
||||
|
|
@ -20,6 +21,13 @@ class MaybeDisableReload:
|
|||
|
||||
runtime.autoreload = self._old_autoreload
|
||||
|
||||
def os_exists(filename):
|
||||
try:
|
||||
os.stat(filename)
|
||||
return True
|
||||
except OSError:
|
||||
return False
|
||||
|
||||
def gc_mem_free_hint():
|
||||
if hasattr(gc, 'mem_free'):
|
||||
gc.collect()
|
||||
|
|
@ -172,15 +180,18 @@ def end(window, buffer, cursor):
|
|||
window.horizontal_scroll(cursor)
|
||||
|
||||
def editor(stdscr, filename):
|
||||
with open(filename) as f:
|
||||
buffer = Buffer(f.read().splitlines())
|
||||
if os_exists(filename):
|
||||
with open(filename) as f:
|
||||
buffer = Buffer(f.read().splitlines())
|
||||
else:
|
||||
buffer = Buffer([])
|
||||
|
||||
window = Window(curses.LINES - 1, curses.COLS - 1)
|
||||
cursor = Cursor()
|
||||
|
||||
stdscr.erase()
|
||||
|
||||
img = [''] * window.n_rows
|
||||
img = [''] * curses.LINES
|
||||
def setline(row, line):
|
||||
if img[row] == line:
|
||||
return
|
||||
|
|
@ -188,7 +199,7 @@ def editor(stdscr, filename):
|
|||
stdscr.addstr(row, 0, line)
|
||||
|
||||
while True:
|
||||
for row, line in enumerate(buffer[window.row:window.row + window.n_rows-1]):
|
||||
for row, line in enumerate(buffer[window.row:window.row + window.n_rows]):
|
||||
if row == cursor.row - window.row and window.col > 0:
|
||||
line = "«" + line[window.col + 1:]
|
||||
if len(line) > window.n_cols:
|
||||
|
|
@ -196,7 +207,7 @@ def editor(stdscr, filename):
|
|||
line += ' ' * (window.n_cols - len(line))
|
||||
setline(row, line)
|
||||
|
||||
row = window.n_rows - 1
|
||||
row = curses.LINES - 1
|
||||
if readonly():
|
||||
line = f"{filename:12} (readonly) | ^C: quit{gc_mem_free_hint()}"
|
||||
else:
|
||||
|
|
@ -243,7 +254,7 @@ def editor(stdscr, filename):
|
|||
|
||||
def edit(filename):
|
||||
with MaybeDisableReload():
|
||||
curses.wrapper(editor, filename)
|
||||
return curses.wrapper(editor, filename)
|
||||
|
||||
if __name__ == "__main__":
|
||||
import argparse
|
||||
|
|
|
|||
57
picker.py
Normal file
57
picker.py
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
import os
|
||||
import dang as curses
|
||||
|
||||
always = ["code.py", "boot.py", "settings.toml", "boot_out.txt"]
|
||||
good_extensions = [".py", ".toml", ".txt", ".json"]
|
||||
|
||||
def os_exists(filename):
|
||||
try:
|
||||
os.stat(filename)
|
||||
return True
|
||||
except OSError:
|
||||
return False
|
||||
|
||||
def isdir(filename):
|
||||
return os.stat(filename)[0] & 0o40_000
|
||||
|
||||
def has_good_extension(filename):
|
||||
for g in good_extensions:
|
||||
if filename.endswith(g):
|
||||
return True
|
||||
return False
|
||||
|
||||
def picker(stdscr, options, notes=[], start_idx=0):
|
||||
stdscr.erase()
|
||||
stdscr.addstr(curses.LINES-1, 0, "Enter: select | ^C: quit")
|
||||
del options[curses.LINES-1:]
|
||||
for row, option in enumerate(options):
|
||||
if row < len(notes) and (note := notes[row]):
|
||||
option = f"{option} {note}"
|
||||
|
||||
stdscr.addstr(row, 3, option)
|
||||
|
||||
old_idx = None
|
||||
idx = start_idx
|
||||
while True:
|
||||
if idx != old_idx:
|
||||
if old_idx is not None:
|
||||
stdscr.addstr(old_idx, 0, " ")
|
||||
stdscr.addstr(idx, 0, "=>")
|
||||
old_idx = idx
|
||||
|
||||
k = stdscr.getkey()
|
||||
|
||||
if k == 'KEY_DOWN':
|
||||
idx = min(idx + 1, len(options) - 1)
|
||||
elif k == 'KEY_UP':
|
||||
idx = max(idx - 1, 0)
|
||||
elif k == '\n':
|
||||
return options[idx]
|
||||
|
||||
def pick_file():
|
||||
options = always[:] + sorted(
|
||||
(g for g in os.listdir('.') if g not in always and not isdir(g) and not g.startswith('.')),
|
||||
key=lambda filename: (not has_good_extension(filename), filename),
|
||||
)
|
||||
notes = [None if os_exists(filename) else "(NEW)" for filename in options]
|
||||
return curses.wrapper(picker, options, notes)
|
||||
Loading…
Reference in a new issue