diff options
-rw-r--r-- | INSTALL | 2 | ||||
-rw-r--r-- | TODO | 1 | ||||
-rw-r--r-- | ranger/__init__.py | 37 | ||||
-rw-r--r-- | ranger/__main__.py | 106 | ||||
-rw-r--r-- | ranger/api/apps.py | 4 | ||||
-rw-r--r-- | ranger/colorschemes/__init__.py | 19 | ||||
-rw-r--r-- | ranger/container/bookmarks.py | 8 | ||||
-rw-r--r-- | ranger/container/tags.py | 4 | ||||
-rw-r--r-- | ranger/core/__init__.py | 0 | ||||
-rw-r--r-- | ranger/core/fm.py (renamed from ranger/fm.py) | 11 | ||||
-rw-r--r-- | ranger/core/runner.py (renamed from ranger/runner.py) | 0 | ||||
-rw-r--r-- | ranger/defaults/apps.py | 3 | ||||
-rw-r--r-- | ranger/defaults/options.py | 41 | ||||
-rw-r--r-- | ranger/ext/openstruct.py | 7 | ||||
-rw-r--r-- | ranger/gui/widgets/browsercolumn.py | 2 | ||||
-rw-r--r-- | ranger/gui/widgets/console.py | 2 | ||||
-rw-r--r-- | ranger/help/starting.py | 4 | ||||
-rw-r--r-- | ranger/shared/settings.py | 84 |
18 files changed, 202 insertions, 133 deletions
diff --git a/INSTALL b/INSTALL index 4635478b..269140c6 100644 --- a/INSTALL +++ b/INSTALL @@ -27,4 +27,4 @@ To install ranger, follow this instructions: alias rng="source ranger ranger" (Unfortunately this feature is shell dependent. It has been - successfully tested with BASH only.) + successfully tested with BASH and ZSH only.) diff --git a/TODO b/TODO index 41b5497e..81af21db 100644 --- a/TODO +++ b/TODO @@ -69,6 +69,7 @@ Bugs (X) #62 10/02/15 curs_set can raise an exception (X) #65 10/02/16 "source ranger ranger some/file.txt" shouldn't cd after exit ( ) #67 10/03/08 terminal title in tty + ( ) #69 10/03/11 tab-completion breaks with Apps subclass Ideas diff --git a/ranger/__init__.py b/ranger/__init__.py index f6913bb5..8bd978d7 100644 --- a/ranger/__init__.py +++ b/ranger/__init__.py @@ -18,12 +18,6 @@ import os import sys -LOGFILE = '/tmp/errorlog' - -__copyright__ = """ -Copyright (C) 2009, 2010 Roman Zimbelmann <romanz@lavabit.com> -""" - __license__ = 'GPL3' __version__ = '1.0.3' __credits__ = 'Roman Zimbelmann' @@ -31,34 +25,41 @@ __author__ = 'Roman Zimbelmann' __maintainer__ = 'Roman Zimbelmann' __email__ = 'romanz@lavabit.com' -debug = False - -CONFDIR = os.path.expanduser(os.path.join('~', '.config', 'ranger')) -RANGERDIR = os.path.dirname(__file__) - -sys.path.append(CONFDIR) +__copyright__ = """ +Copyright (C) 2009, 2010 Roman Zimbelmann <romanz@lavabit.com> +""" USAGE = '%prog [options] [path/filename]' +DEFAULT_CONFDIR = '~/.ranger' +RANGERDIR = os.path.dirname(__file__) +LOGFILE = '/tmp/errorlog' #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')) def log(*objects, **keywords): - """Writes objects to a logfile. - Has the same arguments as print() in python3""" + """ + Writes objects to a logfile (for the purpose of debugging only.) + Has the same arguments as print() in python3. + """ + if LOGFILE is None 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 relpath_conf(*paths): + """returns the path relative to rangers configuration directory""" + if arg.clean: + assert 0, "Should not access relpath_conf in clean mode!" + else: + return os.path.join(arg.confdir, *paths) + def relpath(*paths): """returns the path relative to rangers library directory""" return os.path.join(RANGERDIR, *paths) -def relpath_conf(*paths): - """returns the path relative to rangers configuration directory""" - return os.path.join(CONFDIR, *paths) from ranger.__main__ import main diff --git a/ranger/__main__.py b/ranger/__main__.py index 72b4adf8..dba229bc 100644 --- a/ranger/__main__.py +++ b/ranger/__main__.py @@ -19,6 +19,65 @@ import os import sys + +def parse_arguments(): + """Parse the program arguments""" + + from optparse import OptionParser, SUPPRESS_HELP + from ranger.ext.openstruct import OpenStruct + from ranger import __version__, USAGE, DEFAULT_CONFDIR + + parser = OptionParser(usage=USAGE, version='ranger ' + __version__) + + # Instead of using this directly, use the embedded + # shell script by running ranger with: + # source /path/to/ranger /path/to/ranger + parser.add_option('--cd-after-exit', + action='store_true', + help=SUPPRESS_HELP) + + 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. " \ + "This will disable certain features. (tagging, bookmarks)") + + parser.add_option('-r', '--confdir', dest='confdir', type='string', + default=DEFAULT_CONFDIR, + help="the configuration directory. (%default)") + + parser.add_option('-m', '--mode', type='int', dest='mode', default=0, + help="if a filename is supplied, run it with this mode") + + parser.add_option('-f', '--flags', type='string', dest='flags', default='', + help="if a filename is supplied, run it with these flags.") + + options, positional = parser.parse_args() + + arg = OpenStruct(options.__dict__, targets=positional) + + arg.confdir = os.path.expanduser(arg.confdir) + + if arg.cd_after_exit: + sys.stderr = sys.__stdout__ + + try: + os.makedirs(arg.confdir) + except OSError as err: + if err.errno != 17: # 17 means it already exists + print("This configuration directory could not be created:") + print(arg.confdir) + print("To run ranger without the need for configuration files") + print("use the --clean option (not implemented yet)") + raise SystemExit() + + if not arg.clean: +# sys.path[0:0] = (arg.confdir, ) + sys.path.append(arg.confdir) + + return arg + def main(): """initialize objects and run the filemanager""" try: @@ -30,12 +89,10 @@ def main(): from signal import signal, SIGINT from locale import setlocale, LC_ALL - from optparse import OptionParser, SUPPRESS_HELP import ranger from ranger.ext import curses_interrupt_handler - from ranger import __version__, USAGE, CONFDIR - from ranger.fm import FM + from ranger.core.fm import FM from ranger.container.environment import Environment from ranger.shared.settings import SettingsAware from ranger.gui.defaultui import DefaultUI as UI @@ -45,50 +102,23 @@ def main(): setlocale(LC_ALL, 'en_US.utf8') except: pass - os.stat_float_times(True) - curses_interrupt_handler.install_interrupt_handler() - - if not os.path.exists(CONFDIR): - os.mkdir(CONFDIR) + curses_interrupt_handler.install_interrupt_handler() - # Parse options - parser = OptionParser(usage=USAGE, version='ranger ' + __version__) - - # Instead of using this directly, use the embedded - # shell script by running ranger with: - # source /path/to/ranger /path/to/ranger - parser.add_option('--cd-after-exit', - action='store_true', - help=SUPPRESS_HELP) - - parser.add_option('-m', type='int', dest='mode', default=0, - help="if a filename is supplied, run it with this mode") - - parser.add_option('-f', type='string', dest='flags', default='', - help="if a filename is supplied, run it with these flags.") - - parser.add_option('-d', '--debug', action='store_true', - help="activate debug mode") - - args, rest = parser.parse_args() - - if args.cd_after_exit: - sys.stderr = sys.__stdout__ - - ranger.debug = args.debug + arg = parse_arguments() + ranger.arg = arg SettingsAware._setup() # Initialize objects - target = ' '.join(rest) - if target: + if arg.targets: + target = arg.target[0] 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): thefile = File(target) - FM().execute_file(thefile, mode=args.mode, flags=args.flags) + FM().execute_file(thefile, mode=arg.mode, flags=arg.flags) sys.exit(0) else: path = target @@ -100,7 +130,7 @@ def main(): try: my_ui = UI() my_fm = FM(ui=my_ui) - my_fm.stderr_to_out = args.cd_after_exit + my_fm.stderr_to_out = arg.cd_after_exit # Run the file manager my_fm.initialize() @@ -110,7 +140,7 @@ def main(): # Finish, clean up if 'my_ui' in vars(): my_ui.destroy() - if args.cd_after_exit: + if arg.cd_after_exit: try: sys.__stderr__.write(my_fm.env.pwd.path) except: pass diff --git a/ranger/api/apps.py b/ranger/api/apps.py index 743fa248..eadc0839 100644 --- a/ranger/api/apps.py +++ b/ranger/api/apps.py @@ -14,7 +14,7 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. """ -This module provides helper functions/classes for ranger.defaults.apps. +This module provides helper functions/classes for ranger.apps. """ import os, sys, re @@ -26,7 +26,7 @@ from ranger.shared import FileManagerAware class Applications(FileManagerAware): """ This class contains definitions on how to run programs and should - be extended in ranger.defaults.apps + be extended in ranger.apps The user can decide what program to run, and if he uses eg. 'vim', the function app_vim() will be called. However, usually the user diff --git a/ranger/colorschemes/__init__.py b/ranger/colorschemes/__init__.py index ed5413d8..422c6598 100644 --- a/ranger/colorschemes/__init__.py +++ b/ranger/colorschemes/__init__.py @@ -22,22 +22,15 @@ from os.path import expanduser, dirname, exists, join __all__ = get_all_modules(dirname(__file__)) -from ranger.colorschemes import * -from ranger import relpath_conf - -if exists(relpath_conf('colorschemes')): - initpy = relpath_conf('colorschemes', '__init__.py') - if not exists(initpy): - open(initpy, 'w').write("""# Automatically generated: +if not ranger.arg.clean: + if exists(ranger.relpath_conf('colorschemes')): + initpy = ranger.relpath_conf('colorschemes', '__init__.py') + if not exists(initpy): + open(initpy, 'w').write("""# Automatically generated: from ranger.ext.get_all_modules import get_all_modules from os.path import dirname __all__ = get_all_modules(dirname(__file__)) """) - try: - import sys - sys.path[0:0] = [ranger.CONFDIR] - from colorschemes import * - except ImportError: - pass +from ranger.colorschemes import * diff --git a/ranger/container/bookmarks.py b/ranger/container/bookmarks.py index a0c757ca..d4e12f62 100644 --- a/ranger/container/bookmarks.py +++ b/ranger/container/bookmarks.py @@ -150,6 +150,8 @@ class Bookmarks(object): This is done automatically after every modification if autosave is True.""" import os self.update() + if self.path is None: + return if os.access(self.path, os.W_OK): f = open(self.path, 'w') for key, value in self.dct.items(): @@ -163,6 +165,10 @@ class Bookmarks(object): def _load_dict(self): import os dct = {} + + if self.path is None: + return dct + if not os.path.exists(self.path): try: f = open(self.path, 'w') @@ -193,6 +199,8 @@ class Bookmarks(object): def _get_mtime(self): import os + if self.path is None: + return None try: return os.stat(self.path).st_mtime except OSError: diff --git a/ranger/container/tags.py b/ranger/container/tags.py index 70a4aa3d..11ac3a5d 100644 --- a/ranger/container/tags.py +++ b/ranger/container/tags.py @@ -81,3 +81,7 @@ class Tags(object): for line in f: result.add(line.strip()) return result + + def __nonzero__(self): + return True + __bool__ = __nonzero__ diff --git a/ranger/core/__init__.py b/ranger/core/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/ranger/core/__init__.py diff --git a/ranger/fm.py b/ranger/core/fm.py index a10e9af6..83426a04 100644 --- a/ranger/fm.py +++ b/ranger/core/fm.py @@ -16,9 +16,10 @@ from time import time from collections import deque +import ranger from ranger.actions import Actions from ranger.container import Bookmarks -from ranger.runner import Runner +from ranger.core.runner import Runner from ranger import relpath_conf from ranger.ext.get_executables import get_executables from ranger import __version__ @@ -61,8 +62,12 @@ class FM(Actions): from ranger.fsobject.directory import Directory if self.bookmarks is None: + if ranger.arg.clean: + bookmarkfile = None + else: + bookmarkfile = relpath_conf('bookmarks') self.bookmarks = Bookmarks( - bookmarkfile=relpath_conf('bookmarks'), + bookmarkfile=bookmarkfile, bookmarktype=Directory, autosave=self.settings.autosave_bookmarks) self.bookmarks.load() @@ -71,7 +76,7 @@ class FM(Actions): self.bookmarks = bookmarks from ranger.container.tags import Tags - if self.tags is None: + if not ranger.arg.clean and self.tags is None: self.tags = Tags(relpath_conf('tagged')) if self.ui is None: diff --git a/ranger/runner.py b/ranger/core/runner.py index 26424881..26424881 100644 --- a/ranger/runner.py +++ b/ranger/core/runner.py diff --git a/ranger/defaults/apps.py b/ranger/defaults/apps.py index a19df7a9..37099d04 100644 --- a/ranger/defaults/apps.py +++ b/ranger/defaults/apps.py @@ -78,7 +78,7 @@ class CustomApplications(Applications): return self.either(c, 'mplayer', 'totem') if f.image: - return self.app_feh(c) + return self.either(c, 'feh', 'mirage') if f.document: return self.app_editor(c) @@ -130,7 +130,6 @@ class CustomApplications(Applications): @depends_on('mirage') def app_mirage(self, c): c.flags += 'd' - return tup('mirage', *c) @depends_on('feh') diff --git a/ranger/defaults/options.py b/ranger/defaults/options.py index 139cda88..8711f737 100644 --- a/ranger/defaults/options.py +++ b/ranger/defaults/options.py @@ -21,26 +21,45 @@ intact and the type of the value stays the same. from ranger.api.options import * -one_kb = 1024 - -colorscheme = colorschemes.default +# Which colorscheme to use? There are these by default: +# colorschemes.texas +# colorschemes.jungle +# colorschemes.default +# colorschemes.snow +# Texas uses 88 colors. If they are not supported, it will fall back +# to the default scheme. +colorscheme = colorschemes.texas max_history_size = 20 -max_filesize_for_preview = 300 * one_kb scroll_offset = 2 -preview_files = True -flushinput = True -sort = 'basename' -reverse = False -directories_first = True +# Flush the input after each key hit? (Noticable when ranger lags) +flushinput = True -show_hidden = False +# Preview files on the rightmost column? +# And collapse the last column if there is nothing to preview? +preview_files = True +max_filesize_for_preview = 300 * 1024 # 300kb collapse_preview = True + +# Save bookmarks (used with mX and `X) instantly? +# this helps to synchronize bookmarks between multiple ranger +# instances but leads to slight performance loss. +# When false, bookmarks are saved when ranger is exited. autosave_bookmarks = True + +# Specify a title for the window? Some terminals don't support this: update_title = False +# Makes sense for screen readers: show_cursor = False +# One of: size, basename, mtime, type +sort = 'basename' +reverse = False +directories_first = True + +# Which files are hidden if show_hidden is False? hidden_filter = regexp( - r'lost\+found|^\.|~$|\.(:?pyc|pyo|bak|swp)$') + r'lost\+found|^\.|~$|\.(:?pyc|pyo|bak|swp)$') +show_hidden = False diff --git a/ranger/ext/openstruct.py b/ranger/ext/openstruct.py index 11363127..a94c3031 100644 --- a/ranger/ext/openstruct.py +++ b/ranger/ext/openstruct.py @@ -13,8 +13,11 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. +# prepend __ to arguments because one might use "args" +# or "keywords" as a keyword argument. + class OpenStruct(dict): """The fusion of dict and struct""" - def __init__(self, *args, **keywords): - dict.__init__(self, *args, **keywords) + def __init__(self, *__args, **__keywords): + dict.__init__(self, *__args, **__keywords) self.__dict__ = self diff --git a/ranger/gui/widgets/browsercolumn.py b/ranger/gui/widgets/browsercolumn.py index 2550062f..b98005b5 100644 --- a/ranger/gui/widgets/browsercolumn.py +++ b/ranger/gui/widgets/browsercolumn.py @@ -207,7 +207,7 @@ class BrowserColumn(Pager, Widget): this_color = base_color + list(drawed.mimetype_tuple) text = drawed.basename - tagged = drawed.realpath in self.fm.tags + tagged = self.fm.tags and drawed.realpath in self.fm.tags if i == selected_i: this_color.append('selected') diff --git a/ranger/gui/widgets/console.py b/ranger/gui/widgets/console.py index 87e5a7b5..a331c66d 100644 --- a/ranger/gui/widgets/console.py +++ b/ranger/gui/widgets/console.py @@ -580,7 +580,7 @@ class QuickOpenConsole(ConsoleWithTab): return self.fm.apps.has(arg) def _is_flags(self, arg): - from ranger.runner import ALLOWED_FLAGS + from ranger.core.runner import ALLOWED_FLAGS return all(x in ALLOWED_FLAGS for x in arg) def _is_mode(self, arg): diff --git a/ranger/help/starting.py b/ranger/help/starting.py index 29921ffc..f5517c78 100644 --- a/ranger/help/starting.py +++ b/ranger/help/starting.py @@ -61,7 +61,7 @@ Note: The "open with" console is named QuickOpenConsole in the source code. ============================================================================== 2.3. Programs -Programs have to be defined in ranger/defaults/apps.py. Each function +Programs have to be defined in ranger/apps.py. Each function in the class CustomApplications which starts with "app_" can be used as a program in the "open with" prompt. @@ -83,7 +83,7 @@ start a file in mode 0. "4l" will start the file in mode 4 etc. You can specify a mode in the "open with" console by simply adding the number. Eg: "open with: mplayer 1" or "open with: 1" -For a list of all programs and modes, see ranger/defaults/apps.py +For a list of all programs and modes, see ranger/apps.py ============================================================================== diff --git a/ranger/shared/settings.py b/ranger/shared/settings.py index b549bd20..6df5241f 100644 --- a/ranger/shared/settings.py +++ b/ranger/shared/settings.py @@ -14,6 +14,8 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. import types +from inspect import isclass, ismodule +import ranger from ranger.ext.openstruct import OpenStruct from ranger.gui.colorscheme import ColorScheme @@ -41,54 +43,52 @@ class SettingsAware(object): @staticmethod def _setup(): - from inspect import isclass, ismodule - from ranger.gui.colorscheme import ColorScheme + settings = OpenStruct() - # overwrite single default options with custom options from ranger.defaults import options - try: - import options as custom_options - for setting in ALLOWED_SETTINGS: - if hasattr(custom_options, setting): - setattr(options, setting, getattr(custom_options, setting)) - elif not hasattr(options, setting): - raise Exception("This option was not defined: " + setting) - except ImportError: - pass - - assert check_option_types(options) - - try: - import apps - except ImportError: - from ranger.defaults import apps - - try: - import keys - except ImportError: - from ranger.defaults import keys + for setting in ALLOWED_SETTINGS: + try: + settings[setting] = getattr(options, setting) + except AttributeError: + raise Exception("The option `{0}' was not defined" \ + " in the defaults!".format(setting)) + + import sys + if not ranger.arg.clean: + # overwrite single default options with custom options + try: + import rangerrc + except ImportError: + pass + else: + for setting in ALLOWED_SETTINGS: + try: + settings[setting] = getattr(rangerrc, setting) + except AttributeError: + pass + assert check_option_types(settings) # If a module is specified as the colorscheme, replace it with one # valid colorscheme inside that module. - all_content = options.colorscheme.__dict__.items() + all_content = settings.colorscheme.__dict__.items() - if isclass(options.colorscheme) and \ - issubclass(options.colorscheme, ColorScheme): - options.colorscheme = options.colorscheme() + if isclass(settings.colorscheme) and \ + issubclass(settings.colorscheme, ColorScheme): + settings.colorscheme = settings.colorscheme() - elif ismodule(options.colorscheme): + elif ismodule(settings.colorscheme): def is_scheme(x): return isclass(x) and issubclass(x, ColorScheme) - if hasattr(options.colorscheme, 'Scheme') \ - and is_scheme(options.colorscheme.Scheme): - options.colorscheme = options.colorscheme.Scheme() + if hasattr(settings.colorscheme, 'Scheme') \ + and is_scheme(settings.colorscheme.Scheme): + settings.colorscheme = settings.colorscheme.Scheme() else: - for name, var in options.colorscheme.__dict__.items(): + for name, var in settings.colorscheme.__dict__.items(): if var != ColorScheme and is_scheme(var): - options.colorscheme = var() + settings.colorscheme = var() break else: raise Exception("The module contains no " \ @@ -96,12 +96,18 @@ class SettingsAware(object): else: raise Exception("Cannot locate colorscheme!") - for setting in ALLOWED_SETTINGS: - SettingsAware.settings[setting] = getattr(options, setting) - - SettingsAware.settings.keys = keys - SettingsAware.settings.apps = apps + try: + import apps + except ImportError: + from ranger.defaults import apps + settings.apps = apps + try: + import keys + except ImportError: + from ranger.defaults import keys + settings.keys = keys + SettingsAware.settings = settings def check_option_types(opt): import inspect |