From 3bb9e6b7a689a2da72722d11bc689216b08a4c1d Mon Sep 17 00:00:00 2001 From: moculus Date: Thu, 19 Jul 2007 18:28:21 +0000 Subject: [PATCH] file browsing ahoy --HG-- branch : pmacs2 --- application.py | 5 +-- buffer2.py | 97 +++++++++++++++++++++++++++++++++++++++++++++++--- lex3.py | 2 +- mode_dir.py | 89 +++++++++++++++++++++++++++++++++++++++++++++ window2.py | 5 +-- 5 files changed, 188 insertions(+), 10 deletions(-) create mode 100644 mode_dir.py diff --git a/application.py b/application.py index 30579a4..3b732f7 100755 --- a/application.py +++ b/application.py @@ -11,7 +11,7 @@ import mode2 import mode_mini, mode_search, mode_replace, mode_which import mode_console, mode_consolemini import mode_c, mode_python, mode_perl, mode_nasm, mode_sh, mode_sql -import mode_blame, mode_diff +import mode_blame, mode_diff, mode_dir import mode_xml, mode_tt, mode_css, mode_javascript, mode_html import mode_text, mode_mutt import mode_bds, mode_life @@ -84,6 +84,7 @@ class Application(object): 'console': mode_console.Console, 'consolemini': mode_consolemini.Console, 'diff': mode_diff.Diff, + 'dir': mode_dir.Dir, 'fundamental': mode2.Fundamental, 'mini': mode_mini.Mini, 'nasm': mode_nasm.Nasm, @@ -253,7 +254,7 @@ class Application(object): b = buffer2.FileBuffer(path, name=name) elif os.path.isdir(path): b = buffer2.DirBuffer(path, name=name) - mode_name = 'fundamental' + mode_name = 'dir' else: raise Exception, "not a file or dir: %r" % path elif cipher == 'aes': diff --git a/buffer2.py b/buffer2.py index a48555b..36357f2 100644 --- a/buffer2.py +++ b/buffer2.py @@ -1,4 +1,4 @@ -import md5, os, sets, shutil +import datetime, md5, os, pwd, re, sets, shutil, stat import aes, regex, highlight2 from point2 import Point @@ -475,6 +475,14 @@ class AesBuffer(FileBuffer): def write_filter(self, data): return aes.encrypt_data(data, self.password) +def _path_sort(a, b): + try: + x = cmp(a[0][0], b[0][0]) + if x != 0: + return -x + return cmp(a[5], b[5]) + except: + raise Exception, repr(a) + ' ' + repr(b) class DirBuffer(Buffer): btype = 'dir' def __init__(self, path, nl='\n', name=None): @@ -490,14 +498,93 @@ class DirBuffer(Buffer): return self._name def path_exists(self): return os.path.exists(self.path) + def open(self): if not self.path_exists(): raise Exception, "directory %r does not exists" % self.path - self.lines = [] + + names = os.listdir(self.path) if self.path != '/': - self.lines.append('..') - for name in os.listdir(self.path): - self.lines.append(name) + names.insert(0, '..') + names.insert(0, '.') + + lines = [] + maxlens = [0] * 5 + for name in names: + # let's escape some troublesome characters + name = re.sub(r'([\a\b\n\r\t\v])', r'\\\1', name) + + path = os.path.join(self.path, name) + info = os.stat(path) + + # - regular, b block, c character, d directory, l symlink, p fifo + # s socket, ? unknown + perm = [' '] * 10 + if stat.S_ISREG(info.st_mode): + perm[0] = '-' + elif stat.S_ISBLK(info.st_mode): + perm[0] = 'b' + elif stat.S_ISCHR(info.st_mode): + perm[0] = 'c' + elif stat.S_ISDIR(info.st_mode): + perm[0] = 'd' + elif stat.S_ISLNK(info.st_mode): + perm[0] = 'l' + elif stat.S_ISFIFO(info.st_mode): + perm[0] = 'p' + elif stat.S_ISSOCK(info.st_mode): + perm[0] = 's' + else: + perm[0] = '?' + + i = 1 + symbols = ('r', 'w', 'x') + for bundle in ((stat.S_IRUSR, stat.S_IWUSR, stat.S_IXUSR), + (stat.S_IRGRP, stat.S_IWGRP, stat.S_IXGRP), + (stat.S_IROTH, stat.S_IWOTH, stat.S_IXOTH)): + for j in range(0, 3): + if info.st_mode & bundle[j]: + perm[i] = symbols[j] + else: + perm[i] = '-' + i += 1 + perms = ''.join(perm) + + try: + usr = pwd.getpwuid(info.st_uid)[0] + except: + usr = str(info.st_uid) + try: + grp = pwd.getpwuid(info.st_gid)[0] + except: + grp = str(info.st_gid) + + size = info.st_size + unit = 0 + units = ('B', 'K', 'M', 'G',) + while unit < 3 and size > 1024: + size = size / 1024 + unit += 1 + size = '%d%s' % (size, units[unit]) + + mtime = datetime.datetime.fromtimestamp(info.st_mtime).strftime('%b %d %H:%M') + + fields = (perms, usr, grp, size, mtime, name) + for i in range(0, 5): + try: + maxlens[i] = max(maxlens[i], len(fields[i])) + except: + raise Exception, '%d %r' % (i, fields[i]) + lines.append(fields) + + lines.sort(cmp=_path_sort) + + fmt = '%%%ds %%-%ds %%-%ds %%%ds %%%ds %%s' % tuple(maxlens) + + self.lines = [] + for fields in lines: + s = fmt % fields + self.lines.append(s) def reload(self): self.open() def save(self, force=False): diff --git a/lex3.py b/lex3.py index ac63c26..7ba33bd 100755 --- a/lex3.py +++ b/lex3.py @@ -137,7 +137,7 @@ class PatternGroupRule(PatternRule): pairs = [] while i < len(args): tokname, pattern = args[i], args[i+1] - pairs.append((name, re.compile(pattern, self.reflags))) + pairs.append((tokname, re.compile(pattern, self.reflags))) i += 2 Rule.__init__(self, name) self.pairs = tuple(pairs) diff --git a/mode_dir.py b/mode_dir.py new file mode 100644 index 0000000..fab5e6e --- /dev/null +++ b/mode_dir.py @@ -0,0 +1,89 @@ +import method, mode2, os.path +from lex3 import Grammar, PatternRule, RegionRule, PatternGroupRule +from point2 import Point + +class PermGrammar(Grammar): + rules = [ + PatternRule(r'set', r's'), + 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.set': ('red', 'default'), + 'perm.read': ('magenta', 'default'), + 'perm.write': ('magenta', 'default'), + 'perm.exec': ('magenta', 'default'), + + 'owner': ('blue', '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_and_bindings(OpenPath(), ('RETURN',)) + def name(self): + return "Dir" + +class Chmod(method.Method): + def _execute(self, w, **vargs): + w.set_error('chmod not implemented') +class Chown(method.Method): + def _execute(self, w, **vargs): + w.set_error('chown not implemented') +class Chgrp(method.Method): + def _execute(self, w, **vargs): + w.set_error('chgrp not implemented') + +class OpenPath(method.Method): + def _execute(self, w, **vargs): + assert w.buffer.btype == 'dir' + c = w.logical_cursor() + p = Point(0, c.y) + t = w.get_next_token_by_type(p, 'name') + path = os.path.join(w.buffer.path, t.string) + w.set_error("opening %r" % path) + w.application.methods['open-file'].execute(w, filename=path) diff --git a/window2.py b/window2.py index 631e92b..edaa7e3 100644 --- a/window2.py +++ b/window2.py @@ -577,10 +577,11 @@ class Window(object): return token return None def get_next_token_by_lambda(self, p, f): - for token in self.get_highlighter().tokens[p.y]: + tokens = self.get_highlighter().tokens[p.y] + for token in tokens: if token.x < p.x: continue - if f(token.name): + if f(token): return token return None def get_next_token_by_type(self, p, name):