Micropython/upysh: Improve UX and making functions private

Micropython/upysh: Improve UX by allowing calling commands interactively;
make internal classes and functions not importable (put _ before their names).

interactively means you don't have to type tons of brackets and quotes
(something alike what you expect from a normal shell),
to figure out this behavior just type cd or mv
pull/655/head
Igorello74 2023-05-07 23:34:37 +05:00 zatwierdzone przez GitHub
rodzic a1b9aa934c
commit 3108e2a53e
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
1 zmienionych plików z 70 dodań i 21 usunięć

Wyświetl plik

@ -2,7 +2,7 @@ import sys
import os import os
class LS: class _Ls:
def __repr__(self): def __repr__(self):
self.__call__() self.__call__()
return "" return ""
@ -26,7 +26,7 @@ class LS:
pass pass
class PWD: class _Pwd:
def __repr__(self): def __repr__(self):
return os.getcwd() return os.getcwd()
@ -34,7 +34,7 @@ class PWD:
return self.__repr__() return self.__repr__()
class CLEAR: class _Clear:
def __repr__(self): def __repr__(self):
return "\x1b[2J\x1b[H" return "\x1b[2J\x1b[H"
@ -42,7 +42,34 @@ class CLEAR:
return self.__repr__() return self.__repr__()
def head(f, n=10): class _StdinCommand:
def __init__(self, command, args):
self.command = command
self.args = args.copy()
def __repr__(self):
cur_args = []
for prompt, parser, default in self.args:
arg = input(prompt + ": ")
if arg == "":
if default is not None:
arg = default
else:
print(f"You must provide {prompt.lower()}")
return ""
else:
arg = parser(arg)
cur_args.append(arg)
self.command(*cur_args)
return ""
def __call__(self, *args):
self.command(*args)
def _head_func(f, n=10):
with open(f) as f: with open(f) as f:
for i in range(n): for i in range(n):
l = f.readline() l = f.readline()
@ -51,11 +78,11 @@ def head(f, n=10):
sys.stdout.write(l) sys.stdout.write(l)
def cat(f): def _cat_func(f):
head(f, 1 << 30) head(f, 1 << 30)
def cp(s, t): def _cp_func(s, t):
try: try:
if os.stat(t)[0] & 0x4000: # is directory if os.stat(t)[0] & 0x4000: # is directory
t = t.rstrip("/") + "/" + s t = t.rstrip("/") + "/" + s
@ -71,7 +98,7 @@ def cp(s, t):
t.write(buf_mv[:n]) t.write(buf_mv[:n])
def newfile(path): def _newfile_func(path):
print("Type file contents line by line, finish with EOF (Ctrl+D).") print("Type file contents line by line, finish with EOF (Ctrl+D).")
with open(path, "w") as f: with open(path, "w") as f:
while 1: while 1:
@ -83,12 +110,12 @@ def newfile(path):
f.write("\n") f.write("\n")
def rm(d, recursive=False): # Remove file or tree def _rm_func(d, recursive=False): # Remove file or tree
try: try:
if (os.stat(d)[0] & 0x4000) and recursive: # Dir if (os.stat(d)[0] & 0x4000) and recursive: # Dir
for f in os.ilistdir(d): for f in os.ilistdir(d):
if f[0] != "." and f[0] != "..": if f[0] != "." and f[0] != "..":
rm("/".join((d, f[0]))) # File or Dir rm("/".join((d, f[0])), True) # File or Dir
os.rmdir(d) os.rmdir(d)
else: # File else: # File
os.remove(d) os.remove(d)
@ -96,7 +123,7 @@ def rm(d, recursive=False): # Remove file or tree
print("rm of '%s' failed" % d) print("rm of '%s' failed" % d)
class Man: class _Man:
def __repr__(self): def __repr__(self):
return """ return """
upysh is intended to be imported using: upysh is intended to be imported using:
@ -105,20 +132,42 @@ from upysh import *
To see this help text again, type "man". To see this help text again, type "man".
upysh commands: upysh commands:
clear, ls, ls(...), head(...), cat(...), newfile(...) clear, ls, ls(...), head(...)*, cat(...)*, newfile(...)*
cp('src', 'dest'), mv('old', 'new'), rm(...) cp('src', 'dest')*, mv('old', 'new')*, rm(...)*
pwd, cd(...), mkdir(...), rmdir(...) pwd, cd(...)*, mkdir(...)*, rmdir(...)*
Most commands (marked with *) can be called interactively.
It means you don't have to type tons of brackets and quotes
(something alike what you expect from a normal shell),
to figure out this behavior just type cd or mv
""" """
man = Man() man = _Man()
pwd = PWD() pwd = _Pwd()
ls = LS() ls = _Ls()
clear = CLEAR() clear = _Clear()
cd = os.chdir head = _StdinCommand(
mkdir = os.mkdir _head_func, [["Filename", str, None], ["Num of lines (default=10)", int, 10]]
mv = os.rename )
rmdir = os.rmdir
cat = _StdinCommand(_cat_func, [["Filename", str, None]])
cp = _StdinCommand(_cp_func, [["Source", str, None], ["Target", str, None]])
newfile = _StdinCommand(_newfile_func, [["Filename", str, None]])
rm = _StdinCommand(
_rm_func, [["Filename", str, None], ["Recursive (default=False)", bool, False]]
)
cd = _StdinCommand(os.chdir, [["Target", str, None]])
mkdir = _StdinCommand(os.mkdir, [["Directory name", str, None]])
mv = _StdinCommand(os.rename, [["Source", str, None], ["Target", str, None]])
rmdir = _StdinCommand(os.rmdir, [["Directory name", str, None]])
print(man) print(man)