import grp, method, mode2, os.path, pwd, re from lex3 import Grammar, PatternRule, RegionRule, PatternGroupRule from point2 import Point from method import Method, Argument class PermGrammar(Grammar): rules = [ PatternRule(r'sticky', r'[tT]'), PatternRule(r'setid', r'[sS]'), PatternRule(r'read', r'r'), PatternRule(r'write', r'w'), PatternRule(r'exec', r'x'), ] class PathGrammar(Grammar): rules = [ RegionRule(r'perm', r'(?<=^.)', PermGrammar, r' '), PatternGroupRule(r'fields', r'owner', r'[^ ]+ +', r'group', r'[^ ]+ +', r'size', r'[^ ]+ +', r'mtime', r'[A-Za-z]{3} [ 0-9]{2} [0-9]{2}:[0-9]{2} +', r'name', r'[^\n]*'), ] class DirGrammar(Grammar): rules = [ RegionRule(r'file', r'^-', PathGrammar, r'\n'), RegionRule(r'blk', r'^b', PathGrammar, r'\n'), RegionRule(r'chr', r'^c', PathGrammar, r'\n'), RegionRule(r'dir', r'^d', PathGrammar, r'\n'), RegionRule(r'lnk', r'^l', PathGrammar, r'\n'), RegionRule(r'fifo', r'^p', PathGrammar, r'\n'), RegionRule(r'sock', r'^s', PathGrammar, r'\n'), RegionRule(r'unk', r'^\?', PathGrammar, r'\n'), ] class Dir(mode2.Fundamental): grammar = DirGrammar() colors = { 'blk.start': ('cyan', 'default'), 'blk.name': ('cyan', 'default'), 'chr.start': ('yellow', 'default'), 'chr.name': ('yellow', 'default'), 'dir.start': ('blue', 'default'), 'dir.name': ('blue', 'default'), 'lnk.start': ('green', 'default'), 'lnk.name': ('green', 'default'), 'fifo.start': ('red', 'default'), 'fifo.name': ('red', 'default'), 'sock.start': ('red', 'default'), 'sock.name': ('red', 'default'), 'unk.start': ('magenta', 'default'), 'unk.name': ('magenta', 'default'), 'perm.setid': ('yellow', 'default'), 'perm.sticky': ('yellow', 'default'), 'perm.read': ('magenta', 'default'), 'perm.write': ('magenta', 'default'), 'perm.exec': ('magenta', 'default'), 'owner': ('cyan', 'default'), 'group': ('cyan', 'default'), 'size': ('yellow', 'default'), 'mtime': ('green', 'default'), } def __init__(self, w): mode2.Fundamental.__init__(self, w) self.add_action(Chmod()) self.add_action(Chown()) self.add_action(Chgrp()) self.add_action(TouchPath()) self.add_action(RefreshView()) self.add_action_and_bindings(OpenPath(), ('RETURN',)) self.add_action_and_bindings(RemovePath(), ('DELETE', 'BACKSPACE', 'C-d')) def name(self): return "Dir" def _resolve_token(w): c = w.logical_cursor() p = Point(0, c.y) return w.get_next_token_by_type(p, 'name') def _resolve_name(w): t = _resolve_token(w) return t.string def _resolve_path(w): name = _resolve_name(w) path = os.path.join(w.buffer.path, name) return path def _find_name(w, s): found = False w.goto(Point(0, 0)) c = w.logical_cursor() while not found and c.y < len(w.buffer.lines): t = _resolve_token(w) if t.string == s: found = True break w.goto(Point(c.x, c.y + 1)) c = w.logical_cursor() if not found: w.goto(Point(0, 0)) class RefreshView(Method): def _execute(self, w, **vargs): t = _resolve_token(w) s = t.string w.buffer.reload() _find_name(w, s) class OpenPath(Method): def _execute(self, w, **vargs): path = _resolve_path(w) w.set_error("opening %r" % path) w.application.methods['open-file'].execute(w, filename=path) class Chmod(Method): args = [Argument('mode', type=type(''), prompt="New Mode: ")] octal_re = re.compile('^[0-7]{1,4}$') symbolic_re = re.compile('(?:[ugoa]*(?:[-+=](?:[rwxXst]*|[ugo]))+ *,?)+') def _execute(self, w, **vargs): if self.octal_re.match(vargs['mode']): pass elif self.symbolic_re.match(vargs['mode']): pass else: w.set_error("Not a valid mode: %r" % vargs['mode']) basename = _resolve_name(w) path = os.path.join(w.buffer.path, basename) retval = os.system('chmod %r %r' % (vargs['mode'], path)) w.application.methods['refresh-view'].execute(w, filename=path) _find_name(w, basename) if retval != 0: w.set_error("chmod %r failed (exit %d)" % (vargs['mode'], retval)) class Chown(Method): args = [Argument('owner', type=type(''), prompt="New Owner: ")] def _execute(self, w, **vargs): fields = vargs['owner'].split(':') if len(fields) == 1: (owner, group) = (fields[0], None) elif len(fields) == 2: (owner, group) = fields else: w.set_error("Malformed 'owner' argument: %r" % vargs['owner']) return if not owner.isdigit(): try: pwd.getpwnam(owner) except: w.set_error("User %r does not exist" % owner) return if group is not None and not group.isdigit(): try: grp.getgrnam(group) except: w.set_error("Group %r does not exist" % group) return basename = _resolve_name(w) path = os.path.join(w.buffer.path, basename) retval = os.system('chown %r %r' % (vargs['owner'], path)) w.application.methods['refresh-view'].execute(w, filename=path) _find_name(w, basename) if retval != 0: w.set_error("chown %r failed (exit %d)" % (vargs['mode'], retval)) class Chgrp(Method): args = [Argument('group', type=type(''), prompt="New Group: ")] def _execute(self, w, **vargs): w.set_error('chgrp not implemented') class TouchPath(Method): args = [Argument('filename', datatype="path", prompt="Touch File: ")] def _execute(self, w, **vargs): basename = vargs['filename'] path = os.path.join(w.buffer.path, basename) retval = os.system('touch %r' % path) w.application.methods['refresh-view'].execute(w, filename=path) _find_name(w, basename) if retval != 0: w.set_error("touch %r failed (exit %d)" % (path, retval)) class RemovePath(Method): def _execute(self, w, **vargs): self._old_window = w self._old_path = _resolve_path(w) basename = os.path.basename(self._old_path) self._prompt = "Do you want to delete %r? " % basename w.application.open_mini_buffer(self._prompt, self._callback) def _callback(self, v): a = self._old_window.application if v == 'yes': self._doit() a.close_mini_buffer() return if v == 'no': a.close_mini_buffer() return a.open_mini_buffer(self._prompt, self._callback) a.set_error('Please type "yes" or "no"') def _doit(self): w = self._old_window path = self._old_path try: w.application.methods['previous-line'].execute(w) os.remove(path) w.set_error("deleted %r " % path) w.application.methods['refresh-view'].execute(w, filename=path) except: w.set_error("failed to delete %r" % path)