diff options
author | hut <hut@lavabit.com> | 2010-10-02 05:51:17 +0200 |
---|---|---|
committer | hut <hut@lavabit.com> | 2010-10-02 05:51:17 +0200 |
commit | a457053815d72ef5d7ccfedbfda02101665bdec6 (patch) | |
tree | 5ea00e015b6488f0874c626e61bc64c62e514b9c /ranger/core | |
parent | ba16a2e43a71f3ee1a66ffaf1613bb1cce1665fc (diff) | |
download | ranger-a457053815d72ef5d7ccfedbfda02101665bdec6.tar.gz |
a little restructuration
Diffstat (limited to 'ranger/core')
-rw-r--r-- | ranger/core/actions.py | 3 | ||||
-rw-r--r-- | ranger/core/environment.py | 2 | ||||
-rw-r--r-- | ranger/core/fm.py | 21 | ||||
-rw-r--r-- | ranger/core/helper.py | 167 | ||||
-rw-r--r-- | ranger/core/loader.py | 2 | ||||
-rw-r--r-- | ranger/core/main.py | 98 | ||||
-rw-r--r-- | ranger/core/shared.py | 73 |
7 files changed, 360 insertions, 6 deletions
diff --git a/ranger/core/actions.py b/ranger/core/actions.py index a19927a4..59902bab 100644 --- a/ranger/core/actions.py +++ b/ranger/core/actions.py @@ -26,7 +26,8 @@ from ranger.ext.direction import Direction from ranger.ext.relative_symlink import relative_symlink from ranger.ext.shell_escape import shell_quote from ranger import fsobject -from ranger.shared import FileManagerAware, EnvironmentAware, SettingsAware +from ranger.core.shared import FileManagerAware, EnvironmentAware, \ + SettingsAware from ranger.fsobject import File from ranger.ext import shutil_generatorized as shutil_g from ranger.core.loader import LoadableObject diff --git a/ranger/core/environment.py b/ranger/core/environment.py index 8d4c60df..655054d7 100644 --- a/ranger/core/environment.py +++ b/ranger/core/environment.py @@ -22,7 +22,7 @@ from os.path import abspath, normpath, join, expanduser, isdir from ranger.fsobject import Directory from ranger.container import KeyBuffer, KeyManager, History from ranger.ext.signal_dispatcher import SignalDispatcher -from ranger.shared import SettingsAware +from ranger.core.shared import SettingsAware ALLOWED_CONTEXTS = ('browser', 'pager', 'embedded_pager', 'taskview', 'console') diff --git a/ranger/core/fm.py b/ranger/core/fm.py index 05b3e52b..7f655aa6 100644 --- a/ranger/core/fm.py +++ b/ranger/core/fm.py @@ -19,6 +19,7 @@ The File Manager, putting the pieces together from time import time from collections import deque +import mimetypes import os import sys @@ -28,7 +29,6 @@ from ranger.container.tags import Tags from ranger.gui.defaultui import DefaultUI from ranger.container import Bookmarks from ranger.core.runner import Runner -from ranger import relpath_conf from ranger.ext.get_executables import get_executables from ranger.fsobject import Directory from ranger.ext.signal_dispatcher import SignalDispatcher @@ -69,7 +69,7 @@ class FM(Actions, SignalDispatcher): if ranger.arg.clean: bookmarkfile = None else: - bookmarkfile = relpath_conf('bookmarks') + bookmarkfile = self.confpath('bookmarks') self.bookmarks = Bookmarks( bookmarkfile=bookmarkfile, bookmarktype=Directory, @@ -80,7 +80,7 @@ class FM(Actions, SignalDispatcher): self.bookmarks = bookmarks if not ranger.arg.clean and self.tags is None: - self.tags = Tags(relpath_conf('tagged')) + self.tags = Tags(self.confpath('tagged')) if self.ui is None: self.ui = DefaultUI() @@ -93,6 +93,10 @@ class FM(Actions, SignalDispatcher): self.env.signal_bind('cd', self._update_current_tab) + mimetypes.knownfiles.append(os.path.expanduser('~/.mime.types')) + mimetypes.knownfiles.append(self.relpath('data/mime.types')) + self.mimetypes = mimetypes.MimeTypes() + def block_input(self, sec=0): self.input_blocked = sec != 0 self.input_blocked_until = time() + sec @@ -102,6 +106,17 @@ class FM(Actions, SignalDispatcher): self.input_blocked = False return self.input_blocked + def confpath(self, *paths): + """returns the path relative to rangers configuration directory""" + if ranger.arg.clean: + assert 0, "Should not access relpath_conf in clean mode!" + else: + return os.path.join(ranger.arg.confdir, *paths) + + def relpath(self, *paths): + """returns the path relative to rangers library directory""" + return os.path.join(ranger.RANGERDIR, *paths) + def loop(self): """ The main loop consists of: diff --git a/ranger/core/helper.py b/ranger/core/helper.py new file mode 100644 index 00000000..c7ac3702 --- /dev/null +++ b/ranger/core/helper.py @@ -0,0 +1,167 @@ +# Copyright (C) 2009, 2010 Roman Zimbelmann <romanz@lavabit.com> +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +"""Helper functions""" + +import os.path +import sys +from ranger import * + +def parse_arguments(): + """Parse the program arguments""" + from optparse import OptionParser, SUPPRESS_HELP + from ranger import __version__, USAGE, DEFAULT_CONFDIR + from ranger.ext.openstruct import OpenStruct + from os.path import expanduser + + minor_version = __version__[2:] # assumes major version number is <10 + if '.' in minor_version: + minor_version = minor_version[:minor_version.find('.')] + version_tag = ' (stable)' if int(minor_version) % 2 == 0 else ' (testing)' + if __version__.endswith('.0'): + version_string = 'ranger ' + __version__[:-2] + version_tag + else: + version_string = 'ranger ' + __version__ + version_tag + + parser = OptionParser(usage=USAGE, version=version_string) + + parser.add_option('-d', '--debug', action='store_true', + help="activate debug mode") + parser.add_option('-c', '--clean', action='store_true', + help="don't touch/require any config files. ") + parser.add_option('--fail-if-run', action='store_true', # COMPAT + help=SUPPRESS_HELP) + parser.add_option('--fail-unless-cd', action='store_true', + help="experimental: return the exit code 1 if ranger is" \ + "used to run a file (with `ranger filename`)") + parser.add_option('-r', '--confdir', type='string', + metavar='dir', default=DEFAULT_CONFDIR, + help="the configuration directory. (%default)") + parser.add_option('-m', '--mode', type='int', default=0, metavar='n', + help="if a filename is supplied, run it with this mode") + parser.add_option('-f', '--flags', type='string', default='', + metavar='string', + help="if a filename is supplied, run it with these flags.") + + options, positional = parser.parse_args() + arg = OpenStruct(options.__dict__, targets=positional) + arg.confdir = expanduser(arg.confdir) + if arg.fail_if_run: + arg.fail_unless_cd = arg.fail_if_run + del arg['fail_if_run'] + + return arg + + +def load_settings(fm, clean): + import ranger.core.shared + import ranger.api.commands + import ranger.api.keys + if not clean: + allow_access_to_confdir(ranger.arg.confdir, True) + + # Load commands + comcont = ranger.api.commands.CommandContainer() + ranger.api.commands.alias = comcont.alias + try: + import commands + comcont.load_commands_from_module(commands) + except ImportError: + pass + from ranger.defaults import commands + comcont.load_commands_from_module(commands) + commands = comcont + + # Load apps + try: + import apps + except ImportError: + from ranger.defaults import apps + + # Load keys + keymanager = ranger.core.shared.EnvironmentAware.env.keymanager + ranger.api.keys.keymanager = keymanager + from ranger.defaults import keys + try: + import keys + except ImportError: + pass + allow_access_to_confdir(ranger.arg.confdir, False) + else: + comcont = ranger.api.commands.CommandContainer() + ranger.api.commands.alias = comcont.alias + from ranger.api import keys + keymanager = ranger.core.shared.EnvironmentAware.env.keymanager + ranger.api.keys.keymanager = keymanager + from ranger.defaults import commands, keys, apps + comcont.load_commands_from_module(commands) + commands = comcont + fm.commands = commands + fm.keys = keys + fm.apps = apps.CustomApplications() + + +def load_apps(fm, clean): + import ranger + if not clean: + allow_access_to_confdir(ranger.arg.confdir, True) + try: + import apps + except ImportError: + from ranger.defaults import apps + allow_access_to_confdir(ranger.arg.confdir, False) + else: + from ranger.defaults import apps + fm.apps = apps.CustomApplications() + + +def allow_access_to_confdir(confdir, allow): + if allow: + try: + os.makedirs(confdir) + except OSError as err: + if err.errno != 17: # 17 means it already exists + print("This configuration directory could not be created:") + print(confdir) + print("To run ranger without the need for configuration") + print("files, use the --clean option.") + raise SystemExit() + if not confdir in sys.path: + sys.path[0:0] = [confdir] + else: + if sys.path[0] == confdir: + del sys.path[0] + + +# Debugging functions. These will be activated when run with --debug. +# Example usage in the code: +# import ranger; ranger.log("hello world") +def log(*objects, **keywords): + """ + Writes objects to a logfile (for the purpose of debugging only.) + Has the same arguments as print() in python3. + """ + if LOGFILE is None or not arg.debug or arg.clean: return + 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(map(str, (start, ) + objects)) + end) + + +def log_traceback(): + if LOGFILE is None or not arg.debug or arg.clean: return + import traceback + traceback.print_stack(file=open(LOGFILE, 'a')) diff --git a/ranger/core/loader.py b/ranger/core/loader.py index 4f4424e4..ae6436a1 100644 --- a/ranger/core/loader.py +++ b/ranger/core/loader.py @@ -15,7 +15,7 @@ from collections import deque from time import time -from ranger.shared import FileManagerAware +from ranger.core.shared import FileManagerAware import math def status_generator(): diff --git a/ranger/core/main.py b/ranger/core/main.py new file mode 100644 index 00000000..42118516 --- /dev/null +++ b/ranger/core/main.py @@ -0,0 +1,98 @@ +# Copyright (C) 2009, 2010 Roman Zimbelmann <romanz@lavabit.com> +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +""" +The main function responsible to initialize the FM object and stuff. +""" + +from ranger.core.helper import * + +def main(): + """initialize objects and run the filemanager""" + import locale + import os.path + import ranger + from ranger.ext import curses_interrupt_handler + from ranger.core.runner import Runner + from ranger.core.fm import FM + from ranger.core.environment import Environment + from ranger.gui.defaultui import DefaultUI as UI + from ranger.fsobject import File + from ranger.core.shared import (EnvironmentAware, FileManagerAware, + SettingsAware) + + try: + locale.setlocale(locale.LC_ALL, '') + except: + print("Warning: Unable to set locale. Expect encoding problems.") + + if not 'SHELL' in os.environ: + os.environ['SHELL'] = 'bash' + + ranger.arg = arg = parse_arguments() + SettingsAware._setup(clean=arg.clean) + + targets = arg.targets or ['.'] + target = targets[0] + if arg.targets: + if target.startswith('file://'): + target = target[7:] + if not os.access(target, os.F_OK): + print("File or directory doesn't exist: %s" % target) + sys.exit(1) + elif os.path.isfile(target): + def print_function(string): + print(string) + runner = Runner(logfunc=print_function) + load_apps(runner, arg.clean) + runner(files=[File(target)], mode=arg.mode, flags=arg.flags) + sys.exit(1 if arg.fail_unless_cd else 0) + + crash_traceback = None + try: + # Initialize objects + EnvironmentAware.env = Environment(target) + fm = FM() + fm.tabs = dict((n+1, os.path.abspath(path)) for n, path \ + in enumerate(targets[:9])) + load_settings(fm, arg.clean) + if fm.env.username == 'root': + fm.settings.preview_files = False + FileManagerAware.fm = fm + fm.ui = UI() + if not arg.debug: + curses_interrupt_handler.install_interrupt_handler() + + # Run the file manager + fm.initialize() + fm.ui.initialize() + fm.loop() + except Exception: + import traceback + crash_traceback = traceback.format_exc() + except SystemExit as error: + return error.args[0] + finally: + try: + fm.ui.destroy() + except (AttributeError, NameError): + pass + if crash_traceback: + print(crash_traceback) + print("Ranger crashed. " \ + "Please report this (including the traceback) at:") + print("http://savannah.nongnu.org/bugs/?group=ranger&func=additem") + return 1 + return 0 diff --git a/ranger/core/shared.py b/ranger/core/shared.py new file mode 100644 index 00000000..b91445a3 --- /dev/null +++ b/ranger/core/shared.py @@ -0,0 +1,73 @@ +# Copyright (C) 2009, 2010 Roman Zimbelmann <romanz@lavabit.com> +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +"""Shared objects contain singleton variables which can be +inherited, essentially acting like global variables.""" + +from ranger.ext.lazy_property import lazy_property + +class Awareness(object): + pass + +class EnvironmentAware(Awareness): + # This creates an instance implicitly, mainly for unit tests + @lazy_property + def env(self): + from ranger.core.environment import Environment + return Environment(".") + +class FileManagerAware(Awareness): + # This creates an instance implicitly, mainly for unit tests + @lazy_property + def fm(self): + from ranger.core.fm import FM + return FM() + +class SettingsAware(Awareness): + # This creates an instance implicitly, mainly for unit tests + @lazy_property + def settings(self): + from ranger.ext.openstruct import OpenStruct + return OpenStruct() + + @staticmethod + def _setup(clean=True): + from ranger.container.settingobject import SettingObject, \ + ALLOWED_SETTINGS + import ranger + import sys + settings = SettingObject() + + from ranger.gui.colorscheme import _colorscheme_name_to_class + settings.signal_bind('setopt.colorscheme', + _colorscheme_name_to_class, priority=1) + + if not clean: + # add the custom options to the list of setting sources + sys.path[0:0] = [ranger.arg.confdir] + try: + import options as my_options + except ImportError: + pass + else: + settings._setting_sources.append(my_options) + del sys.path[0] + + from ranger.defaults import options as default_options + settings._setting_sources.append(default_options) + assert all(hasattr(default_options, setting) \ + for setting in ALLOWED_SETTINGS), \ + "Ensure that all options are defined in the defaults!" + SettingsAware.settings = settings |