import commands, dirutil, grp, method, mode, os.path, pwd, re import buffer, buffer.fs import window from lex import Grammar, PatternRule, RegionRule, PatternGroupRule from point import Point from method import Method, Argument class PermGrammar(Grammar): rules = [ PatternRule(r'perm_sticky', r'[tT]'), PatternRule(r'perm_setid', r'[sS]'), PatternRule(r'perm_read', r'r'), PatternRule(r'perm_write', r'w'), PatternRule(r'perm_exec', r'x'), ] class PathGrammar(Grammar): rules = [ RegionRule(r'dir_perm', r'(?<=^.)', PermGrammar, r' '), PatternGroupRule( r'dir_fields', r'dir_owner', r'[^ ]+ +', r'dir_group', r'[^ ]+ +', r'dir_size', r'[^ ]+ +', r'dir_mtime', r'[A-Za-z]{3} [ 0-9]{2} [0-9]{2}:[0-9]{2} +', r'dir_name', r'[^\n]*', ), ] class DirGrammar(Grammar): rules = [ RegionRule(r'dir_file', r'^-', PathGrammar, r'\n'), RegionRule(r'dir_blk', r'^b', PathGrammar, r'\n'), RegionRule(r'dir_chr', r'^c', PathGrammar, r'\n'), RegionRule(r'dir_dir', r'^d', PathGrammar, r'\n'), RegionRule(r'dir_lnk', r'^l', PathGrammar, r'\n'), RegionRule(r'dir_fifo', r'^p', PathGrammar, r'\n'), RegionRule(r'dir_sock', r'^s', PathGrammar, r'\n'), RegionRule(r'dir_unk', r'^\?', PathGrammar, r'\n'), ] class RefreshView(Method): def _execute(self, w, **vargs): t = dirutil.resolve_token(w) s = t.string w.buffer.reload() dirutil.find_name(w, s) class OpenPath(Method): def _execute(self, w, **vargs): path = dirutil.resolve_path(w) w.set_error("opening %r" % path) w.application.methods['open-file'].execute(w, filename=path) class DirGrep(Method): args = [Argument('pattern', datatype="str", prompt="Pattern: ")] def _execute(self, w, **vargs): cmd = 'grep -rEl %r %r' % (vargs['pattern'], w.buffer.path) (status, output) = commands.getstatusoutput(cmd) paths = [x for x in output.split('\n') if x] bufname = '*%s*' % self.name.title() b = buffer.fs.PathListBuffer(bufname, paths) b.modename = 'dir' b.open() window.Window(b, w.application, height=0, width=0) w.application.add_buffer(b) w.application.switch_buffer(b) w.set_error("grep exited with %d" % status) class DirCmd(Method): def _make_cmd(self, w, path, **vargs): return '' def _run(self, w, **vargs): basename = dirutil.resolve_name(w) path = os.path.join(w.buffer.path, basename) cmd = self._make_cmd(w, path, **vargs) (status, output) = commands.getstatusoutput(cmd) if status != 0: w.set_error("%s failed (exit %d)" % (self.name, status)) #w.application.methods['refresh-view'].execute(w, filename=path) dirutil.find_name(w, basename) class Chmod(DirCmd): args = [Argument('mode', type=type(''), prompt="New Mode: ")] octal_re = re.compile('^[0-7]{1,4}$') symbolic_re = re.compile('(?:[ugoa]*(?:[-+=](?:[rwxXst]*|[ugo]))+ *,?)+') def _make_cmd(self, w, path, **vargs): return 'chmod %r %r' % (vargs['mode'], path) 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']) self._run(w, **vargs) class Chown(DirCmd): args = [Argument('owner', type=type(''), prompt="New Owner: ")] def _make_cmd(self, w, path, **vargs): return 'chown %r %r' % (vargs['owner'], path) 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 dirutil.valid_owner(owner): w.set_error('User %r does not exist' % owner) return if group is not None and not dirutil.valid_group(group): w.set_error('Group %r does not exist' % group) return self._run(w, **vargs) class Chgrp(DirCmd): args = [Argument('group', type=type(''), prompt="New Group: ")] def _make_cmd(self, w, path, **vargs): return 'chgrp %r %r' % (vargs['group'], path) def _execute(self, w, **vargs): if not dirutil.valid_group(vargs['group']): w.set_error('Group %r does not exist' % group) return self._run(w, **vargs) 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) dirutil.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 = dirutil.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) class Dir(mode.Fundamental): modename = 'Dir' grammar = DirGrammar() colors = { 'dir_blk.start': ('cyan', 'default', 'bold'), 'dir_blk.dir_name': ('cyan', 'default', 'bold'), 'dir_chr.start': ('yellow', 'default', 'bold'), 'dir_chr.dir_name': ('yellow', 'default', 'bold'), 'dir_dir.start': ('blue', 'default', 'bold'), 'dir_dir.dir_name': ('blue', 'default', 'bold'), 'dir_lnk.start': ('green', 'default', 'bold'), 'dir_lnk.dir_name': ('green', 'default', 'bold'), 'dir_fifo.start': ('red', 'default', 'bold'), 'dir_fifo.dir_name': ('red', 'default', 'bold'), 'dir_sock.start': ('red', 'default', 'bold'), 'dir_sock.dir_name': ('red', 'default', 'bold'), 'dir_unk.start': ('magenta', 'default', 'bold'), 'dir_unk.dir_name': ('magenta', 'default', 'bold'), 'dir_perm.perm_setid': ('yellow', 'default', 'bold'), 'dir_perm.perm_sticky': ('yellow', 'default', 'bold'), 'dir_perm.perm_read': ('magenta', 'default', 'bold'), 'dir_perm.perm_write': ('magenta', 'default', 'bold'), 'dir_perm.perm_exec': ('magenta', 'default', 'bold'), 'dir_owner': ('cyan', 'default', 'bold'), 'dir_group': ('cyan', 'default', 'bold'), 'dir_size': ('yellow', 'default', 'bold'), 'dir_mtime': ('green', 'default', 'bold'), } actions = [RefreshView, OpenPath, DirGrep, Chmod, Chown, Chgrp, TouchPath, RemovePath] def __init__(self, w): mode.Fundamental.__init__(self, w) self.add_bindings('refresh-view', ('C-c r',)) self.add_bindings('open-path', ('RETURN',)) self.add_bindings('dir-grep', ('C-c G',)) self.add_bindings('chmod', ('C-c m',)) self.add_bindings('chown', ('C-c o',)) self.add_bindings('chgrp', ('C-c g',)) self.add_bindings('touch-path', ('C-c t',)) self.add_bindings('remove-path', ('DELETE', 'BACKSPACE', 'C-d')) install = Dir.install