diff options
63 files changed, 756 insertions, 1337 deletions
diff --git a/Makefile b/Makefile index f13de38d..20cf6f25 100644 --- a/Makefile +++ b/Makefile @@ -1,17 +1,5 @@ # Copyright (C) 2009, 2010, 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. NAME = ranger VERSION = $(shell grep -m 1 -o '[0-9][0-9.]\+' README) @@ -72,7 +60,7 @@ doc: cleandoc test: @for FILE in $(shell grep -IHm 1 doctest -r ranger | cut -d: -f1); do \ echo "Testing $$FILE..."; \ - PYTHONPATH=".:"$$PYTHONPATH ${PYTHON} $$FILE; \ + RANGER_DOCTEST=1 PYTHONPATH=".:"$$PYTHONPATH ${PYTHON} $$FILE; \ done man: diff --git a/ranger.py b/ranger.py index c763a8d9..efd81f4d 100755 --- a/ranger.py +++ b/ranger.py @@ -1,19 +1,7 @@ #!/usr/bin/python -O # ranger - a vim-inspired file manager for the console (coding: utf-8) # Copyright (C) 2009, 2010, 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. # ===================== # This embedded bash script can be executed by sourcing this file. diff --git a/ranger/__init__.py b/ranger/__init__.py index ae9229b3..735ed527 100644 --- a/ranger/__init__.py +++ b/ranger/__init__.py @@ -1,17 +1,5 @@ # Copyright (C) 2009, 2010, 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. """ A console file manager with VI key bindings. @@ -34,6 +22,7 @@ RANGERDIR = os.path.dirname(__file__) TICKS_BEFORE_COLLECTING_GARBAGE = 100 TIME_BEFORE_FILE_BECOMES_GARBAGE = 1200 MACRO_DELIMITER = '%' +DEFAULT_PAGER = 'less' LOGFILE = '/tmp/ranger_errorlog' USAGE = '%prog [options] [path/filename]' STABLE = True diff --git a/ranger/api/apps.py b/ranger/api/apps.py deleted file mode 100644 index 56f8afd2..00000000 --- a/ranger/api/apps.py +++ /dev/null @@ -1,180 +0,0 @@ -# Copyright (C) 2009, 2010, 2011 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/>. - -import os, sys, re -from ranger.api import * -from ranger.ext.iter_tools import flatten -from ranger.ext.get_executables import get_executables -from ranger.core.runner import Context -from ranger.core.shared import FileManagerAware - - -class Applications(FileManagerAware): - """ - This class contains definitions on how to run programs and should - 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 - simply wants to "start" the file without specific instructions. - In such a case, app_default() is called, where you should examine - the context and decide which program to use. - - All app functions have a name starting with app_ and return a string - containing the whole command or a tuple containing a list of the - arguments. They are supplied with one argument, which is the - AppContext instance. - - You should define at least app_default, app_pager and app_editor since - internal functions depend on those. Here are sample implementations: - - def app_default(self, context): - if context.file.media: - if context.file.video: - # detach videos from the filemanager - context.flags += 'd' - return self.app_mplayer(context) - else: - return self.app_editor(context) - - def app_pager(self, context): - return 'less', context - - def app_editor(self, context): - return ('vim', context) - """ - - def _meets_dependencies(self, fnc): - try: - deps = fnc.dependencies - except AttributeError: - return True - - for dep in deps: - if dep == 'X': - if 'DISPLAY' not in os.environ or not os.environ['DISPLAY']: - return False - continue - if hasattr(dep, 'dependencies') \ - and not self._meets_dependencies(dep): - return False - if dep not in get_executables(): - return False - - return True - - def either(self, context, *args): - for app in args: - try: - application_handler = getattr(self, 'app_' + app) - except AttributeError: - if app in get_executables(): - return _generic_app(app, context) - continue - if self._meets_dependencies(application_handler): - return application_handler(context) - - def app_self(self, context): - """Run the file itself""" - return "./" + context.file.basename - - def get(self, app): - """Looks for an application, returns app_default if it doesn't exist""" - try: - return getattr(self, 'app_' + app) - except AttributeError: - return self.app_default - - def apply(self, app, context): - if not app: - app = 'default' - try: - handler = getattr(self, 'app_' + app) - except AttributeError: - if app in get_executables(): - return [app] + list(context) - handler = self.app_default - arguments = handler(context) - # flatten - if isinstance(arguments, str): - return arguments - if arguments is None: - return None - result = [] - for obj in arguments: - if isinstance(obj, (tuple, list, Context)): - result.extend(obj) - else: - result.append(obj) - return result - - def has(self, app): - """Returns whether an application is defined""" - return hasattr(self, 'app_' + app) - - def all(self): - """Returns a list with all application functions""" - result = set() - # go through all the classes in the mro (method resolution order) - # so subclasses will return the apps of their superclasses. - for cls in self.__class__.__mro__: - result |= set(m[4:] for m in cls.__dict__ if m.startswith('app_')) - return sorted(result) - - @classmethod - def generic(cls, *args, **keywords): - flags = 'flags' in keywords and keywords['flags'] or "" - deps = 'deps' in keywords and keywords['deps'] or () - for name in args: - assert isinstance(name, str) - if not hasattr(cls, "app_" + name): - fnc = _generic_wrapper(name, flags=flags) - fnc = depends_on(*deps)(fnc) - setattr(cls, "app_" + name, fnc) - - -def tup(*args): - """ - This helper function creates a tuple out of the arguments. - - ('a', ) + tuple(some_iterator) - is equivalent to: - tup('a', *some_iterator) - """ - return args - - -def depends_on(*args): - args = tuple(flatten(args)) - def decorator(fnc): - try: - fnc.dependencies += args - except: - fnc.dependencies = args - return fnc - return decorator - - -def _generic_app(name, context, flags=''): - """Use this function when no other information is given""" - context.flags += flags - return name, context - - -def _generic_wrapper(name, flags=''): - """Wraps _generic_app into a method for Applications""" - assert isinstance(name, str) - return depends_on(name)(lambda self, context: - _generic_app(name, context, flags)) diff --git a/ranger/api/commands.py b/ranger/api/commands.py index a2501c7f..c3317939 100644 --- a/ranger/api/commands.py +++ b/ranger/api/commands.py @@ -1,17 +1,5 @@ # Copyright (C) 2009, 2010, 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. # TODO: Add an optional "!" to all commands and set a flag if it's there diff --git a/ranger/api/options.py b/ranger/api/options.py index e2558ffb..3691fe94 100644 --- a/ranger/api/options.py +++ b/ranger/api/options.py @@ -1,17 +1,5 @@ # Copyright (C) 2009, 2010, 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. import re from re import compile as regexp diff --git a/ranger/colorschemes/default.py b/ranger/colorschemes/default.py index fb46dd43..fa1d92bc 100644 --- a/ranger/colorschemes/default.py +++ b/ranger/colorschemes/default.py @@ -1,17 +1,5 @@ # Copyright (C) 2009, 2010, 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. from ranger.gui.colorscheme import ColorScheme from ranger.gui.color import * diff --git a/ranger/colorschemes/default88.py b/ranger/colorschemes/default88.py index 8bf33807..2a2d4825 100644 --- a/ranger/colorschemes/default88.py +++ b/ranger/colorschemes/default88.py @@ -1,17 +1,5 @@ # Copyright (C) 2009, 2010, 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. """ The default colorscheme, using 88 colors. diff --git a/ranger/colorschemes/jungle.py b/ranger/colorschemes/jungle.py index ea2e0d94..4f2b30ba 100644 --- a/ranger/colorschemes/jungle.py +++ b/ranger/colorschemes/jungle.py @@ -1,17 +1,5 @@ # Copyright (C) 2009, 2010, 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. from ranger.gui.color import * from ranger.colorschemes.default import Default diff --git a/ranger/colorschemes/snow.py b/ranger/colorschemes/snow.py index a8125ee6..c5940cc8 100644 --- a/ranger/colorschemes/snow.py +++ b/ranger/colorschemes/snow.py @@ -1,17 +1,5 @@ # Copyright (C) 2009, 2010, 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. from ranger.gui.colorscheme import ColorScheme from ranger.gui.color import * diff --git a/ranger/container/bookmarks.py b/ranger/container/bookmarks.py index 750515c5..4d692989 100644 --- a/ranger/container/bookmarks.py +++ b/ranger/container/bookmarks.py @@ -1,17 +1,5 @@ # Copyright (C) 2009, 2010, 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. import string import re diff --git a/ranger/container/history.py b/ranger/container/history.py index dd511d0e..1f2c5a4b 100644 --- a/ranger/container/history.py +++ b/ranger/container/history.py @@ -1,17 +1,5 @@ # Copyright (C) 2009, 2010, 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. class HistoryEmptyException(Exception): pass diff --git a/ranger/container/settingobject.py b/ranger/container/settingobject.py index e7ded15e..cbc56278 100644 --- a/ranger/container/settingobject.py +++ b/ranger/container/settingobject.py @@ -1,17 +1,5 @@ # Copyright (C) 2009, 2010, 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. from inspect import isfunction from ranger.ext.signals import SignalDispatcher diff --git a/ranger/container/tags.py b/ranger/container/tags.py index c08abdaa..7212345e 100644 --- a/ranger/container/tags.py +++ b/ranger/container/tags.py @@ -1,17 +1,5 @@ # Copyright (C) 2009, 2010, 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. from os.path import isdir, exists, dirname, abspath, realpath, expanduser import string diff --git a/ranger/core/actions.py b/ranger/core/actions.py index 4e72de77..2102cf2d 100644 --- a/ranger/core/actions.py +++ b/ranger/core/actions.py @@ -1,17 +1,5 @@ # Copyright (C) 2009, 2010, 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. import codecs import os @@ -29,6 +17,7 @@ from ranger.ext.relative_symlink import relative_symlink from ranger.ext.keybinding_parser import key_to_string, construct_keybinding from ranger.ext.shell_escape import shell_quote from ranger.ext.next_available_filename import next_available_filename +from ranger.ext.rifle import squash_flags from ranger.core.shared import FileManagerAware, EnvironmentAware, \ SettingsAware from ranger.fsobject import File @@ -285,8 +274,10 @@ class Actions(FileManagerAware, EnvironmentAware, SettingsAware): mode is a positive integer. Both flags and mode specify how the program is run.""" + mode = kw['mode'] if 'mode' in kw else 0 + # ranger can act as a file chooser when running with --choosefile=... - if ('mode' not in kw or kw['mode'] == 0) and 'app' not in kw: + if mode == 0 and 'label' not in kw: if ranger.arg.choosefile: open(ranger.arg.choosefile, 'w').write(self.fm.env.cf.path) @@ -302,16 +293,16 @@ class Actions(FileManagerAware, EnvironmentAware, SettingsAware): elif type(files) not in (list, tuple): files = [files] - if 'flags' in kw: - from ranger.core.runner import Context - context = Context(files=list(files), flags=kw['flags']) - context.squash_flags() - if 'c' in context.flags: - files = [self.fm.env.cf] + flags = kw.get('flags', '') + if 'c' in squash_flags(flags): + files = [self.fm.env.cf] self.signal_emit('execute.before', keywords=kw) + filenames = [f.path for f in files] + mimetype = files[0].mimetype if files else None + label = kw.get('label', kw.get('app', None)) try: - return self.run(files=list(files), **kw) + return self.rifle.execute(filenames, mode, label, flags, mimetype) finally: self.signal_emit('execute.after') @@ -463,6 +454,9 @@ class Actions(FileManagerAware, EnvironmentAware, SettingsAware): def taskview_move(self, narg=None, **kw): self.ui.taskview.move(narg=narg, **kw) + def pause_tasks(self): + self.loader.pause(-1) + def pager_close(self): if self.ui.pager.visible: self.ui.close_pager() @@ -479,14 +473,14 @@ class Actions(FileManagerAware, EnvironmentAware, SettingsAware): return self.run(cmd, **kw) def edit_file(self, file=None): - """Calls execute_file with the current file and app='editor'""" + """Calls execute_file with the current file and label='editor'""" if file is None: file = self.env.cf elif isinstance(file, str): file = File(os.path.expanduser(file)) if file is None: return - self.execute_file(file, app = 'editor') + self.execute_file(file, label='editor') def toggle_option(self, string): """Toggle a boolean option named <string>""" @@ -691,6 +685,19 @@ class Actions(FileManagerAware, EnvironmentAware, SettingsAware): def hide_bookmarks(self): self.ui.browser.draw_bookmarks = False + def draw_possible_programs(self): + try: + target = self.env.get_selection()[0] + except: + self.ui.browser.draw_info = [] + return + programs = self.rifle.list_commands([target.path], target.mimetype) + programs = ['%s | %s' % program[0:2] for program in programs] + self.ui.browser.draw_info = programs + + def hide_console_info(self): + self.ui.browser.draw_info = False + # -------------------------- # -- Pager # -------------------------- @@ -905,7 +912,8 @@ class Actions(FileManagerAware, EnvironmentAware, SettingsAware): write("\n") temporary_file.flush() - self.run(app='pager', files=[File(temporary_file.name)]) + pager = os.environ.get('PAGER', ranger.DEFAULT_PAGER) + self.run([pager, temporary_file.name]) def dump_commands(self): temporary_file = tempfile.NamedTemporaryFile() @@ -927,7 +935,8 @@ class Actions(FileManagerAware, EnvironmentAware, SettingsAware): write(" :%s\n" % cmd.get_name()) temporary_file.flush() - self.run(app='pager', files=[File(temporary_file.name)]) + pager = os.environ.get('PAGER', ranger.DEFAULT_PAGER) + self.run([pager, temporary_file.name]) def dump_settings(self): from ranger.container.settingobject import ALLOWED_SETTINGS @@ -939,7 +948,8 @@ class Actions(FileManagerAware, EnvironmentAware, SettingsAware): write("%30s = %s\n" % (setting, getattr(self.settings, setting))) temporary_file.flush() - self.run(app='pager', files=[File(temporary_file.name)]) + pager = os.environ.get('PAGER', ranger.DEFAULT_PAGER) + self.run([pager, temporary_file.name]) # -------------------------- # -- File System Operations diff --git a/ranger/core/environment.py b/ranger/core/environment.py index b5ab223d..29ebcdf0 100644 --- a/ranger/core/environment.py +++ b/ranger/core/environment.py @@ -1,17 +1,5 @@ # Copyright (C) 2009, 2010, 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. import curses import os diff --git a/ranger/core/fm.py b/ranger/core/fm.py index 20327a71..50c22067 100644 --- a/ranger/core/fm.py +++ b/ranger/core/fm.py @@ -1,17 +1,5 @@ # Copyright (C) 2009, 2010, 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. """ The File Manager, putting the pieces together @@ -25,13 +13,13 @@ import stat import sys import ranger -from ranger import * from ranger.core.actions import Actions from ranger.container.tags import Tags from ranger.gui.ui import UI from ranger.container.bookmarks import Bookmarks from ranger.core.runner import Runner from ranger.ext.get_executables import get_executables +from ranger.ext.rifle import Rifle from ranger.fsobject import Directory from ranger.ext.signals import SignalDispatcher from ranger import __version__ @@ -64,6 +52,14 @@ class FM(Actions, SignalDispatcher): def initialize(self): """If ui/bookmarks are None, they will be initialized here.""" + + if not ranger.arg.clean and os.path.isfile(self.confpath('rifle.conf')): + rifleconf = self.confpath('rifle.conf') + else: + rifleconf = self.relpath('defaults/rifle.conf') + self.rifle = Rifle(rifleconf) + self.rifle.reload_config() + if self.bookmarks is None: if ranger.arg.clean: bookmarkfile = None @@ -82,10 +78,13 @@ class FM(Actions, SignalDispatcher): self.ui = UI() self.ui.initialize() + self.rifle.hook_before_executing = lambda a, b, flags: self.ui.suspend() if 'f' not in flags else None + self.rifle.hook_after_executing = lambda a, b, flags: self.ui.initialize() if 'f' not in flags else None + self.rifle.hook_logger = self.notify + def mylogfunc(text): self.notify(text, bad=True) - self.run = Runner(ui=self.ui, apps=self.apps, - logfunc=mylogfunc, fm=self) + self.run = Runner(ui=self.ui, logfunc=mylogfunc, fm=self) self.env.signal_bind('cd', self._update_current_tab) @@ -130,8 +129,8 @@ class FM(Actions, SignalDispatcher): shutil.copy(self.relpath(_from), self.confpath(to)) except Exception as e: sys.stderr.write(" ERROR: %s\n" % str(e)) - if which == 'apps' or which == 'all': - copy('defaults/apps.py', 'apps.py') + if which == 'rifle' or which == 'all': + copy('defaults/rifle.conf', 'rifle.conf') if which == 'commands' or which == 'all': copy('defaults/commands.py', 'commands.py') if which == 'rc' or which == 'all': @@ -143,7 +142,7 @@ class FM(Actions, SignalDispatcher): os.chmod(self.confpath('scope.sh'), os.stat(self.confpath('scope.sh')).st_mode | stat.S_IXUSR) if which not in \ - ('all', 'apps', 'scope', 'commands', 'rc', 'options'): + ('all', 'rifle', 'scope', 'commands', 'rc', 'options'): sys.stderr.write("Unknown config file `%s'\n" % which) def confpath(self, *paths): @@ -190,7 +189,7 @@ class FM(Actions, SignalDispatcher): ui.redraw() - ui.set_load_mode(loader.has_work()) + ui.set_load_mode(not loader.paused and loader.has_work()) ui.handle_input() @@ -200,10 +199,10 @@ class FM(Actions, SignalDispatcher): zombies.remove(zombie) gc_tick += 1 - if gc_tick > TICKS_BEFORE_COLLECTING_GARBAGE: + if gc_tick > ranger.TICKS_BEFORE_COLLECTING_GARBAGE: gc_tick = 0 - env.garbage_collect(TIME_BEFORE_FILE_BECOMES_GARBAGE, - self.tabs) + env.garbage_collect( + ranger.TIME_BEFORE_FILE_BECOMES_GARBAGE, self.tabs) except KeyboardInterrupt: # this only happens in --debug mode. By default, interrupts diff --git a/ranger/core/helper.py b/ranger/core/helper.py index c556b9bd..233f1b8a 100644 --- a/ranger/core/helper.py +++ b/ranger/core/helper.py @@ -1,29 +1,16 @@ # Copyright (C) 2009, 2010, 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. """Helper functions""" from errno import EEXIST import os.path import sys -from ranger import * +from ranger import CONFDIR, USAGE, STABLE, __version__ def parse_arguments(): """Parse the program arguments""" from optparse import OptionParser - from ranger import __version__ from ranger.ext.openstruct import OpenStruct from os.path import expanduser @@ -41,7 +28,7 @@ def parse_arguments(): help="don't touch/require any config files. ") parser.add_option('--copy-config', type='string', metavar='which', help="copy the default configs to the local config directory. " - "Possible values: all, rc, apps, commands, options, scope") + "Possible values: all, rc, rifle, commands, options, scope") 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`)") @@ -107,13 +94,6 @@ def load_settings(fm, clean): except ImportError: pass - # Load apps - try: - import apps - except ImportError: - from ranger.defaults import apps - fm.apps = apps.CustomApplications() - # Load rc.conf custom_conf = fm.confpath('rc.conf') default_conf = fm.relpath('defaults', 'rc.conf') @@ -150,25 +130,9 @@ def load_settings(fm, clean): allow_access_to_confdir(ranger.arg.confdir, False) else: - from ranger.defaults import apps - fm.apps = apps.CustomApplications() fm.source(fm.relpath('defaults', 'rc.conf')) -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: diff --git a/ranger/core/loader.py b/ranger/core/loader.py index 59d3e6c0..777ce0f2 100644 --- a/ranger/core/loader.py +++ b/ranger/core/loader.py @@ -1,17 +1,5 @@ # Copyright (C) 2009, 2010, 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. from collections import deque from time import time, sleep @@ -123,8 +111,8 @@ class CommandLoader(Loadable, SignalDispatcher, FileManagerAware): self.process.send_signal(20) except: pass - Loadable.pause(self) - self.signal_emit('pause', process=self.process, loader=self) + Loadable.pause(self) + self.signal_emit('pause', process=self.process, loader=self) def unpause(self): if not self.finished and self.paused: @@ -132,8 +120,8 @@ class CommandLoader(Loadable, SignalDispatcher, FileManagerAware): self.process.send_signal(18) except: pass - Loadable.unpause(self) - self.signal_emit('unpause', process=self.process, loader=self) + Loadable.unpause(self) + self.signal_emit('unpause', process=self.process, loader=self) def destroy(self): self.signal_emit('destroy', process=self.process, loader=self) @@ -154,6 +142,8 @@ def safeDecode(string): class Loader(FileManagerAware): seconds_of_work_time = 0.03 throbber_chars = r'/-\|' + throbber_paused = '#' + paused = False def __init__(self): self.queue = deque() @@ -178,6 +168,10 @@ class Loader(FileManagerAware): while obj in self.queue: self.queue.remove(obj) self.queue.appendleft(obj) + if self.paused: + obj.pause() + else: + obj.unpause() def move(self, _from, to): try: @@ -213,11 +207,34 @@ class Loader(FileManagerAware): item.destroy() del self.queue[index] + def pause(self, state): + """ + Change the pause-state to 1 (pause), 0 (no pause) or -1 (toggle) + """ + if state == -1: + state = not self.paused + elif state == self.paused: + return + + self.paused = state + + if not self.queue: + return + + if state: + self.queue[0].pause() + else: + self.queue[0].unpause() + def work(self): """ Load items from the queue if there are any. Stop after approximately self.seconds_of_work_time. """ + if self.paused: + self.status = self.throbber_paused + return + while True: # get the first item with a proper load_generator try: @@ -229,6 +246,8 @@ class Loader(FileManagerAware): except IndexError: return + item.unpause() + self.rotate() if item != self.old_item: if self.old_item: diff --git a/ranger/core/main.py b/ranger/core/main.py index b4629801..37cdc586 100644 --- a/ranger/core/main.py +++ b/ranger/core/main.py @@ -1,24 +1,10 @@ # Copyright (C) 2009, 2010, 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. """ 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 @@ -28,6 +14,7 @@ def main(): from ranger.core.shared import (EnvironmentAware, FileManagerAware, SettingsAware) from ranger.core.fm import FM + from ranger.core.helper import parse_arguments, load_settings if not sys.stdin.isatty(): sys.stderr.write("Error: Must run ranger from terminal\n") @@ -85,12 +72,15 @@ def main(): elif os.path.isfile(target): def print_function(string): print(string) - from ranger.core.runner import Runner - from ranger.fsobject import File + from ranger.ext.rifle import Rifle fm = FM() - runner = Runner(logfunc=print_function, fm=fm) - load_apps(runner, arg.clean) - runner(files=[File(target)], mode=arg.mode, flags=arg.flags) + if not arg.clean and os.path.isfile(fm.confpath('rifle.conf')): + rifleconf = fm.confpath('rifle.conf') + else: + rifleconf = fm.relpath('defaults/rifle.conf') + rifle = Rifle(rifleconf) + rifle.reload_config() + rifle.execute(targets, number=ranger.arg.mode, flags=ranger.arg.flags) return 1 if arg.fail_unless_cd else 0 crash_traceback = None diff --git a/ranger/core/runner.py b/ranger/core/runner.py index 17cdcca5..52c0b669 100644 --- a/ranger/core/runner.py +++ b/ranger/core/runner.py @@ -1,17 +1,5 @@ # Copyright (C) 2009, 2010, 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. """ This module is an abstract layer over subprocess.Popen @@ -41,7 +29,9 @@ from subprocess import Popen, PIPE from ranger.ext.get_executables import get_executables -ALLOWED_FLAGS = 'sdpwcrtSDPWCRT' +# TODO: Remove unused parts of runner.py +#ALLOWED_FLAGS = 'sdpwcrtSDPWCRT' +ALLOWED_FLAGS = 'cfrtCFRT' def press_enter(): @@ -97,11 +87,10 @@ class Context(object): class Runner(object): - def __init__(self, ui=None, logfunc=None, apps=None, fm=None): + def __init__(self, ui=None, logfunc=None, fm=None): self.ui = ui self.fm = fm self.logfunc = logfunc - self.apps = apps self.zombies = set() def _log(self, text): @@ -140,16 +129,6 @@ class Runner(object): flags=flags, wait=wait, popen_kws=popen_kws, file=files and files[0] or None) - if self.apps: - if try_app_first and action is not None: - test = self.apps.apply(app, context) - if test: - action = test - if action is None: - action = self.apps.apply(app, context) - if action is None: - return self._log("No action found!") - if action is None: return self._log("No way of determining the action!") diff --git a/ranger/core/shared.py b/ranger/core/shared.py index 9da79578..dae83b78 100644 --- a/ranger/core/shared.py +++ b/ranger/core/shared.py @@ -1,17 +1,5 @@ # Copyright (C) 2009, 2010, 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. """Shared objects contain singleton variables which can be inherited, essentially acting like global variables.""" diff --git a/ranger/defaults/apps.py b/ranger/defaults/apps.py deleted file mode 100644 index 1619eb1e..00000000 --- a/ranger/defaults/apps.py +++ /dev/null @@ -1,325 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (C) 2009, 2010, 2011 Roman Zimbelmann <romanz@lavabit.com> -# This configuration file is licensed under the same terms as ranger. -# =================================================================== -# This is the configuration file for file type detection and application -# handling. It's all in python; lines beginning with # are comments. -# -# You can customize this in the file ~/.config/ranger/apps.py. -# It has the same syntax as this file. In fact, you can just copy this -# file there with `ranger --copy-config=apps' and make your modifications. -# But make sure you update your configs when you update ranger. -# -# In order to add application definitions "on top of" the default ones -# in your ~/.config/ranger/apps.py, you should subclass the class defined -# here like this: -# -# from ranger.defaults.apps import CustomApplications as DefaultApps -# class CustomApplications(DeafultApps): -# <your definitions here> -# -# To override app_defaults, you can write something like: -# -# def app_defaults(self, c): -# f = c.file -# if f.extension == 'lol': -# return "lolopener", c -# return DefaultApps.app_default(self, c) -# -# =================================================================== -# This system is based on things called MODES and FLAGS. You can read -# in the man page about them. To remind you, here's a list of all flags. -# An uppercase flag inverts previous flags of the same name. -# s Silent mode. Output will be discarded. -# d Detach the process. (Run in background) -# p Redirect output to the pager -# w Wait for an Enter-press when the process is done -# c Run the current file only, instead of the selection -# r Run application with root privilege -# t Run application in a new terminal window -# -# To implement flags in this file, you could do this: -# context.flags += "d" -# Another example: -# context.flags += "Dw" -# -# To implement modes in this file, you can do something like: -# if context.mode == 1: -# <run in one way> -# elif context.mode == 2: -# <run in another way> -# -# =================================================================== -# The methods are called with a "context" object which provides some -# attributes that transfer information. Relevant attributes are: -# -# mode -- a number, mainly used in determining the action in app_xyz() -# flags -- a string with flags which change the way programs are run -# files -- a list containing files, mainly used in app_xyz -# filepaths -- a list of the paths of each file -# file -- an arbitrary file from that list (or None) -# fm -- the filemanager instance -# popen_kws -- keyword arguments which are directly passed to Popen -# -# =================================================================== -# The return value of the functions should be either: -# 1. A reference to another app, like: -# return self.app_editor(context) -# -# 2. A call to the "either" method, which uses the first program that -# is installed on your system. If none are installed, None is returned. -# return self.either(context, "libreoffice", "soffice", "ooffice") -# -# 3. A tuple of arguments that should be run. -# return "mplayer", "-fs", context.file.path -# If you use lists instead of strings, they will be flattened: -# args = ["-fs", "-shuf"] -# return "mplayer", args, context.filepaths -# "context.filepaths" can, and will often be abbreviated with just "context": -# return "mplayer", context -# -# 4. "None" to indicate that no action was found. -# return None -# -# =================================================================== -# When using the "either" method, ranger determines which program to -# pick by looking at its dependencies. You can set dependencies by -# adding the decorator "depends_on": -# @depends_on("vim") -# def app_vim(self, context): -# .... -# There is a special keyword which you can use as a dependence: "X" -# This ensures that the program will only run when X is running. -# =================================================================== - -import ranger -from ranger.api.apps import * -from ranger.ext.get_executables import get_executables - -class CustomApplications(Applications): - def app_default(self, c): - """How to determine the default application?""" - f = c.file - - if f.basename.lower() == 'makefile' and c.mode == 1: - made = self.either(c, 'make') - if made: return made - - if f.extension is not None: - if f.extension in ('pdf', ): - return self.either(c, 'llpp', 'zathura', 'mupdf', 'apvlv', - 'evince', 'okular', 'epdfview') - if f.extension == 'djvu': - return self.either(c, 'evince') - if f.extension in ('xml', 'csv'): - return self.either(c, 'editor') - if f.extension == 'mid': - return self.either(c, 'wildmidi') - if f.extension in ('html', 'htm', 'xhtml') or f.extension == 'swf': - c.flags += 'd' - handler = self.either(c, - 'luakit', 'uzbl', 'vimprobable', 'vimprobable2', 'jumanji', - 'firefox', 'seamonkey', 'iceweasel', 'opera', - 'surf', 'midori', 'epiphany', 'konqueror') - # Only return if some program was found: - if handler: - return handler - if f.extension in ('html', 'htm', 'xhtml'): - # These browsers can't handle flash, so they're not called above. - c.flags += 'D' - return self.either(c, 'elinks', 'links', 'links2', 'lynx', 'w3m') - if f.extension == 'nes': - return self.either(c, 'fceux') - if f.extension in ('swc', 'smc', 'sfc'): - return self.either(c, 'zsnes') - if f.extension == 'doc': - return self.either(c, 'abiword', 'libreoffice', - 'soffice', 'ooffice') - if f.extension in ('odt', 'ods', 'odp', 'odf', 'odg', 'sxc', - 'stc', 'xls', 'xlsx', 'xlt', 'xlw', 'gnm', 'gnumeric'): - return self.either(c, 'gnumeric', 'kspread', - 'libreoffice', 'soffice', 'ooffice') - - if f.mimetype is not None: - if INTERPRETED_LANGUAGES.match(f.mimetype): - return self.either(c, 'edit_or_run') - - if f.container: - return self.either(c, 'aunpack', 'file_roller') - - if f.video or f.audio: - if f.video: - c.flags += 'd' - return self.either(c, 'smplayer', 'gmplayer', 'mplayer2', - 'mplayer', 'vlc', 'totem') - - if f.image: - if c.mode in (11, 12, 13, 14): - return self.either(c, 'set_bg_with_feh') - else: - return self.either(c, 'sxiv', 'feh', 'eog', 'mirage') - - if f.document or f.filetype.startswith('text') or f.size == 0: - return self.either(c, 'editor') - - # You can put this at the top of the function and mimeopen will - # always be used for every file. - return self.either(c, 'mimeopen') - - - # ----------------------------------------- application definitions - # Note: Trivial application definitions are at the bottom - def app_pager(self, c): - return 'less', '-R', c - - def app_editor(self, c): - try: - default_editor = os.environ['EDITOR'] - except KeyError: - pass - else: - parts = default_editor.split() - exe_name = os.path.basename(parts[0]) - if exe_name in get_executables(): - return tuple(parts) + tuple(c) - - return self.either(c, 'vim', 'emacs', 'nano') - - def app_edit_or_run(self, c): - if c.mode is 1: - return self.app_self(c) - return self.app_editor(c) - - @depends_on('mplayer') - def app_mplayer(self, c): - if c.mode is 1: - return 'mplayer', '-fs', c - - elif c.mode is 2: - args = "mplayer -fs -sid 0 -vfm ffmpeg -lavdopts " \ - "lowres=1:fast:skiploopfilter=all:threads=8".split() - args.extend(c) - return args - - elif c.mode is 3: - return 'mplayer', '-mixer', 'software', c - - else: - return 'mplayer', c - - @depends_on('mplayer2') - def app_mplayer2(self, c): - args = list(self.app_mplayer(c)) - args[0] += '2' - return args - - # A dependence on "X" means: this programs requires a running X server! - @depends_on('feh', 'X') - def app_set_bg_with_feh(self, c): - c.flags += 'd' - arg = {11: '--bg-scale', 12: '--bg-tile', 13: '--bg-center', - 14: '--bg-fill'} - if c.mode in arg: - return 'feh', arg[c.mode], c.file.path - return 'feh', arg[11], c.file.path - - @depends_on('feh', 'X') - def app_feh(self, c): - c.flags += 'd' - if c.mode is 0 and len(c.files) is 1 and self.fm.env.cwd: - # view all files in the cwd - images = [f.basename for f in self.fm.env.cwd.files if f.image] - return 'feh', '--start-at', c.file.basename, images - return 'feh', c - - @depends_on('sxiv', 'X') - def app_sxiv(self, c): - c.flags = 'd' + c.flags - if len(c.files) is 1 and self.fm.env.cwd: - images = [f.basename for f in self.fm.env.cwd.files if f.image] - try: - position = images.index(c.file.basename) + 1 - except: - return None - return 'sxiv', '-n', str(position), images - return 'sxiv', c - - @depends_on('aunpack') - def app_aunpack(self, c): - if c.mode is 0: - c.flags += 'p' - return 'aunpack', '-l', c.file.path - return 'aunpack', c.file.path - - @depends_on('file-roller', 'X') - def app_file_roller(self, c): - c.flags += 'd' - return 'file-roller', c.file.path - - @depends_on('make') - def app_make(self, c): - if c.mode is 0: - return "make" - if c.mode is 1: - return "make", "install" - if c.mode is 2: - return "make", "clear" - - @depends_on('java') - def app_java(self, c): - def strip_extensions(file): - if '.' in file.basename: - return file.path[:file.path.index('.')] - return file.path - files_without_extensions = map(strip_extensions, c.files) - return "java", files_without_extensions - - @depends_on('totem', 'X') - def app_totem(self, c): - if c.mode is 0: - return "totem", c - if c.mode is 1: - return "totem", "--fullscreen", c - - @depends_on('mimeopen') - def app_mimeopen(self, c): - if c.mode is 0: - return "mimeopen", c - if c.mode is 1: - # Will ask user to select program - # aka "Open with..." - return "mimeopen", "--ask", c - - -# Often a programs invocation is trivial. For example: -# vim test.py readme.txt [...] -# -# This could be implemented like: -# @depends_on("vim") -# def app_vim(self, context): -# return "vim", context -# -# But this is redundant and ranger does this automatically. However, sometimes -# you want to change some properties like flags or dependencies. -# The method "generic" defines a generic method for the given programs which -# looks like the one above, but you can add dependencies and flags here. -# Add programs (that are not defined yet) here if they should only run in X: -CustomApplications.generic('fceux', 'wine', 'zsnes', deps=['X']) - -# Add those which should only run in X AND should be detached/forked here: -CustomApplications.generic( - 'luakit', 'uzbl', 'vimprobable', 'vimprobable2', 'jumanji', - 'firefox', 'seamonkey', 'iceweasel', 'opera', - 'surf', 'midori', 'epiphany', 'konqueror', - 'evince', 'zathura', 'apvlv', 'okular', 'epdfview', 'mupdf', 'llpp', - 'eog', 'mirage', 'gimp', - 'libreoffice', 'soffice', 'ooffice', 'gnumeric', 'kspread', 'abiword', - 'gmplayer', 'smplayer', 'vlc', - flags='d', deps=['X']) - -# What filetypes are recognized as scripts for interpreted languages? -# This regular expression is used in app_default() -INTERPRETED_LANGUAGES = re.compile(r''' - ^(text|application)/x-( - haskell|perl|python|ruby|sh - )$''', re.VERBOSE) diff --git a/ranger/defaults/commands.py b/ranger/defaults/commands.py index a89dd0f7..52a1d30e 100644 --- a/ranger/defaults/commands.py +++ b/ranger/defaults/commands.py @@ -311,18 +311,8 @@ class open_with(Command): return app, flags, int(mode) - def tab(self): - data = self.rest(1) - if ' ' not in data: - all_apps = self.fm.apps.all() - if all_apps: - return (self.firstpart + app for app in all_apps if app.startswith(data)) - - return None - def _is_app(self, arg): - return self.fm.apps.has(arg) or \ - (not self._is_flags(arg) and arg in get_executables()) + return not self._is_flags(arg) and not arg.isdigit() def _is_flags(self, arg): return all(x in ALLOWED_FLAGS for x in arg) diff --git a/ranger/defaults/rc.conf b/ranger/defaults/rc.conf index 77ffa5c3..5ac2763a 100644 --- a/ranger/defaults/rc.conf +++ b/ranger/defaults/rc.conf @@ -53,7 +53,7 @@ map ! console shell map @ console -p6 shell %%s map # console shell -p map s console shell -map r console open_with +map r chain draw_possible_programs; console open_with map f console find map cd console cd diff --git a/ranger/defaults/rifle.conf b/ranger/defaults/rifle.conf new file mode 100644 index 00000000..9ee15b25 --- /dev/null +++ b/ranger/defaults/rifle.conf @@ -0,0 +1,181 @@ +# vim: ft=cfg +# +# This is the configuration file of "rifle", ranger's file executor/opener. +# Each line consists of conditions and a command. For each line the conditions +# are checked and if they are met, the respective command is run. +# +# Syntax: +# <condition1> , <condition2> , ... = command +# +# The command can contain these environment variables: +# $1-$9 | The n-th selected file +# $@ | All selected files +# +# Prefixing a condition with "!" will negate its result. +# These conditions are currently supported: +# match <regexp> | The regexp matches $1 +# ext <regexp> | The regexp matches the extension of $1 +# mime <regexp> | The regexp matches the mime type of $1 +# name <regexp> | The regexp matches the basename of $1 +# path <regexp> | The regexp matches the absolute path of $1 +# has <program> | The program is installed (i.e. located in $PATH) +# file | $1 is a file +# directory | $1 is a directory +# number <n> | change the number of this command to n +# terminal | stdin, stderr and stdout are connected to a terminal +# X | $DISPLAY is not empty (i.e. Xorg runs) +# +# There are also pseudo-conditions which have a "side effect": +# flag <flags> | Change how the program is run. See below. +# label <label> | Assign a label or name to the command so it can +# | be started with :open_with <label> in ranger +# | or `rifle -p <label>` in the standalone executable. +# else | Always true. +# +# Flags are single characters which slightly transform the command: +# f | Fork the program, make it run in the background. +# | New command = setsid $command >& /dev/null & +# r | Execute the command with root permissions +# | New command = sudo $command +# t | Run the program in a new terminal. If $TERMCMD is not defined, +# | rifle will attempt to extract it from $TERM. +# | New command = $TERMCMD -e $command +# +# NOTE: FLAGS DO NOT WORK PROPERLY WHEN PIPES ARE IN THE COMMAND + +#------------------------------------------- +# Websites +#------------------------------------------- +# Rarely installed browsers get higher priority; It is assumed that if you +# install a rare browser, you probably use it. Firefox/konqueror/w3m on the +# other hand are often only installed as fallback browsers. +ext x?html?, has surf, X, flag f = surf -- file://"$1" +ext x?html?, has vimprobable, X, flag f = vimprobable -- "$@" +ext x?html?, has vimprobable2, X, flag f = vimprobable2 -- "$@" +ext x?html?, has jumanji, X, flag f = jumanji -- "$@" +ext x?html?, has luakit, X, flag f = luakit -- "$@" +ext x?html?, has uzbl, X, flag f = uzbl -- "$@" +ext x?html?, has uzbl-browser, X, flag f = uzbl-browser -- "$@" +ext x?html?, has uzbl-core, X, flag f = uzbl-core -- "$@" +ext x?html?, has midori, X, flag f = midori -- "$@" +ext x?html?, has opera, X, flag f = opera -- "$@" +ext x?html?, has firefox, X, flag f = firefox -- "$@" +ext x?html?, has seamonkey, X, flag f = seamonkey -- "$@" +ext x?html?, has iceweasel, X, flag f = iceweasel -- "$@" +ext x?html?, has epiphany, X, flag f = epiphany -- "$@" +ext x?html?, has konqueror, X, flag f = konqueror -- "$@" +ext x?html?, has elinks, terminal = elinks "$@" +ext x?html?, has links2, terminal = links2 "$@" +ext x?html?, has links, terminal = links "$@" +ext x?html?, has lynx, terminal = lynx -- "$@" +ext x?html?, has w3m, terminal = w3m "$@" + +#------------------------------------------- +# Misc +#------------------------------------------- +# Define the "editor" for text files as first action +mime ^text, label editor = "$EDITOR" -- "$@" +ext xml|csv|tex, label editor = "$EDITOR" -- "$@" +mime ^text, label pager = "$PAGER" -- "$@" +ext xml|csv|tex, label pager = "$PAGER" -- "$@" + +ext 1 = man "$1" +ext s[wmf]c, has zsnes, X = zsnes "$1" +ext nes, has fceux, X = fceux "$1" +ext exe = wine "$1" +name ^[mM]akefile$ = make + +#-------------------------------------------- +# Code +#------------------------------------------- +ext py = python -- "$1" +ext pl = perl -- "$1" +ext rb = ruby -- "$1" +ext sh = bash -- "$1" +ext php = php -- "$1" + +#-------------------------------------------- +# Audio without X +#------------------------------------------- +mime ^audio, terminal, has mplayer = mplayer -- "$@" +mime ^audio, terminal, has mplayer2 = mplayer2 -- "$@" +ext midi?, terminal, has wildmidi = wildmidi -- "$@" + +#-------------------------------------------- +# Video/Audio with a GUI +#------------------------------------------- +mime ^video|audio, has gmplayer, X, flag f = gmplayer -- "$@" +mime ^video|audio, has smplayer, X, flag f = smplayer -- "$@" +mime ^video, has mplayer2, X, flag f = mplayer2 -- "$@" +mime ^video, has mplayer2, X, flag f = mplayer2 -fs -- "$@" +mime ^video, has mplayer, X, flag f = mplayer -- "$@" +mime ^video, has mplayer, X, flag f = mplayer -fs -- "$@" +mime ^video|audio, has vlc, X, flag f = vlc -- "$@" +mime ^video|audio, has totem, X, flag f = totem -- "$@" +mime ^video|audio, has totem, X, flag f = totem --fullscreen -- "$@" + +#-------------------------------------------- +# Video without X: +#------------------------------------------- +mime ^video, terminal, !X, has mplayer2 = mplayer2 -- "$@" +mime ^video, terminal, !X, has mplayer = mplayer -- "$@" + +#------------------------------------------- +# Image Viewing: +#------------------------------------------- +mime ^image, has eog, X, flag f = eog -- "$@" +mime ^image, has sxiv, X, flag f = sxiv -- "$@" +mime ^image, has feh, X, flag f = feh -- "$@" +mime ^image, has mirage, X, flag f = mirage -- "$@" +mime ^image, has gimp, X, flag f = gimp -- "$@" +ext xcf, X, flag f = gimp -- "$@" + +#------------------------------------------- +# Documents +#------------------------------------------- +ext pdf, has llpp, X, flag f = llpp "$@" +ext pdf, has zathura, X, flag f = zathura -- "$@" +ext pdf, has mupdf, X, flag f = mupdf -- "$@" +ext pdf, has apvlv, X, flag f = apvlv -- "$@" +ext pdf, has xpdf, X, flag f = xpdf -- "$@" +ext pdf, has evince, X, flag f = evince -- "$@" +ext pdf, has okular, X, flag f = okular -- "$@" +ext pdf, has epdfview, X, flag f = epdfview -- "$@" + +ext sxc|xlsx?|xlt|xlw|gnm|gnumeric, has gnumeric, X, flag f = gnumeric -- "$@" +ext sxc|xlsx?|xlt|xlw|gnm|gnumeric, has kspread, X, flag f = kspread -- "$@" +ext od[tspfg]|sxc|xlsx?|xlt|xlw|gnm|gnumeric, has libreoffice, X, flag f = libreoffice -- "$@" +ext od[tspfg]|sxc|xlsx?|xlt|xlw|gnm|gnumeric, has soffice, X, flag f = soffice -- "$@" +ext od[tspfg]|sxc|xlsx?|xlt|xlw|gnm|gnumeric, has ooffice, X, flag f = ooffice -- "$@" + +ext docx?, has catdoc, terminal = catdoc -- "$@" | "$PAGER" +ext docx?, has libreoffice, X, flag f = libreoffice -- "$@" +ext docx?, has soffice, X, flag f = soffice -- "$@" +ext docx?, has ooffice, X, flag f = ooffice -- "$@" + +ext djvu, has evince, X, flag f = evince -- "$@" + +#------------------------------------------- +# Archives +#------------------------------------------- +# This requires atool +ext 7z|ace|ar|arc|bz2?|cab|cpio|cpt|deb|dgc|dmg|gz, has als = als -- "$@" | "$PAGER" +ext iso|jar|msi|pkg|rar|shar|tar|tgz|xar|xpi|xz|zip, has als = als -- "$@" | "$PAGER" +ext 7z|ace|ar|arc|bz2?|cab|cpio|cpt|deb|dgc|dmg|gz, has aunpack = aunpack -- "$@" +ext iso|jar|msi|pkg|rar|shar|tar|tgz|xar|xpi|xz|zip, has aunpack = aunpack -- "$@" + +# Fallback: +ext tar|gz, has tar = tar vvtf "$@" | "$PAGER" +ext tar|gz, has tar = tar vvxf "$@" + +#------------------------------------------- +# Misc +#------------------------------------------- +label wallpaper, number 11, mime ^image, X = feh --bg-scale "$1" +label wallpaper, number 12, mime ^image, X = feh --bg-tile "$1" +label wallpaper, number 13, mime ^image, X = feh --bg-center "$1" +label wallpaper, number 14, mime ^image, X = feh --bg-fill "$1" + +# Define the editor for non-text files + pager as last action +label editor, !mime ^text, !ext xml|csv|tex = "$EDITOR" -- "$@" +label pager, !mime ^text !ext xml|csv|tex = "$PAGER" -- "$@" diff --git a/ranger/ext/accumulator.py b/ranger/ext/accumulator.py index d68bc656..7665c99f 100644 --- a/ranger/ext/accumulator.py +++ b/ranger/ext/accumulator.py @@ -1,17 +1,5 @@ # Copyright (C) 2009, 2010, 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. from ranger.ext.direction import Direction diff --git a/ranger/ext/cached_function.py b/ranger/ext/cached_function.py index 4d9ded18..ad7c5c11 100644 --- a/ranger/ext/cached_function.py +++ b/ranger/ext/cached_function.py @@ -1,17 +1,5 @@ # Copyright (C) 2012 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/>. +# This software is distributed under the terms of the GNU GPL version 3. def cached_function(fnc): cache = {} diff --git a/ranger/ext/curses_interrupt_handler.py b/ranger/ext/curses_interrupt_handler.py index 7c5b153e..eb86e0a9 100644 --- a/ranger/ext/curses_interrupt_handler.py +++ b/ranger/ext/curses_interrupt_handler.py @@ -1,17 +1,5 @@ # Copyright (C) 2009, 2010, 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. """ This module can catch interrupt signals which would otherwise diff --git a/ranger/ext/direction.py b/ranger/ext/direction.py index 8a37c54a..742f54da 100644 --- a/ranger/ext/direction.py +++ b/ranger/ext/direction.py @@ -1,17 +1,5 @@ # Copyright (C) 2009, 2010, 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. """ Directions provide convenient methods for movement operations. diff --git a/ranger/ext/get_executables.py b/ranger/ext/get_executables.py index 03f438dd..0c01ffd6 100644 --- a/ranger/ext/get_executables.py +++ b/ranger/ext/get_executables.py @@ -1,17 +1,5 @@ # Copyright (C) 2009, 2010, 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. from stat import S_IXOTH, S_IFREG from ranger.ext.iter_tools import unique @@ -23,13 +11,11 @@ _cached_executables = None def get_executables(): """ - Return all executable files in each of the given directories. - - Looks in $PATH by default. + Return all executable files in $PATH. Cached version. """ global _cached_executables if _cached_executables is None: - _cached_executables = sorted(get_executables_uncached()) + _cached_executables = get_executables_uncached() return _cached_executables diff --git a/ranger/ext/human_readable.py b/ranger/ext/human_readable.py index 1a667519..9667421a 100644 --- a/ranger/ext/human_readable.py +++ b/ranger/ext/human_readable.py @@ -1,17 +1,5 @@ # Copyright (C) 2009, 2010, 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. def human_readable(byte, separator=' '): """ diff --git a/ranger/ext/iter_tools.py b/ranger/ext/iter_tools.py index e515fa07..341230f4 100644 --- a/ranger/ext/iter_tools.py +++ b/ranger/ext/iter_tools.py @@ -1,17 +1,5 @@ # Copyright (C) 2009, 2010, 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. from collections import deque diff --git a/ranger/ext/keybinding_parser.py b/ranger/ext/keybinding_parser.py index 295855fb..eed85a2b 100644 --- a/ranger/ext/keybinding_parser.py +++ b/ranger/ext/keybinding_parser.py @@ -1,17 +1,5 @@ # Copyright (C) 2009, 2010, 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. import sys import copy diff --git a/ranger/ext/mount_path.py b/ranger/ext/mount_path.py index 31d6c602..19747eba 100644 --- a/ranger/ext/mount_path.py +++ b/ranger/ext/mount_path.py @@ -1,17 +1,5 @@ # Copyright (C) 2009, 2010, 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. from os.path import realpath, abspath, dirname, ismount diff --git a/ranger/ext/next_available_filename.py b/ranger/ext/next_available_filename.py index 696063cf..705e1558 100644 --- a/ranger/ext/next_available_filename.py +++ b/ranger/ext/next_available_filename.py @@ -1,17 +1,5 @@ # Copyright (C) 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. import os.path diff --git a/ranger/ext/openstruct.py b/ranger/ext/openstruct.py index b538d384..fa521d34 100644 --- a/ranger/ext/openstruct.py +++ b/ranger/ext/openstruct.py @@ -1,17 +1,5 @@ # Copyright (C) 2009, 2010, 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. # prepend __ to arguments because one might use "args" # or "keywords" as a keyword argument. diff --git a/ranger/ext/relative_symlink.py b/ranger/ext/relative_symlink.py index 420f186c..de1cb908 100644 --- a/ranger/ext/relative_symlink.py +++ b/ranger/ext/relative_symlink.py @@ -1,17 +1,5 @@ # Copyright (C) 2009, 2010, 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. from os import symlink, sep diff --git a/ranger/ext/rifle.py b/ranger/ext/rifle.py new file mode 100755 index 00000000..1080ecec --- /dev/null +++ b/ranger/ext/rifle.py @@ -0,0 +1,387 @@ +#!/usr/bin/python -S +# Copyright (C) 2012 Roman Zimbelmann <romanz@lavabit.com> +# This software is distributed under the terms of the GNU GPL version 3. + +""" +rifle, the file executor/opener of ranger + +This can be used as a standalone program or can be embedded in python code. +When used together with ranger, it doesn't have to be installed to $PATH. + +Example usage: + + rifle = Rifle("rilfe.conf") + rifle.reload_config() + rifle.execute(["file1", "file2"]) +""" + +import os.path +import re +from subprocess import Popen, PIPE +import sys + +DEFAULT_PAGER = 'less' +DEFAULT_EDITOR = 'nano' +ENCODING = 'utf-8' + +try: + from ranger.ext.get_executables import get_executables +except ImportError: + _cached_executables = None + + def get_executables(): + """ + Return all executable files in $PATH + Cache them. + """ + global _cached_executables + if _cached_executables is not None: + return _cached_executables + + if 'PATH' in os.environ: + paths = os.environ['PATH'].split(':') + else: + paths = ['/usr/bin', '/bin'] + + from stat import S_IXOTH, S_IFREG + paths_seen = set() + _cached_executables = set() + for path in paths: + if path in paths_seen: + continue + paths_seen.add(path) + try: + content = listdir(path) + except: + continue + for item in content: + abspath = path + '/' + item + try: + filestat = stat(abspath) + except: + continue + if filestat.st_mode & (S_IXOTH | S_IFREG): + _cached_executables.add(item) + return _cached_executables + + +def _is_terminal(): + # Check if stdin (file descriptor 0), stdout (fd 1) and + # stderr (fd 2) are connected to a terminal + try: + os.ttyname(0) + os.ttyname(1) + os.ttyname(2) + except: + return False + return True + + +def squash_flags(flags): + """ + Remove lowercase flags if the respective uppercase flag exists + + >>> squash_flags('abc') + 'abc' + >>> squash_flags('abcC') + 'ab' + >>> squash_flags('CabcAd') + 'bd' + """ + exclude = ''.join(f.upper() + f.lower() for f in flags if f == f.upper()) + return ''.join(f for f in flags if f not in exclude) + + +class Rifle(object): + delimiter1 = '=' + delimiter2 = ',' + + def hook_before_executing(self, command, mimetype, flags): + pass + + def hook_after_executing(self, command, mimetype, flags): + pass + + def hook_command_preprocessing(self, command): + return command + + def hook_command_postprocessing(self, command): + return command + + def hook_environment(self, env): + return env + + def hook_logger(self, string): + sys.stderr.write(string + "\n") + + def __init__(self, config_file): + self.config_file = config_file + self._app_flags = '' + self._app_label = None + + def reload_config(self, config_file=None): + """Replace the current configuration with the one in config_file""" + if config_file is None: + config_file = self.config_file + f = open(config_file, 'r') + self.rules = [] + lineno = 1 + for line in f: + if line.startswith('#') or line == '\n': + continue + line = line.strip() + try: + if self.delimiter1 not in line: + raise Exception("Line without delimiter") + tests, command = line.split(self.delimiter1, 1) + tests = tests.split(self.delimiter2) + tests = tuple(tuple(f.strip().split(None, 1)) for f in tests) + command = command.strip() + self.rules.append((command, tests)) + except Exception as e: + self.hook_logger("Syntax error in %s line %d (%s)" % \ + (config_file, lineno, str(e))) + lineno += 1 + f.close() + + def _eval_condition(self, condition, files, label): + # Handle the negation of conditions starting with an exclamation mark, + # then pass on the arguments to _eval_condition2(). + + if not condition: + return True + if condition[0].startswith('!'): + new_condition = tuple([condition[0][1:]]) + tuple(condition[1:]) + return not self._eval_condition2(new_condition, files, label) + return self._eval_condition2(condition, files, label) + + def _eval_condition2(self, rule, files, label): + # This function evaluates the condition, after _eval_condition() handled + # negation of conditions starting with a "!". + + if not files: + return False + + function = rule[0] + argument = rule[1] if len(rule) > 1 else '' + + if function == 'ext': + extension = os.path.basename(files[0]).rsplit('.', 1)[-1] + return bool(re.search('^(' + argument + ')$', extension)) + elif function == 'name': + return bool(re.search(argument, os.path.basename(files[0]))) + elif function == 'match': + return bool(re.search(argument, files[0])) + elif function == 'file': + return os.path.isfile(files[0]) + elif function == 'directory': + return os.path.isdir(files[0]) + elif function == 'path': + return bool(re.search(argument, os.path.abspath(files[0]))) + elif function == 'mime': + return bool(re.search(argument, self._get_mimetype(files[0]))) + elif function == 'has': + return argument in get_executables() + elif function == 'terminal': + return _is_terminal() + elif function == 'number': + if argument.isdigit(): + self._skip = int(argument) + return True + elif function == 'label': + self._app_label = argument + if label: + return argument == label + return True + elif function == 'flag': + self._app_flags = argument + return True + elif function == 'X': + return 'DISPLAY' in os.environ + elif function == 'else': + return True + + def _get_mimetype(self, fname): + # Spawn "file" to determine the mime-type of the given file. + if self._mimetype: + return self._mimetype + process = Popen(["file", "--mime-type", "-Lb", fname], + stdout=PIPE, stderr=PIPE) + mimetype, _ = process.communicate() + self._mimetype = mimetype.decode(ENCODING) + return self._mimetype + + def _build_command(self, files, action, flags): + # Get the flags + if isinstance(flags, str): + self._app_flags += flags + self._app_flags = squash_flags(self._app_flags) + flags = self._app_flags + + _filenames = "' '".join(f.replace("'", "'\\\''") for f in files + if "\x00" not in f) + command = "set -- '%s'" % _filenames + '\n' + + # Apply flags + command += self._apply_flags(action, flags) + return command + + def _apply_flags(self, action, flags): + # FIXME: Flags do not work properly when pipes are in the command. + if 'r' in flags: + action = 'sudo ' + action + if 't' in flags: + if 'TERMCMD' not in os.environ: + term = os.environ['TERM'] + if term.startswith('rxvt-unicode'): + term = 'urxvt' + if term not in get_executables(): + self.hook_logger("Can not determine terminal command. " + "Please set $TERMCMD manually.") + os.environ['TERMCMD'] = term + action = "$TERMCMD -e %s" % action + if 'f' in flags: + if 'setsid' in get_executables(): + action = "setsid %s > /dev/null 2> /dev/null &" % action + else: + action = "nohup %s > /dev/null 2> /dev/null &" % action + return action + + def list_commands(self, files, mimetype=None): + """ + Returns one 4-tuple for all currently applicable commands + The 4-tuple contains (count, command, label, flags). + count is the index, counted from 0 upwards, + command is the command that will be executed. + label and flags are the label and flags specified in the rule. + """ + self._mimetype = mimetype + count = -1 + for cmd, tests in self.rules: + self._skip = None + self._app_flags = '' + self._app_label = None + for test in tests: + if not self._eval_condition(test, files, None): + break + else: + if self._skip is None: + count += 1 + else: + count = self._skip + yield (count, cmd, self._app_label, self._app_flags) + + def execute(self, files, number=0, label=None, flags="", mimetype=None): + """ + Executes the given list of files. + + By default, this executes the first command where all conditions apply, + but by specifying number=N you can run the 1+Nth command. + + If a label is specified, only rules with this label will be considered. + + If you specify the mimetype, rifle will not try to determine it itself. + + By specifying a flag, you extend the flag that is defined in the rule. + Uppercase flags negate the respective lowercase flags. + For example: if the flag in the rule is "pw" and you specify "Pf", then + the "p" flag is negated and the "f" flag is added, resulting in "wf". + """ + command = None + found_at_least_one = None + + # Determine command + for count, cmd, lbl, flgs in self.list_commands(files, mimetype): + if label and label == lbl or not label and count == number: + cmd = self.hook_command_preprocessing(cmd) + command = self._build_command(files, cmd, flags + flgs) + break + else: + found_at_least_one = True + else: + if label and label in get_executables(): + cmd = '%s "$@"' % label + command = self._build_command(files, cmd, flags) + + # Execute command + if command is None: + if found_at_least_one: + if label: + self.hook_logger("Label '%s' is undefined" % label) + else: + self.hook_logger("Method number %d is undefined." % number) + else: + self.hook_logger("No action found.") + else: + if 'PAGER' not in os.environ: + os.environ['PAGER'] = DEFAULT_PAGER + if 'EDITOR' not in os.environ: + os.environ['EDITOR'] = DEFAULT_EDITOR + command = self.hook_command_postprocessing(command) + self.hook_before_executing(command, self._mimetype, self._app_flags) + try: + p = Popen(command, env=self.hook_environment(os.environ), shell=True) + p.wait() + finally: + self.hook_after_executing(command, self._mimetype, self._app_flags) + + +def main(): + """The main function which is run when you start this program direectly.""" + import sys + + # Find configuration file path + if 'XDG_CONFIG_HOME' in os.environ and os.environ['XDG_CONFIG_HOME']: + conf_path = os.environ['XDG_CONFIG_HOME'] + '/ranger/rifle.conf' + else: + conf_path = os.path.expanduser('~/.config/ranger/rifle.conf') + if not os.path.isfile(conf_path): + conf_path = os.path.normpath(os.path.join(os.path.dirname(__file__), + '../defaults/rifle.conf')) + + # Evaluate arguments + from optparse import OptionParser + parser = OptionParser(usage="%prog [-fhlpw] [files]") + parser.add_option('-f', type="string", default="", metavar="FLAGS", + help="use additional flags: f=fork, r=root, t=terminal. " + "Uppercase flag negates respective lowercase flags.") + parser.add_option('-l', action="store_true", + help="list possible ways to open the files (id:label:flags:command)") + parser.add_option('-p', type='string', default='0', metavar="KEYWORD", + help="pick a method to open the files. KEYWORD is either the " + "number listed by 'rifle -l' or a string that matches a label in " + "the configuration file") + parser.add_option('-w', type='string', default=None, metavar="PROGRAM", + help="open the files with PROGRAM") + options, positional = parser.parse_args() + if not positional: + parser.print_help() + raise SystemExit(1) + + if options.p.isdigit(): + number = int(options.p) + label = None + else: + number = 0 + label = options.p + + if options.w is not None and not options.l: + p = Popen([options.w] + list(positional)) + p.wait() + else: + # Start up rifle + rifle = Rifle(conf_path) + rifle.reload_config() + #print(rifle.list_commands(sys.argv[1:])) + if options.l: + for count, cmd, label, flags in rifle.list_commands(positional): + print("%d:%s:%s:%s" % (count, label or '', flags, cmd)) + else: + rifle.execute(positional, number=number, label=label, flags=options.f) + + +if __name__ == '__main__': + if 'RANGER_DOCTEST' in os.environ: + import doctest + doctest.testmod() + else: + main() diff --git a/ranger/ext/shell_escape.py b/ranger/ext/shell_escape.py index b68afc33..c9a22074 100644 --- a/ranger/ext/shell_escape.py +++ b/ranger/ext/shell_escape.py @@ -1,17 +1,5 @@ # Copyright (C) 2009, 2010, 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. """ Functions to escape metacharacters of arguments for shell commands. diff --git a/ranger/ext/signals.py b/ranger/ext/signals.py index 0df39fe0..c3e546e3 100644 --- a/ranger/ext/signals.py +++ b/ranger/ext/signals.py @@ -1,17 +1,5 @@ # Copyright (C) 2009, 2010, 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. """ An efficient and minimalistic signaling/hook module. diff --git a/ranger/ext/spawn.py b/ranger/ext/spawn.py index 5e5d6a95..0f3a629a 100644 --- a/ranger/ext/spawn.py +++ b/ranger/ext/spawn.py @@ -1,17 +1,5 @@ # Copyright (C) 2009, 2010, 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. from subprocess import Popen, PIPE ENCODING = 'utf-8' diff --git a/ranger/ext/widestring.py b/ranger/ext/widestring.py index 525e1bc1..44972c9c 100644 --- a/ranger/ext/widestring.py +++ b/ranger/ext/widestring.py @@ -1,18 +1,6 @@ # -*- encoding: utf8 -*- # Copyright (C) 2009, 2010, 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. import sys from unicodedata import east_asian_width diff --git a/ranger/fsobject/directory.py b/ranger/fsobject/directory.py index 81e50ed9..1abd6ddd 100644 --- a/ranger/fsobject/directory.py +++ b/ranger/fsobject/directory.py @@ -1,17 +1,5 @@ # Copyright (C) 2009, 2010, 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. import os.path from os import stat as os_stat, lstat as os_lstat diff --git a/ranger/fsobject/file.py b/ranger/fsobject/file.py index 66bc549b..39146cd5 100644 --- a/ranger/fsobject/file.py +++ b/ranger/fsobject/file.py @@ -1,17 +1,5 @@ # Copyright (C) 2009, 2010, 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. import re from ranger.fsobject import FileSystemObject diff --git a/ranger/fsobject/fsobject.py b/ranger/fsobject/fsobject.py index 943c8aa4..9c20a18f 100644 --- a/ranger/fsobject/fsobject.py +++ b/ranger/fsobject/fsobject.py @@ -1,17 +1,5 @@ # Copyright (C) 2009, 2010, 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. CONTAINER_EXTENSIONS = ('7z', 'ace', 'ar', 'arc', 'bz', 'bz2', 'cab', 'cpio', 'cpt', 'deb', 'dgc', 'dmg', 'gz', 'iso', 'jar', 'msi', 'pkg', 'rar', diff --git a/ranger/gui/ansi.py b/ranger/gui/ansi.py index 65038120..96b95669 100644 --- a/ranger/gui/ansi.py +++ b/ranger/gui/ansi.py @@ -1,18 +1,6 @@ # Copyright (C) 2010 David Barnett <davidbarnett2@gmail.com> # Copyright (C) 2010, 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. """ A library to help to convert ANSI codes to curses instructions. diff --git a/ranger/gui/bar.py b/ranger/gui/bar.py index 40218fb1..ae07dd35 100644 --- a/ranger/gui/bar.py +++ b/ranger/gui/bar.py @@ -1,17 +1,5 @@ # Copyright (C) 2009, 2010, 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. from ranger.ext.widestring import WideString, utf_char_width import sys diff --git a/ranger/gui/color.py b/ranger/gui/color.py index 889f9e9a..037ff5c1 100644 --- a/ranger/gui/color.py +++ b/ranger/gui/color.py @@ -1,17 +1,5 @@ # Copyright (C) 2009, 2010, 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. """ Contains abbreviations to curses color/attribute constants. diff --git a/ranger/gui/colorscheme.py b/ranger/gui/colorscheme.py index cc72d6a8..c77c1500 100644 --- a/ranger/gui/colorscheme.py +++ b/ranger/gui/colorscheme.py @@ -1,17 +1,5 @@ # Copyright (C) 2009, 2010, 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. """ Colorschemes define colors for specific contexts. diff --git a/ranger/gui/context.py b/ranger/gui/context.py index 3e7ca505..0227b6bc 100644 --- a/ranger/gui/context.py +++ b/ranger/gui/context.py @@ -1,17 +1,5 @@ # Copyright (C) 2009, 2010, 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. CONTEXT_KEYS = ['reset', 'error', 'badinfo', 'in_browser', 'in_statusbar', 'in_titlebar', 'in_console', diff --git a/ranger/gui/curses_shortcuts.py b/ranger/gui/curses_shortcuts.py index a383ab4c..43b583a6 100644 --- a/ranger/gui/curses_shortcuts.py +++ b/ranger/gui/curses_shortcuts.py @@ -1,18 +1,6 @@ # Copyright (C) 2009, 2010, 2011 Roman Zimbelmann <romanz@lavabit.com> # Copyright (C) 2010 David Barnett <davidbarnett2@gmail.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/>. +# This software is distributed under the terms of the GNU GPL version 3. import curses import _curses diff --git a/ranger/gui/displayable.py b/ranger/gui/displayable.py index 5e9562a7..8888d8bf 100644 --- a/ranger/gui/displayable.py +++ b/ranger/gui/displayable.py @@ -1,17 +1,5 @@ # Copyright (C) 2009, 2010, 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. from ranger.core.shared import FileManagerAware, EnvironmentAware from ranger.gui.curses_shortcuts import CursesShortcuts diff --git a/ranger/gui/mouse_event.py b/ranger/gui/mouse_event.py index cb697d8d..ed370e54 100644 --- a/ranger/gui/mouse_event.py +++ b/ranger/gui/mouse_event.py @@ -1,17 +1,5 @@ # Copyright (C) 2009, 2010, 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. import curses diff --git a/ranger/gui/ui.py b/ranger/gui/ui.py index 69b8463b..b0d3edc6 100644 --- a/ranger/gui/ui.py +++ b/ranger/gui/ui.py @@ -1,17 +1,5 @@ # Copyright (C) 2009, 2010, 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. import os import sys diff --git a/ranger/gui/widgets/browsercolumn.py b/ranger/gui/widgets/browsercolumn.py index e9c08439..eb02c1f3 100644 --- a/ranger/gui/widgets/browsercolumn.py +++ b/ranger/gui/widgets/browsercolumn.py @@ -1,18 +1,6 @@ # -*- encoding: utf8 -*- # Copyright (C) 2009, 2010, 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. """The BrowserColumn widget displays the contents of a directory or file.""" import stat diff --git a/ranger/gui/widgets/browserview.py b/ranger/gui/widgets/browserview.py index ea04c1e0..89d099ea 100644 --- a/ranger/gui/widgets/browserview.py +++ b/ranger/gui/widgets/browserview.py @@ -1,17 +1,5 @@ # Copyright (C) 2009, 2010, 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. """The BrowserView manages a set of BrowserColumns.""" import curses @@ -31,6 +19,7 @@ class BrowserView(Widget, DisplayableContainer): need_clear = False old_collapse = False draw_hints = False + draw_info = False def __init__(self, win, ratios, preview = True): DisplayableContainer.__init__(self, win) @@ -110,6 +99,8 @@ class BrowserView(Widget, DisplayableContainer): self._draw_bookmarks() elif self.draw_hints: self._draw_hints() + elif self.draw_info: + self._draw_info(self.draw_info) def finalize(self): if self.pager.visible: @@ -197,6 +188,19 @@ class BrowserView(Widget, DisplayableContainer): self.win.chgat(ystart - 1, 0, curses.A_UNDERLINE) + def _draw_info(self, lines): + self.need_clear = True + hei = min(self.hei - 1, len(lines)) + ystart = self.hei - hei + i = ystart + whitespace = " " * self.wid + for line in lines: + if i >= self.hei: + break + self.addstr(i, 0, whitespace) + self.addnstr(i, 0, line, self.wid) + i += 1 + def _draw_hints(self): self.need_clear = True hints = [] diff --git a/ranger/gui/widgets/console.py b/ranger/gui/widgets/console.py index 2376ba5a..06552ef6 100644 --- a/ranger/gui/widgets/console.py +++ b/ranger/gui/widgets/console.py @@ -1,17 +1,5 @@ # Copyright (C) 2009, 2010, 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. """ The Console widget implements a vim-like console for entering @@ -131,6 +119,7 @@ class Console(Widget): except: pass self.last_cursor_mode = None + self.fm.hide_console_info() self.add_to_history() self.tab_deque = None self.clear() diff --git a/ranger/gui/widgets/pager.py b/ranger/gui/widgets/pager.py index 38451781..566c5ff1 100644 --- a/ranger/gui/widgets/pager.py +++ b/ranger/gui/widgets/pager.py @@ -1,18 +1,6 @@ # Copyright (C) 2009, 2010, 2011 Roman Zimbelmann <romanz@lavabit.com> # Copyright (C) 2010 David Barnett <davidbarnett2@gmail.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/>. +# This software is distributed under the terms of the GNU GPL version 3. """ The pager displays text and allows you to scroll inside it. diff --git a/ranger/gui/widgets/statusbar.py b/ranger/gui/widgets/statusbar.py index 1ffb9fa3..20bc7c60 100644 --- a/ranger/gui/widgets/statusbar.py +++ b/ranger/gui/widgets/statusbar.py @@ -1,17 +1,5 @@ # Copyright (C) 2009, 2010, 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. """ The statusbar displays information about the current file and directory. diff --git a/ranger/gui/widgets/taskview.py b/ranger/gui/widgets/taskview.py index a3f8e314..59e99679 100644 --- a/ranger/gui/widgets/taskview.py +++ b/ranger/gui/widgets/taskview.py @@ -1,17 +1,5 @@ # Copyright (C) 2009, 2010, 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. """ The TaskView allows you to modify what the loader is doing. diff --git a/ranger/gui/widgets/titlebar.py b/ranger/gui/widgets/titlebar.py index 2b5e836b..f4f4cb77 100644 --- a/ranger/gui/widgets/titlebar.py +++ b/ranger/gui/widgets/titlebar.py @@ -1,17 +1,5 @@ # Copyright (C) 2009, 2010, 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. """ The titlebar is the widget at the top, giving you broad overview. diff --git a/setup.py b/setup.py index ec782794..40681290 100755 --- a/setup.py +++ b/setup.py @@ -1,18 +1,6 @@ #!/usr/bin/env python # Copyright (C) 2009, 2010, 2011 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/>. +# This software is distributed under the terms of the GNU GPL version 3. import distutils.core import ranger @@ -29,7 +17,8 @@ if __name__ == '__main__': url='http://savannah.nongnu.org/projects/ranger', scripts=['ranger/data/ranger'], data_files=[('share/man/man1', ['doc/ranger.1'])], - package_data={'ranger': ['data/*', 'defaults/rc.conf']}, + package_data={'ranger': ['data/*', 'defaults/rc.conf', + 'defaults/rifle.conf']}, packages=('ranger', 'ranger.api', 'ranger.colorschemes', |