diff options
Diffstat (limited to 'lib/macshell.py')
| -rw-r--r-- | lib/macshell.py | 399 |
1 files changed, 399 insertions, 0 deletions
diff --git a/lib/macshell.py b/lib/macshell.py new file mode 100644 index 0000000..c96d65b --- /dev/null +++ b/lib/macshell.py @@ -0,0 +1,399 @@ +# Macintosh 'shell' +# vi:set tabsize=4: + +# XXX string quoting in arguments +# XXX directory stack +# XXX $macros? +# XXX ^C during any command +# XXX 'sh' builtin command? +# XXX why does open require absolute path? (need to fix chdir.c) + + +import mac + +import macpath +import string +import glob +from macpath import isfile, isdir, exists +import TclUtil # For splitting/quoting mechanisms + +class Struct(): pass +G = Struct() + +def reset(): + G.debug = 0 + G.ps1 = '$ ' + G.homedir = mac.getcwd() + G.commands = mkcmdtab() + G.aliases = {} + +def mkcmdtab(): + tab = {} + tab['alias'] = do_alias + tab['cd'] = do_cd + tab['debug'] = do_debug + tab['grep'] = do_grep + tab['help'] = do_help + tab['ls'] = do_ls + tab['mkdir'] = do_mkdir + tab['mv'] = do_mv + tab['page'] = do_page + tab['pwd'] = do_pwd + tab['reset'] = do_reset + tab['rm'] = do_rm + tab['rmdir'] = do_rmdir + tab['sync'] = do_sync + tab['unalias'] = do_unalias + return tab + +def main(): + while 1: + try: + line = raw_input(G.ps1) + except EOFError: + print '[EOF]' + break + except KeyboardInterrupt: + print '[Intr]' + line = '' + if G.debug: + print 'line:', `line` + words = TclUtil.SplitList(line) + if G.debug: + print 'words:', words + if words and words[0][0] <> '#': + run(words) + +def run(words): + expandaliases(words) + cmd = words[0] + args = words[1:] + if G.commands.has_key(cmd): + if args: + try: + args = expandgloblist(args) + except glob_error, msg: + print cmd, ': glob error :', msg + return + G.commands[cmd](args) + return + if hasglobchar(cmd): + if args: + print cmd, ': cannot glob pattern with arguments' + return + try: + words = expandglobword(cmd) + except glob_error, msg: + print cmd, ': glob error :', msg + return + if len(words) > 1: + columnize(words) + return + cmd = words[0] + print cmd + if isfile(cmd): + if args: + print cmd, ': file command expects no arguments' + return + do_page([cmd]) + elif isdir(cmd): + if args: + print cmd, ': directory command expects no arguments' + return + do_cd([cmd]) + else: + print cmd, ': no such command, file or directory' + +glob_error = 'glob error' + +def expandgloblist(words): + res = [] + for word in words: + if hasglobchar(word): + res = res + expandglobword(word) + else: + res.append(word) + return res + +def expandglobword(word): + names = glob.globlist(mac.listdir(':'), word) + if not names: raise glob_error, 'no match for pattern ' + word + return names + +def hasglobchar(word): + return '*' in word or '?' in word + +def expandaliases(words): + seen = [] + cmd = words[0] + while cmd not in seen and G.aliases.has_key(cmd): + seen.append(cmd) + words[:1] = G.aliases[cmd] + cmd = words[0] + +def do_alias(args): + if not args: + listaliases() + elif len(args) = 1: + listalias(args[0]) + else: + defalias(args[0], args[1:]) + +def listaliases(): + names = G.aliases.keys() + names.sort() + for name in names: listalias(name) + +def listalias(name): + if not G.aliases.has_key(name): + print name, ': no such alias' + return + print 'alias', name, + printlist(G.aliases[name]) + print + +def defalias(name, expansion): + G.aliases[name] = expansion + +def do_cd(args): + if len(args) > 1: + print 'usage: cd [dirname]' + elif args: + chdirto(args[0]) + else: + chdirto(G.homedir) + +def chdirto(dirname): + try: + mac.chdir(dirname) + except mac.error, msg: + print dirname, ':', msg + return + +def do_debug(args): + G.debug = (not G.debug) + +def do_grep(args): + if len(args) < 2: + print 'usage: grep regexp file ...' + return + import regexp + try: + prog = regexp.compile(args[0]) + except regexp.error, msg: + print 'regexp.compile error for', args[0], ':', msg + return + for file in args[1:]: + grepfile(prog, file) + +def grepfile(prog, file): + try: + fp = open(file, 'r') + except RuntimeError, msg: + print file, ': cannot open :', msg + return + lineno = 0 + while 1: + line = fp.readline() + if not line: break + lineno = lineno+1 + if prog.exec(line): + print file+'('+`lineno`+'):', line, + +def do_help(args): + if args: + print 'usage: help' + return + names = G.commands.keys() + names.sort() + columnize(names) + +def do_ls(args): + if not args: + lsdir(':') + else: + for dirname in args: + lsdir(dirname) + +def lsdir(dirname): + if not isdir(dirname): + print dirname, ': no such directory' + return + names = mac.listdir(dirname) + lsfiles(names, dirname) + +def lsfiles(names, dirname): + names = names[:] # Make a copy so we can modify it + for i in range(len(names)): + name = names[i] + if G.debug: print i, name + if isdir(macpath.cat(dirname, name)): + names[i] = ':' + name + ':' + columnize(names) + +def columnize(list): + COLUMNS = 80-1 + n = len(list) + colwidth = maxwidth(list) + ncols = (COLUMNS + 1) / (colwidth + 1) + if ncols < 1: ncols = 1 + nrows = (n + ncols - 1) / ncols + for irow in range(nrows): + line = '' + for icol in range(ncols): + i = irow + nrows*icol + if 0 <= i < n: + word = list[i] + if i+nrows < n: + word = string.ljust(word, colwidth) + if icol > 0: + word = ' ' + word + line = line + word + print line + +def maxwidth(list): + width = 0 + for word in list: + if len(word) > width: + width = len(word) + return width + +def do_mv(args): + if len(args) <> 2: + print 'usage: mv src dst' + return + src, dst = args[0], args[1] + if not exists(src): + print src, ': source does not exist' + return + if exists(dst): + print src, ': destination already exists' + return + try: + mac.rename(src, dst) + except mac.error, msg: + print src, dst, ': rename failed:', msg + +def do_mkdir(args): + if not args: + print 'usage: mkdir name ...' + return + for name in args: + makedir(name) + +def makedir(name): + if exists(name): + print name, ': already exists' + return + try: + mac.mkdir(name, 0777) + except mac.error, msg: + print name, ': mkdir failed:', msg + +def do_page(args): + if not args: + print 'usage: page file ...' + return + for name in args: + pagefile(name) + +def pagefile(name): + if not isfile(name): + print name, ': no such file' + return + LINES = 24 - 1 + # For THINK C 3.0, make the path absolute: + # if not macpath.isabs(name): + # name = macpath.cat(mac.getcwd(), name) + try: + fp = open(name, 'r') + except: + print name, ': cannot open' + return + line = fp.readline() + while line: + for i in range(LINES): + print line, + line = fp.readline() + if not line: break + if line: + try: + more = raw_input('[more]') + except (EOFError, KeyboardInterrupt): + print + break + if string.strip(more)[:1] in ('q', 'Q'): + break + +def do_pwd(args): + if args: + print 'usage: pwd' + else: + print mac.getcwd() + +def do_reset(args): + if args: + print 'usage: reset' + else: + reset() + +def do_rm(args): + if not args: + print 'usage: rm file ...' + return + for name in args: + remove(name) + +def remove(name): + if not isfile(name): + print name, ': no such file' + return + try: + mac.unlink(name) + except mac.error, msg: + print name, ': unlink failed:', msg + +def do_rmdir(args): + if not args: + print 'usage: rmdir dir ...' + return + for name in args: + rmdir(name) + +def rmdir(name): + if not isdir(name): + print name, ': no such directory' + return + try: + mac.rmdir(name) + except mac.error, msg: + print name, ': rmdir failed:', msg + +def do_sync(args): + if args: + print 'usage: sync' + return + try: + mac.sync() + except mac.error, msg: + print 'sync failed:', msg + +def do_unalias(args): + if not args: + print 'usage: unalias name ...' + return + for name in args: + unalias(name) + +def unalias(name): + if not G.aliases.has_key(name): + print name, ': no such alias' + return + del G.aliases[name] + +def printlist(list): + for word in list: + print word, + +reset() +main() |
