pmacs3/mode/dir.py

185 lines
7.0 KiB
Python

import commands, dirutil, 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_and_bindings(RefreshView(), ('C-c r',))
self.add_action_and_bindings(OpenPath(), ('RETURN',))
self.add_action_and_bindings(Chmod(), ('C-c m',))
self.add_action_and_bindings(Chown(), ('C-c o',))
self.add_action_and_bindings(Chgrp(), ('C-c g',))
self.add_action_and_bindings(TouchPath(), ('C-c t',))
self.add_action_and_bindings(RemovePath(), ('DELETE', 'BACKSPACE', 'C-d'))
def name(self):
return "Dir"
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 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)