change the methods so they all throw exceptions

change the shell code to catch these exceptions
shell version 1.2
change the quoted-string parser to simplify
This commit is contained in:
2021-04-09 08:37:34 -04:00
parent 83857b5571
commit ddbea490ea
2 changed files with 131 additions and 129 deletions

202
tf.py
View File

@@ -16,77 +16,61 @@ import re,os,sys,gc
def transfer(src,dest,first=1,last=0xFFFFFFFF,numbers=False,grep_func=None):
#src is a filename, dst is a handle
i=0
try:
with open(src) as f:
for lin in f:
i=i+1
if i<first or i>last:
continue
if grep_func and not grep_func(lin):
continue
if numbers:
dest.write(str(i)+' ')
dest.write(lin)
except:
print("could not open file {}".format(src))
with open(src) as f:
for lin in f:
i=i+1
if i<first or i>last:
continue
if grep_func and not grep_func(lin):
continue
if numbers:
dest.write(str(i)+' ')
dest.write(lin)
def cp(src,dest):
try:
with open(dest,'w') as g:
transfer(src,g)
except:
print("could not write to file {}".format(dest))
def grep(filename, pattern, numbers=False):
m=re.compile(pattern)
if not m:
print("grep() called with invalid pattern")
return
transfer(filename,sys.stdout,numbers=numbers,grep_func=(lambda x:m.search(x)))
with open(dest,'w') as g:
transfer(src,g)
def cat(filename, first=1, last=1000000, numbers=False, title=True):
if title:
print("===={}=====".format(filename))
print("===={}====".format(filename))
transfer(filename,sys.stdout,first,last,numbers=numbers)
def grep(filename, pattern, numbers=False):
m=re.compile(pattern)
transfer(filename,sys.stdout,numbers=numbers,grep_func=(lambda x:m.search(x[:-1])))
def sed(filename, sed_cmd, bak_ext=".bak"):
# parse the sed_cmd
# group 1,3 are the n-start, n-end group 4 is command: aidsxX
a=re.search("^(\d*)([,-](\d+|\$))?\s*([sdaixX].*)",sed_cmd)
if not a:
print("sed() failed; 2nd argument must be a number-range followed by one of sdaixX; no changes applied")
return
raise ValueError("sed() failed; pattern must be a number-range followed by one of sdaixX; no changes applied")
cmd=a.group(4)
s,e=(1,1000000)
s,e=1,1000000
if a.group(1):
s=e=int(a.group(1))
if a.group(3):
e=1000000 if a.group(3)=='$' else int(a.group(3))
op=cmd[0]
if op not in "sdiaxX":
print("sed requires an operation, one of 's,d,i,a,x or X'")
return
#print("sed command parser of <{}> returned {} {} {} {}".format(cmd,sr,de,ins,add))
if op in "aid" and e-s==1000000:
raise ValueError("sed(a/i/d) should have a line number")
#print("sed command parser of <{}> returned {} {} {}".format(op,cmd,a.group(1),a.group(3)))
if op in "sxX":
if len(cmd)<2:
print("invalid sed argument")
return
if len(cmd)<2 or cmd[1] in "\^$()[]":
raise ValueError("invalid sed argument: {}".format(cmd))
dl=cmd[1]
if op=='s':
gs=re.search("s"+dl+"([^"+dl+"]*)"+dl+"([^"+dl+"]*)"+dl,cmd)
else:
gs=re.search("[xX]"+dl+"([^"+dl+"]*)"+dl,cmd)
if not gs:
print("invalid sed search pattern")
return 0,0
raise ValueError("invalid sed search pattern: {}".format(cmd))
ss=gs.group(1)
if op=='s':
ss,r = gs.group(1),gs.group(2)
#print("search <{}> and replace <{}>".format(s,r))
else:
ss=gs.group(1)
#print("search <{}>".format(s))
r=gs.group(2)
sp=re.compile(ss)
extra=a.group(4)[1:] + '\n'
@@ -94,50 +78,41 @@ def sed(filename, sed_cmd, bak_ext=".bak"):
try:
os.rename(filename,filename+bak_ext)
except:
print("problem with filename; backup failed; no changes made")
return
raise OSError("problem with filename",filename," backup failed; no changes made")
i=h=0
try:
with open(filename+bak_ext) as f:
with open(filename,'w') as g:
for lin in f:
i=i+1
m=(i>=s and i<=e)
if op=='s' and m:
lin=lin[:-1]
if sp.search(lin): h+=1
lin=sp.sub(r,lin)+'\n'
if op=='d' and m:
h+=1
continue # delete line
if op=='i' and m:
#print("insert a line before {} <{}>".format(i,extra))
g.write(extra)
h+=1
if op in "aids":
g.write(lin)
elif m and (op=='x' if sp.search(lin) else op=='X'):
g.write(lin)
h+=1
if op=='a' and m:
#print("append a line after {} <{}>".format(i,extra))
g.write(extra)
h+=1
#f.write("--file modifed by sed()--\n")
except OSError:
print("problem opening file {}".format(filename))
except RuntimeError:
print("problem with the regex; try a different pattern")
with open(filename+bak_ext) as f:
with open(filename,'w') as g:
for lin in f:
i=i+1
m=(i>=s and i<=e)
if op=='s' and m:
lin=lin[:-1]
if sp.search(lin): h+=1
lin=sp.sub(r,lin)+'\n'
if op=='d' and m:
h+=1
continue # delete line
if op=='i' and m:
#print("insert a line before {} <{}>".format(i,extra))
g.write(extra)
h+=1
if op in "aids":
g.write(lin)
elif m and (op=='x' if sp.search(lin) else op=='X'):
g.write(lin)
h+=1
if op=='a' and m:
#print("append a line after {} <{}>".format(i,extra))
g.write(extra)
h+=1
#f.write("--file modifed by sed()--\n")
return (i, h)
def _dir(d='.'):
try:
for f in os.listdir(d):
s=os.stat(d+'/'+f)
print("{}rwx all {:9d} {}".format('d' if (s[0] & 0x4000) else '-',s[6],f))
except:
print("not a valid directory")
for f in os.listdir(d):
s=os.stat(d+'/'+f)
print("{}rwx all {:9d} {}".format('d' if (s[0] & 0x4000) else '-',s[6],f))
s=os.statvfs('/')
print("disk size:{:8d} KB disk free: {} KB".format(s[0]*s[2]//1024,s[0]*s[3]//1024))
@@ -149,26 +124,27 @@ if 'tf_extend.py' in os.listdir():
ext_cmd=tf_extend.cmd
def _help():
print("==Simple shell v1.1")
print("==Simple shell v1.2 for Text Files")
print(" cp/copy <src-file> <dest-file>")
print(" mv/move <src-file> <dest-file> \t\trm/del <file>")
print(" cd [<folder>] mkdir <folder>\t\trmdir <folder>")
print(" cd [<folder>]\t\tmkdir <folder>\t\trmdir <folder>")
print(" dir/ls [<folder>]")
print(" cat/list [-n] [-l <n>,<m>] <file>")
print(" grep <pattern> <file>")
print(" sed <pattern> <file>")
print(" pattern is '<line-range><op><extra>' e.g'a/search/replace/', 'x!TODO:!', '43,49d', '8itext'")
print(" patterns with spaces require single-quotes sed ops are one of s/d/i/a/x/X")
print(" sed does not work across line boundaries sed s/x/X-patterns: non-/ delimiters are allowed")
print("file names must NOT have embedded spaces options must be early on the command line")
print(" pattern is <line-range><op><extra> e.g'a/search/replace/', 'x!TODO:!', '43,49d', '8itext'")
print(" patterns with spaces require '-quotes\tsed ops are one of s/d/i/a/x/X")
print(" sed cannot cross line boundaries\t\tsed s/x/X-patterns: non-/ delimiters are ok")
print("file names must NOT have embedded spaces\toptions must be early on the command line")
ext_cmd('help')
def parseQuotedArgs(st):
st=st.strip()
if st[0]=="'":
p=re.search("'((\'|[^'])*)'",st)
p=re.search("'(.*?[^\\\\])'",st)
if not p:
print("quoted pattern error")
return ""
print("error in quoted pattern:",st)
return
return p.group(1)
else:
return st.split()[0]
@@ -182,7 +158,10 @@ def main():
if not len(rp): continue
op=rp[0]
if op in ('dir','ls'):
_dir(rp[1] if len(rp)>1 else '.')
try:
_dir(rp[1] if len(rp)>1 else '.')
except:
print("directory not found")
elif op in ('cat','list'):
n=(" -n " in r) #print line-nums
s,e=1,1000000 #start/end
@@ -191,21 +170,28 @@ def main():
s=e=int(g.group(2))
if g.group(3):
e=int(g.group(4)) if g.group(4) and g.group(4).isdigit() else 1000000
cat(rp[-1],s,e,numbers=n)
elif op=='grep':
try:
cat(rp[-1],s,e,numbers=n)
except:
print("file not found",rp[-1])
elif op in('grep','sed'):
if len(rp)<3:
print("grep pattern filename")
print(op,"pattern filename")
continue
grep(rp[-1],parseQuotedArgs(r[5:]),numbers=True)
elif op=='sed':
if len(rp)<3:
print("sed pattern filename")
p=parseQuotedArgs(r[4:])
if not p:
continue
r=sed(rp[-1],parseQuotedArgs(r[4:]))
if r:
print("Lines processed: {} Lines modifed: {}".format(*r))
elif op=='cd':
os.chdir(rp[1] if len(rp)>1 else '/')
try:
if op=='grep':
grep(rp[-1],p,numbers=True)
else:
r=sed(rp[-1],p)
if r:
print("Lines processed: {} Lines modifed: {}".format(*r))
except (ValueError, OSError) as e:
print(e)
except RuntimeError:
print("problem with the regex; try a different pattern")
elif op=='help':
_help()
ext_cmd(rp)
@@ -215,6 +201,8 @@ def main():
try:
if op in ('cp','copy'):
cp(rp[1],rp[2])
elif op=='cd':
os.chdir(rp[1] if len(rp)>1 else '/')
elif op=='mkdir':
os.mkdir(rp[1])
elif op=='rmdir':
@@ -224,15 +212,15 @@ def main():
elif op in('rm','del'):
os.remove(rp[1])
else:
print("command not implemented")
print("command not implemented:",op)
except IndexError:
print("not enough argments; check syntax with 'help'")
except OSError:
print("file not found")
print("file/folder not found or cannot be writtencd")
gc.collect()
if __name__=="tf":
print("tf module loaded; members cp(), cat(), cd(), _dir(), grep() and sed()")
main()
# grep 12.*\) dmesg fails