From 3de15ddd7fb0151e5f43f0b8e7d06bd76568e235 Mon Sep 17 00:00:00 2001 From: hut Date: Fri, 11 Dec 2009 17:13:59 +0100 Subject: restructurations --- ranger.py | 6 +- ranger/__init__.py | 40 +++---- ranger/applications.py | 2 +- ranger/colorschemes/__init__.py | 10 +- ranger/data/generate.py | 20 ++-- ranger/directory.py | 218 --------------------------------------- ranger/environment.py | 4 +- ranger/ext/__init__.py | 3 - ranger/ext/get_all_modules.py | 8 ++ ranger/ext/log.py | 15 +++ ranger/ext/relpath.py | 5 + ranger/file.py | 4 - ranger/fm.py | 3 + ranger/fsobject.py | 139 ------------------------- ranger/fsobject/__init__.py | 9 ++ ranger/fsobject/directory.py | 223 ++++++++++++++++++++++++++++++++++++++++ ranger/fsobject/file.py | 4 + ranger/fsobject/fsobject.py | 153 +++++++++++++++++++++++++++ ranger/gui/colorscheme.py | 2 +- ranger/gui/wdisplay.py | 8 +- ranger/main.py | 3 +- ranger/shared/mimetype.py | 2 +- test/tc_directory.py | 4 +- 23 files changed, 468 insertions(+), 417 deletions(-) delete mode 100644 ranger/directory.py create mode 100644 ranger/ext/get_all_modules.py create mode 100644 ranger/ext/log.py create mode 100644 ranger/ext/relpath.py delete mode 100644 ranger/file.py delete mode 100644 ranger/fsobject.py create mode 100644 ranger/fsobject/__init__.py create mode 100644 ranger/fsobject/directory.py create mode 100644 ranger/fsobject/file.py create mode 100644 ranger/fsobject/fsobject.py diff --git a/ranger.py b/ranger.py index 090789c5..7ab00a26 100755 --- a/ranger.py +++ b/ranger.py @@ -1,6 +1,6 @@ #!/usr/bin/python # coding=utf-8 -# ranger: Browse your files inside the console. +# ranger: Browse your files inside the terminal. # An embedded shell script. Assuming this file is /usr/bin/ranger, @@ -13,11 +13,13 @@ if [ $1 ]; then cd "`$1 --cd-after-exit $@ 3>&1 1>&2 2>&3 3>&-`" else - echo "use with: source path/to/ranger.py path/to/ranger.py" + echo "usage: source path/to/ranger.py path/to/ranger.py" fi return 1 """ +__doc__ = """Ranger - file browser for the unix terminal""" + try: from ranger.main import main diff --git a/ranger/__init__.py b/ranger/__init__.py index f5a1c480..b26a76cb 100644 --- a/ranger/__init__.py +++ b/ranger/__init__.py @@ -1,30 +1,20 @@ -import os -import sys - -confdir = os.path.expanduser('~/.ranger') -rangerdir = os.path.dirname(__file__) +"""Ranger - file browser for the unix terminal""" -sys.path.append(confdir) +__copyright__ = 'none' +__license__ = 'GPL' +__version__ = '1.0.0' +__credits__ = 'hut' +__author__ = 'hut' +__maintainer__ = 'hut' +__email__ = 'hut@lavabit.com' +import os +import sys -def relpath(*args): - return os.path.join(rangerdir, *args) - -LOGFILE = '/tmp/errorlog' +# for easier access +from ranger.ext.log import log -def log(txt): - f = open(LOGFILE, 'a') - f.write("r1: ") - f.write(str(txt)) - f.write("\n") - f.close() +CONFDIR = os.path.expanduser('~/.ranger') +RANGERDIR = os.path.dirname(__file__) -# used to get all colorschemes in ~/.ranger/colorschemes -# and ranger/colorschemes -def get_all(dirname): - import os - result = [] - for filename in os.listdir(dirname): - if filename.endswith('.py') and not filename.startswith('_'): - result.append(filename[0:filename.index('.')]) - return result +sys.path.append(CONFDIR) diff --git a/ranger/applications.py b/ranger/applications.py index 7f029fde..99a40e93 100644 --- a/ranger/applications.py +++ b/ranger/applications.py @@ -19,7 +19,7 @@ null = open(os.devnull, 'a') def run(*args, **kw): from subprocess import Popen from subprocess import PIPE - from ranger.ext import waitpid_no_intr + from ranger.ext.waitpid_no_intr import waitpid_no_intr flags, fm = kw['flags'], kw['fm'] for flag in flags: diff --git a/ranger/colorschemes/__init__.py b/ranger/colorschemes/__init__.py index 2318ba27..6c710bd8 100644 --- a/ranger/colorschemes/__init__.py +++ b/ranger/colorschemes/__init__.py @@ -1,7 +1,7 @@ -from ranger import get_all, log +from ranger.ext.get_all_modules import get_all_modules from os.path import expanduser, dirname, exists, join -__all__ = get_all(dirname(__file__)) +__all__ = get_all_modules(dirname(__file__)) from ranger.colorschemes import * @@ -9,8 +9,10 @@ confpath = expanduser('~/.ranger') if exists(join(confpath, 'colorschemes')): initpy = join(confpath, 'colorschemes/__init__.py') if not exists(initpy): - open(initpy, 'w').write("""import ranger, os.path -__all__ = ranger.get_all( os.path.dirname( __file__ ) ) + open(initpy, 'w').write("""from ranger.ext.get_all_modules import get_all_modules +from os.path import dirname + +__all__ = get_all_modules(dirname(__file__)) """) try: diff --git a/ranger/data/generate.py b/ranger/data/generate.py index 61309259..fb9e0017 100755 --- a/ranger/data/generate.py +++ b/ranger/data/generate.py @@ -1,16 +1,16 @@ #!/usr/bin/python3 # coding=utf-8 -protocol = 0 +if __name__ == '__main__': + import sys, pickle -import sys, pickle + protocol = 0 + table = {} -table = {} -for line in open(len(sys.argv) > 1 and sys.argv[1] or "mime.types"): - if len(line) > 3 and line[0] != '#' and '\t' in line: - name, *extensions = line.split() - for ext in extensions: - table[ext] = name - -pickle.dump(table, open('mime.dat', 'wb'), protocol) + for line in open(len(sys.argv) > 1 and sys.argv[1] or "mime.types"): + if len(line) > 3 and line[0] != '#' and '\t' in line: + name, *extensions = line.split() + for ext in extensions: + table[ext] = name + pickle.dump(table, open('mime.dat', 'wb'), protocol) diff --git a/ranger/directory.py b/ranger/directory.py deleted file mode 100644 index 258266c0..00000000 --- a/ranger/directory.py +++ /dev/null @@ -1,218 +0,0 @@ -import ranger.fsobject -from ranger.file import File -#from ranger.helper import log - -from ranger.fsobject import BAD_INFO -from ranger.fsobject import FileSystemObject as SuperClass -from ranger.shared import SettingsAware - -def sort_by_basename(path): - return path.basename - -def sort_by_directory(path): - return -int( isinstance( path, Directory ) ) - -class NoDirectoryGiven(Exception): - pass - -class Directory(SuperClass, SettingsAware): - def __init__(self, path): - from os.path import isfile - - if isfile(path): - raise NoDirectoryGiven() - - SuperClass.__init__(self, path) - self.content_loaded = False - self.scheduled = False - self.enterable = False - - self.filenames = None - self.files = None - self.filter = None - self.pointed_index = None - self.pointed_file = None - self.scroll_begin = 0 - - # to find out if something has changed: - self.old_show_hidden = self.settings.show_hidden - self.old_directories_first = self.settings.directories_first - - def load_content(self): - from os.path import join, isdir, basename - from os import listdir - - self.load_if_outdated() - self.content_loaded = True - - if self.exists and self.runnable: - filenames = [] - for fname in listdir(self.path): - if not self.settings.show_hidden and fname[0] == '.': - continue - if isinstance(self.filter, str) and self.filter in fname: - continue - filenames.append(join(self.path, fname)) - self.scroll_offset = 0 - self.filenames = filenames - self.infostring = ' %d' % len(self.filenames) # update the infostring - files = [] - for name in self.filenames: - if isdir(name): - f = Directory(name) - else: - f = File(name) - f.load() - files.append(f) - - self.files = files - self.old_directories_first = None -# self.sort() - - if len(self.files) > 0: - if self.pointed_file is not None: - self.move_pointer_to_file_path(self.pointed_file) -# if self.pointed_file is None: -# self.correct_pointer() - else: - self.filenames = None - self.files = None - self.infostring = BAD_INFO - - def sort(self): - if self.files is None: - return - - old_pointed_file = self.pointed_file - self.files.sort(key = sort_by_basename) - - if self.settings.directories_first: - self.files.sort(key = sort_by_directory) - - if self.pointed_index is not None: - self.move_pointer_to_file_path(old_pointed_file) - else: - self.correct_pointer() - - self.old_directories_first = self.settings.directories_first - - def sort_if_outdated(self): - if self.old_directories_first != self.settings.directories_first: - self.sort() - - # Notice: fm.env.cf should always point to the current file. If you - # modify the current directory with this function, make sure - # to update fm.env.cf aswell. - def move_pointer(self, relative=0, absolute=None): - if self.empty(): return - i = self.pointed_index - if isinstance(absolute, int): - if absolute < 0: - absolute = len(self.files) + absolute - i = absolute - - if isinstance(relative, int): - i += relative - - self.pointed_index = i - self.correct_pointer() - return self.pointed_file - - def move_pointer_to_file_path(self, path): - if path is None: return - try: path = path.path - except AttributeError: pass - - self.load_content_once() - if self.empty(): return - - i = 0 - for f in self.files: - if f.path == path: - self.move_pointer(absolute = i) - return True - i += 1 - return False - - def search(self, arg, direction = 1): - if self.empty() or arg is None: - return False - elif hasattr(arg, 'search'): - fnc = lambda x: arg.search(x.basename) - else: - fnc = lambda x: arg in x.basename - - length = len(self) - - if direction > 0: - generator = ((self.pointed_index + (x + 1)) % length for x in range(length-1)) - else: - generator = ((self.pointed_index - (x + 1)) % length for x in range(length-1)) - - for i in generator: - _file = self.files[i] - if fnc(_file): - self.pointed_index = i - self.pointed_file = _file - return True - return False - - def correct_pointer(self): - """make sure the pointer is in the valid range of 0 : len(self.files)-1 (or None if directory is empty.)""" - - if self.files is None or len(self.files) == 0: - self.pointed_index = None - self.pointed_file = None - - else: - i = self.pointed_index - - if i is None: i = 0 - if i >= len(self.files): i = len(self.files) - 1 - if i < 0: i = 0 - - self.pointed_index = i - self.pointed_file = self[i] - - def load_content_once(self): - if not self.content_loaded: - self.load_content() - return True - return False - - def load_content_if_outdated(self): - if self.load_content_once(): return True - - if self.old_show_hidden != self.settings.show_hidden: - self.old_show_hidden = self.settings.show_hidden - self.load_content() - return True - - import os - real_mtime = os.stat(self.path).st_mtime - cached_mtime = self.stat.st_mtime - - if real_mtime != cached_mtime: - self.load_content() - return True - return False - - def empty(self): - return self.files is None or len(self.files) == 0 - - def __nonzero__(self): - return True - - def __len__(self): - if not self.accessible: raise ranger.fsobject.NotLoadedYet() - return len(self.files) - - def __getitem__(self, key): - if not self.accessible: raise ranger.fsobject.NotLoadedYet() - return self.files[key] - - def __eq__(self, other): - return isinstance(other, Directory) and self.path == other.path - - def __neq__(self, other): - return not self.__eq__(other) diff --git a/ranger/environment.py b/ranger/environment.py index 8e45516b..d7097fc8 100644 --- a/ranger/environment.py +++ b/ranger/environment.py @@ -1,5 +1,5 @@ from os.path import abspath, normpath, join, expanduser -from ranger.directory import Directory, NoDirectoryGiven +from ranger.fsobject.directory import Directory, NoDirectoryGiven from ranger.container import KeyBuffer, History from ranger.shared import SettingsAware @@ -42,7 +42,7 @@ class Environment(SettingsAware): return self.cf def garbage_collect(self): - from ranger.fsobject import FileSystemObject + from ranger.fsobject.fsobject import FileSystemObject for key in tuple(self.directories.keys()): value = self.directories[key] if isinstance(value, FileSystemObject): diff --git a/ranger/ext/__init__.py b/ranger/ext/__init__.py index f09324b7..e69de29b 100644 --- a/ranger/ext/__init__.py +++ b/ranger/ext/__init__.py @@ -1,3 +0,0 @@ -from .openstruct import OpenStruct -from .human_readable import human_readable -from .waitpid_no_intr import waitpid_no_intr diff --git a/ranger/ext/get_all_modules.py b/ranger/ext/get_all_modules.py new file mode 100644 index 00000000..2d98278b --- /dev/null +++ b/ranger/ext/get_all_modules.py @@ -0,0 +1,8 @@ +def get_all_modules(dirname): + """returns a list of strings containing the names of modules in a directory""" + import os + result = [] + for filename in os.listdir(dirname): + if filename.endswith('.py') and not filename.startswith('_'): + result.append(filename[0:filename.index('.')]) + return result diff --git a/ranger/ext/log.py b/ranger/ext/log.py new file mode 100644 index 00000000..9f56dd71 --- /dev/null +++ b/ranger/ext/log.py @@ -0,0 +1,15 @@ +LOGFILE = '/tmp/errorlog' + +def log(*objects, **keywords): + """Writes objects to a logfile. +Has the same arguments as print() in python3""" + start = 'start' in keywords and keywords['start'] or 'ranger:' + sep = 'sep' in keywords and keywords['sep'] or ' ' + _file = 'file' in keywords and keywords['file'] or open(LOGFILE, 'a') + end = 'end' in keywords and keywords['end'] or '\n' + _file.write(sep.join((start, ) + objects) + end) + +#for python3-only versions, this could be replaced with: +# +#def log(*objects, start='ranger:', sep=' ', end='\n'): +# print(start, *objects, end=end, sep=sep, file=open(LOGFILE, 'a')) diff --git a/ranger/ext/relpath.py b/ranger/ext/relpath.py new file mode 100644 index 00000000..46d8018d --- /dev/null +++ b/ranger/ext/relpath.py @@ -0,0 +1,5 @@ +def relpath(*paths): + """returns the path relative to rangers library directory""" + from os.path import join + from ranger import RANGERDIR + return join(RANGERDIR, *paths) diff --git a/ranger/file.py b/ranger/file.py deleted file mode 100644 index e95067b1..00000000 --- a/ranger/file.py +++ /dev/null @@ -1,4 +0,0 @@ -from ranger.fsobject import FileSystemObject as SuperClass -class File(SuperClass): - pass - diff --git a/ranger/fm.py b/ranger/fm.py index 2b4b32e4..cdcfb8d7 100644 --- a/ranger/fm.py +++ b/ranger/fm.py @@ -1,5 +1,8 @@ from ranger.actions import Actions from ranger.container import Bookmarks +from ranger import __version__ + +USAGE = '''%s [options] [path/filename]''' class FM(Actions): def __init__(self, ui = None, bookmarks = None): diff --git a/ranger/fsobject.py b/ranger/fsobject.py deleted file mode 100644 index 35d0d5b3..00000000 --- a/ranger/fsobject.py +++ /dev/null @@ -1,139 +0,0 @@ -class NotLoadedYet(Exception): - pass - -T_FILE = 'file' -T_DIRECTORY = 'directory' -T_UNKNOWN = 'unknown' -T_NONEXISTANT = 'nonexistant' - -BAD_INFO = None - -CONTAINER_EXTENSIONS = 'rar zip tar gz bz bz2 tgz 7z iso cab'.split() -DOCUMENT_EXTENSIONS = 'pdf doc ppt odt'.split() -DOCUMENT_BASENAMES = 'README TODO LICENSE'.split() - -from ranger.shared import MimeTypeAware, FileManagerAware -class FileSystemObject(MimeTypeAware, FileManagerAware): - - def __init__(self, path): - MimeTypeAware.__init__(self) - if type(self) == FileSystemObject: - raise TypeError("FileSystemObject is an abstract class and cannot be initialized.") - - from os.path import basename, dirname - - self.path = path - self.basename = basename(path) - self.dirname = dirname(path) - try: - self.extension = self.basename[self.basename.rindex('.') + 1:] - except ValueError: - self.extension = None - self.exists = False - self.accessible = False - self.marked = False - self.tagged = False - self.frozen = False - self.loaded = False - self.runnable = False - self.islink = False - self.brokenlink = False - self.stat = None - self.infostring = None - self.permissions = None - self.type = T_UNKNOWN - - self.set_mimetype() - self.use() - - def __str__(self): - return str(self.path) - - def use(self): - import time - self.last_used = time.time() - - def is_older_than(self, seconds): - import time - return self.last_used + seconds < time.time() - - def set_mimetype(self): - try: - self.mimetype = self.mimetypes[self.extension] - except KeyError: - self.mimetype = '' - - self.video = self.mimetype.startswith('video') - self.image = self.mimetype.startswith('image') - self.audio = self.mimetype.startswith('audio') - self.media = self.video or self.image or self.audio - self.document = self.mimetype.startswith('text') or (self.extension in DOCUMENT_EXTENSIONS) or (self.basename in DOCUMENT_BASENAMES) - self.container = self.extension in CONTAINER_EXTENSIONS - - keys = ('video', 'audio', 'image', 'media', 'document', 'container') - self.mimetype_tuple = tuple(key for key in keys if getattr(self, key)) - - if self.mimetype == '': - self.mimetype = None - - # load() reads useful information about the file from the file system - # and caches it in instance attributes. - def load(self): - import os - from ranger.ext import human_readable - - self.loaded = True - - if os.access(self.path, os.F_OK): - self.stat = os.stat(self.path) - self.islink = os.path.islink(self.path) - self.exists = True - self.accessible = True - - if os.path.isdir(self.path): - self.type = T_DIRECTORY - try: - self.size = len(os.listdir(self.path)) - self.infostring = ' %d' % self.size - self.runnable = True - except OSError: - self.infostring = BAD_INFO - self.runnable = False - self.accessible = False - elif os.path.isfile(self.path): - self.type = T_FILE - self.size = self.stat.st_size - self.infostring = ' ' + human_readable(self.stat.st_size) - else: - self.type = T_UNKNOWN - self.infostring = None - - else: - self.stat = None - self.islink = False - self.infostring = None - self.type = T_NONEXISTANT - self.exists = False - self.runnable = False - self.accessible = False - - def load_once(self): - if not self.loaded: - self.load() - return True - return False - - def go(self): - self.fm.enter_dir(self.path) - - def load_if_outdated(self): - if self.load_once(): return True - - import os - real_mtime = os.stat(self.path).st_mtime - cached_mtime = self.stat.st_mtime - - if real_mtime != cached_mtime: - self.load() - return True - return False diff --git a/ranger/fsobject/__init__.py b/ranger/fsobject/__init__.py new file mode 100644 index 00000000..2d6da282 --- /dev/null +++ b/ranger/fsobject/__init__.py @@ -0,0 +1,9 @@ +T_FILE = 'file' +T_DIRECTORY = 'directory' +T_UNKNOWN = 'unknown' +T_NONEXISTANT = 'nonexistant' + +BAD_INFO = None + +class NotLoadedYet(Exception): + pass diff --git a/ranger/fsobject/directory.py b/ranger/fsobject/directory.py new file mode 100644 index 00000000..cdcbc2ed --- /dev/null +++ b/ranger/fsobject/directory.py @@ -0,0 +1,223 @@ +from . import BAD_INFO +from .file import File +from .fsobject import FileSystemObject as SuperClass +from ranger.shared import SettingsAware +import ranger.fsobject + +def sort_by_basename(path): + """returns path.basename (for sorting)""" + return path.basename + +def sort_by_directory(path): + """returns 0 if path is a directory, otherwise 1 (for sorting)""" + return 1 - int( isinstance( path, Directory ) ) + +class NoDirectoryGiven(Exception): + pass + +class Directory(SuperClass, SettingsAware): + content_loaded = False + scheduled = False + enterable = False + + filenames = None + files = None + filter = None + pointed_index = None + pointed_file = None + scroll_begin = 0 + scroll_offset = 0 + + old_show_hidden = None + old_directories_first = None + + def __init__(self, path): + from os.path import isfile + + if isfile(path): + raise NoDirectoryGiven() + + SuperClass.__init__(self, path) + + # to find out if something has changed: + self.old_show_hidden = self.settings.show_hidden + self.old_directories_first = self.settings.directories_first + + def load_content(self): + from os.path import join, isdir, basename + from os import listdir + + self.load_if_outdated() + self.content_loaded = True + + if self.exists and self.runnable: + filenames = [] + for fname in listdir(self.path): + if not self.settings.show_hidden and fname[0] == '.': + continue + if isinstance(self.filter, str) and self.filter in fname: + continue + filenames.append(join(self.path, fname)) + self.scroll_offset = 0 + self.filenames = filenames + self.infostring = ' %d' % len(self.filenames) # update the infostring + files = [] + for name in self.filenames: + if isdir(name): + f = Directory(name) + else: + f = File(name) + f.load() + files.append(f) + + self.files = files + self.old_directories_first = None +# self.sort() + + if len(self.files) > 0: + if self.pointed_file is not None: + self.move_pointer_to_file_path(self.pointed_file) +# if self.pointed_file is None: +# self.correct_pointer() + else: + self.filenames = None + self.files = None + self.infostring = BAD_INFO + + def sort(self): + if self.files is None: + return + + old_pointed_file = self.pointed_file + self.files.sort(key = sort_by_basename) + + if self.settings.directories_first: + self.files.sort(key = sort_by_directory) + + if self.pointed_index is not None: + self.move_pointer_to_file_path(old_pointed_file) + else: + self.correct_pointer() + + self.old_directories_first = self.settings.directories_first + + def sort_if_outdated(self): + if self.old_directories_first != self.settings.directories_first: + self.sort() + + # Notice: fm.env.cf should always point to the current file. If you + # modify the current directory with this function, make sure + # to update fm.env.cf aswell. + def move_pointer(self, relative=0, absolute=None): + if self.empty(): return + i = self.pointed_index + if isinstance(absolute, int): + if absolute < 0: + absolute = len(self.files) + absolute + i = absolute + + if isinstance(relative, int): + i += relative + + self.pointed_index = i + self.correct_pointer() + return self.pointed_file + + def move_pointer_to_file_path(self, path): + if path is None: return + try: path = path.path + except AttributeError: pass + + self.load_content_once() + if self.empty(): return + + i = 0 + for f in self.files: + if f.path == path: + self.move_pointer(absolute = i) + return True + i += 1 + return False + + def search(self, arg, direction = 1): + if self.empty() or arg is None: + return False + elif hasattr(arg, 'search'): + fnc = lambda x: arg.search(x.basename) + else: + fnc = lambda x: arg in x.basename + + length = len(self) + + if direction > 0: + generator = ((self.pointed_index + (x + 1)) % length for x in range(length-1)) + else: + generator = ((self.pointed_index - (x + 1)) % length for x in range(length-1)) + + for i in generator: + _file = self.files[i] + if fnc(_file): + self.pointed_index = i + self.pointed_file = _file + return True + return False + + def correct_pointer(self): + """make sure the pointer is in the valid range of 0 : len(self.files)-1 (or None if directory is empty.)""" + + if self.files is None or len(self.files) == 0: + self.pointed_index = None + self.pointed_file = None + + else: + i = self.pointed_index + + if i is None: i = 0 + if i >= len(self.files): i = len(self.files) - 1 + if i < 0: i = 0 + + self.pointed_index = i + self.pointed_file = self[i] + + def load_content_once(self): + if not self.content_loaded: + self.load_content() + return True + return False + + def load_content_if_outdated(self): + if self.load_content_once(): return True + + if self.old_show_hidden != self.settings.show_hidden: + self.old_show_hidden = self.settings.show_hidden + self.load_content() + return True + + import os + real_mtime = os.stat(self.path).st_mtime + cached_mtime = self.stat.st_mtime + + if real_mtime != cached_mtime: + self.load_content() + return True + return False + + def empty(self): + return self.files is None or len(self.files) == 0 + + def __nonzero__(self): + return True + + def __len__(self): + if not self.accessible: raise ranger.fsobject.NotLoadedYet() + return len(self.files) + + def __getitem__(self, key): + if not self.accessible: raise ranger.fsobject.NotLoadedYet() + return self.files[key] + + def __eq__(self, other): + return isinstance(other, Directory) and self.path == other.path + + def __neq__(self, other): + return not self.__eq__(other) diff --git a/ranger/fsobject/file.py b/ranger/fsobject/file.py new file mode 100644 index 00000000..9087eab6 --- /dev/null +++ b/ranger/fsobject/file.py @@ -0,0 +1,4 @@ +from .fsobject import FileSystemObject as SuperClass +class File(SuperClass): + pass + diff --git a/ranger/fsobject/fsobject.py b/ranger/fsobject/fsobject.py new file mode 100644 index 00000000..20b47813 --- /dev/null +++ b/ranger/fsobject/fsobject.py @@ -0,0 +1,153 @@ +CONTAINER_EXTENSIONS = 'rar zip tar gz bz bz2 tgz 7z iso cab'.split() +DOCUMENT_EXTENSIONS = 'pdf doc ppt odt'.split() +DOCUMENT_BASENAMES = 'README TODO LICENSE'.split() + +from . import T_FILE, T_DIRECTORY, T_UNKNOWN, T_NONEXISTANT, BAD_INFO +from ranger.shared import MimeTypeAware, FileManagerAware +class FileSystemObject(MimeTypeAware, FileManagerAware): + path = None + basename = None + dirname = None + extension = None + exists = False + accessible = False + marked = False + tagged = False + frozen = False + loaded = False + runnable = False + islink = False + brokenlink = False + stat = None + infostring = None + permissions = None + type = T_UNKNOWN + + last_used = None + + video = False + image = False + audio = False + media = False + document = False + container = False + mimetype_tuple = () + + def __init__(self, path): + MimeTypeAware.__init__(self) + if type(self) == FileSystemObject: + raise TypeError("FileSystemObject is an abstract class and cannot be initialized.") + + from os.path import basename, dirname + + self.path = path + self.basename = basename(path) + self.dirname = dirname(path) + + try: + self.extension = self.basename[self.basename.rindex('.') + 1:] + except ValueError: + self.extension = None + + self.set_mimetype() + self.use() + + def __str__(self): + """returns a string containing the absolute path""" + return str(self.path) + + def use(self): + """mark the filesystem-object as used at the current time""" + import time + self.last_used = time.time() + + def is_older_than(self, seconds): + """returns whether this object wasn't use()d in the last n seconds""" + import time + return self.last_used + seconds < time.time() + + def set_mimetype(self): + """assign attributes such as self.video according to the mimetype""" + try: + self.mimetype = self.mimetypes[self.extension] + except KeyError: + self.mimetype = '' + + self.video = self.mimetype.startswith('video') + self.image = self.mimetype.startswith('image') + self.audio = self.mimetype.startswith('audio') + self.media = self.video or self.image or self.audio + self.document = self.mimetype.startswith('text') or (self.extension in DOCUMENT_EXTENSIONS) or (self.basename in DOCUMENT_BASENAMES) + self.container = self.extension in CONTAINER_EXTENSIONS + + keys = ('video', 'audio', 'image', 'media', 'document', 'container') + self.mimetype_tuple = tuple(key for key in keys if getattr(self, key)) + + if self.mimetype == '': + self.mimetype = None + + def load(self): + """reads useful information about the filesystem-object from the filesystem +and caches it for later use""" + import os + from ranger.ext.human_readable import human_readable + + self.loaded = True + + if os.access(self.path, os.F_OK): + self.stat = os.stat(self.path) + self.islink = os.path.islink(self.path) + self.exists = True + self.accessible = True + + if os.path.isdir(self.path): + self.type = T_DIRECTORY + try: + self.size = len(os.listdir(self.path)) + self.infostring = ' %d' % self.size + self.runnable = True + except OSError: + self.infostring = BAD_INFO + self.runnable = False + self.accessible = False + elif os.path.isfile(self.path): + self.type = T_FILE + self.size = self.stat.st_size + self.infostring = ' ' + human_readable(self.stat.st_size) + else: + self.type = T_UNKNOWN + self.infostring = None + + else: + self.stat = None + self.islink = False + self.infostring = None + self.type = T_NONEXISTANT + self.exists = False + self.runnable = False + self.accessible = False + + def load_once(self): + """calls load() if it has not been called at least once yet""" + if not self.loaded: + self.load() + return True + return False + + def go(self): + """enter the directory if the filemanager is running""" + if self.fm: + self.fm.enter_dir(self.path) + + def load_if_outdated(self): + """calls load() if the currently cached information is outdated or nonexistant""" + if self.load_once(): return True + + import os + real_mtime = os.stat(self.path).st_mtime + cached_mtime = self.stat.st_mtime + + if real_mtime != cached_mtime: + self.load() + return True + return False diff --git a/ranger/gui/colorscheme.py b/ranger/gui/colorscheme.py index 281396a5..38f4ac5a 100644 --- a/ranger/gui/colorscheme.py +++ b/ranger/gui/colorscheme.py @@ -28,7 +28,7 @@ CONTEXT_KEYS = [ 'reset', 'error', # If your colorscheme-file contains more than one colorscheme, specify it with: # colorscheme = colorschemes.filename.classname -from ranger.ext import OpenStruct +from ranger.ext.openstruct import OpenStruct class ColorScheme(object): def __init__(self): diff --git a/ranger/gui/wdisplay.py b/ranger/gui/wdisplay.py index 5e5e80d6..c7e78b8e 100644 --- a/ranger/gui/wdisplay.py +++ b/ranger/gui/wdisplay.py @@ -12,7 +12,7 @@ class WDisplay(SuperClass): self.target = env.at_level(self.level) def click(self, event, fm): - from ranger.fsobject import T_DIRECTORY + from ranger.fsobject.fsobject import T_DIRECTORY if self.target is None: pass @@ -38,8 +38,8 @@ class WDisplay(SuperClass): fm.move_right() def draw(self): - from ranger.file import File - from ranger.directory import Directory + from ranger.fsobject.file import File + from ranger.fsobject.directory import Directory if self.target is None: pass @@ -66,7 +66,7 @@ class WDisplay(SuperClass): pass def draw_directory(self): - from ranger.directory import Directory + from ranger.fsobject.directory import Directory import curses import stat diff --git a/ranger/main.py b/ranger/main.py index 1cac2873..48297a7c 100644 --- a/ranger/main.py +++ b/ranger/main.py @@ -6,13 +6,14 @@ from optparse import OptionParser, SUPPRESS_HELP from ranger.fm import FM from ranger.environment import Environment from ranger.gui.defaultui import DefaultUI as UI -from ranger.file import File +from ranger.fsobject.file import File VERSION = '1.0.0' USAGE = '''%s [options] [path/filename]''' def main(): + """initialize objects and run the filemanager""" try: import curses except ImportError as errormessage: diff --git a/ranger/shared/mimetype.py b/ranger/shared/mimetype.py index ac4ff629..8cc658fb 100644 --- a/ranger/shared/mimetype.py +++ b/ranger/shared/mimetype.py @@ -1,4 +1,4 @@ -from ranger import relpath +from ranger.ext.relpath import relpath class MimeTypeAware(object): mimetypes = {} __initialized = False diff --git a/test/tc_directory.py b/test/tc_directory.py index 7faeb7d2..92a4f01c 100644 --- a/test/tc_directory.py +++ b/test/tc_directory.py @@ -4,8 +4,8 @@ if __name__ == '__main__': sys.path.append(abspath(join(sys.path[0], '..'))) from ranger import fsobject -from ranger.file import File -from ranger.directory import Directory +from ranger.fsobject.file import File +from ranger.fsobject.directory import Directory from os.path import realpath, join, dirname TESTDIR = realpath(join(dirname(__file__), 'testdir')) -- cgit 1.4.1-2-gfad0