#!/usr/bin/env python """ metashell.py - Meta Shell Author: Sean B. Palmer, inamidst.com """ import sys, os, re from code import metagen metagen.meta = '../meta' def PS1(path): return 'sbp@metashell:%s$ ' % path def makepath(path): path = os.path.dirname(path) if not os.path.isdir(path): os.makedirs(path) def barf(msg): print >> sys.stderr, msg sys.exit(1) def join(here, there): if there.startswith('~') or there.startswith('/'): return os.path.normpath(there) elif here.startswith('~'): here = here.lstrip('~') if not here.startswith('/'): here = '/' + here return os.path.normpath('~' + os.path.join(here, there)) return os.path.normpath(os.path.join(here, there)) def cd(keyword): newpath = join(main.path, keyword) if newpath.startswith('/'): dirname = os.path.join(metagen.meta, newpath.lstrip('/')) if not os.path.exists(dirname): raise OSError("Directory does not exist: %s" % dirname) elif newpath.startswith('~/'): if not metagen.bykeyword(newpath[2:]): raise OSError("No files have this keyword: %s" % newpath[2:]) elif newpath != '~': raise ValueError("Unknown path: %s" % newpath) main.path = newpath def ls(keyword=None): if keyword is None: keyword = main.path else: keyword = join(main.path, keyword) if not keyword: for keyword in metagen.bykeyword(): print '~/' + keyword elif keyword in ('~', '~/'): for filename in metagen.bykeyword(): print '~/' + filename elif keyword.startswith('~'): # @@@@@@@@@@ empty keyword? keyword = keyword.lstrip('~/') for (path, metafn, metadata) in metagen.bykeyword(keyword): print path, '-', metadata.get('title') or '[untitled]' else: keyword = keyword.lstrip('/') dirname = os.path.join(metagen.meta, keyword) for fn in sorted(os.listdir(dirname)): filename = os.path.join(keyword, fn) if os.path.isdir(os.path.join(dirname, filename)): print '/' + filename + '/' else: print '/' + filename def make(path): path = join(main.path, path) if not path.startswith('/'): raise OSError("Path %s doesn't start with /" % path) if path.endswith('/'): path += 'index' if not os.path.isdir(metagen.meta): barf("Error: There is no meta directory") metafn = os.path.join(metagen.meta, '.' + path) metafn = os.path.normpath(metafn) if os.path.exists(metafn): barf("Error: file <%s> already exists" % metafn) makepath(metafn) title = raw_input("Title: ") desc = raw_input("Description: ") keywords = raw_input("Keywords: ") if not (title or desc or keywords): barf("Error: Must enter title or desc or keywords") # print "Opening %s for writing..." % metafn f = open(metafn, 'w') if title: print >> f, 'title:', title if desc: print >> f, 'description:', desc if keywords: keywords = sorted(keywords.split(' ')) print >> f, 'keywords:', ' '.join(keywords) f.close() print "Created %s successfully" % path def edit(path): path = join(main.path, path) if not path.startswith('/'): raise OSError("Path %s doesn't start with /" % path) if path.endswith('/'): path += 'index' filepath = os.path.join(metagen.meta, '.' + path) filepath = os.path.normpath(filepath) replacement = [] f = open(filepath) for line in f: line = line.rstrip('\r\n') if (not line.startswith('#')) and line: print 'Current:', line input = raw_input('Replacement Value: ') key, value = line.split(': ', 1) if not input.strip(): replacement.append(key + ': ' + value) elif input.startswith('/') or input.startswith('!'): sep = input[0] here, there = input[1:-1].split(sep, 1) try: r_regexp = re.compile(here) except: newvalue = value.replace(here, there) else: newvalue = r_regexp.sub(there, value) replacement.append(key + ': ' + newvalue) else: replacement.append(key + ': ' + input.rstrip('\r\n')) f.close() if replacement: f = open(filepath, 'w') for line in replacement: print >> f, line f.close() def cat(path): path = join(main.path, path) if not path.startswith('/'): raise OSError("Path %s doesn't start with /" % path) if path.endswith('/'): path += 'index' filepath = os.path.join(metagen.meta, '.' + path) filepath = os.path.normpath(filepath) if not os.path.exists(filepath): barf("Path doesn't exist: %s" % filepath) f = open(filepath) for line in f: print line.rstrip('\r\n') f.close() def exit(): print sys.exit() def run(func, args): assert func.isalpha() try: eval(func)(*args) except Exception, e: if isinstance(e, SystemExit): raise e else: print 'Error:', e def main(): main.path = '~' while True: try: command = raw_input(PS1(main.path)) except EOFError: command = 'exit' if ' ' in command: prog, args = command.split(' ', 1) run(prog, args.split(' ')) else: run(command, tuple()) if __name__=="__main__": main()