Skip to content

Micropython/upysh: imporve ux #655

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 66 additions & 21 deletions micropython/upysh/upysh.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import os


class LS:
class _Ls:
def __repr__(self):
self.__call__()
return ""
Expand All @@ -26,23 +26,50 @@ def __call__(self, path="."):
pass


class PWD:
class _Pwd:
def __repr__(self):
return os.getcwd()

def __call__(self):
return self.__repr__()


class CLEAR:
class _Clear:
def __repr__(self):
return "\x1b[2J\x1b[H"

def __call__(self):
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:
for i in range(n):
l = f.readline()
Expand All @@ -51,11 +78,11 @@ def head(f, n=10):
sys.stdout.write(l)


def cat(f):
def _cat_func(f):
head(f, 1 << 30)


def cp(s, t):
def _cp_func(s, t):
try:
if os.stat(t)[0] & 0x4000: # is directory
t = t.rstrip("/") + "/" + s
Expand All @@ -71,7 +98,7 @@ def cp(s, t):
t.write(buf_mv[:n])


def newfile(path):
def _newfile_func(path):
print("Type file contents line by line, finish with EOF (Ctrl+D).")
with open(path, "w") as f:
while 1:
Expand All @@ -83,20 +110,20 @@ def newfile(path):
f.write("\n")


def rm(d, recursive=False): # Remove file or tree
def _rm_func(d, recursive=False): # Remove file or tree
try:
if (os.stat(d)[0] & 0x4000) and recursive: # Dir
for f in os.ilistdir(d):
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)
else: # File
os.remove(d)
except:
print("rm of '%s' failed" % d)


class Man:
class _Man:
def __repr__(self):
return """
upysh is intended to be imported using:
Expand All @@ -105,20 +132,38 @@ def __repr__(self):
To see this help text again, type "man".

upysh commands:
clear, ls, ls(...), head(...), cat(...), newfile(...)
cp('src', 'dest'), mv('old', 'new'), rm(...)
pwd, cd(...), mkdir(...), rmdir(...)
clear, ls, ls(...), head(...)*, cat(...)*, newfile(...)*
cp('src', 'dest')*, mv('old', 'new')*, rm(name, recursive=False)*
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()
pwd = PWD()
ls = LS()
clear = CLEAR()
man = _Man()
pwd = _Pwd()
ls = _Ls()
clear = _Clear()

head = _StdinCommand(_head_func, [["Filename", str, None], ["Num of lines (default=10)", int, 10]])

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]])

cd = os.chdir
mkdir = os.mkdir
mv = os.rename
rmdir = os.rmdir
rmdir = _StdinCommand(os.rmdir, [["Directory name", str, None]])

print(man)