diff options
-rw-r--r-- | AUTHORS | 2 | ||||
-rw-r--r-- | CHANGELOG | 24 | ||||
-rw-r--r-- | README.md | 12 | ||||
-rw-r--r-- | doc/ranger.1 | 32 | ||||
-rw-r--r-- | doc/ranger.pod | 30 | ||||
-rw-r--r-- | doc/rifle.1 | 2 | ||||
-rw-r--r-- | examples/README (renamed from doc/examples/README) | 0 | ||||
-rw-r--r-- | examples/bash_automatic_cd.sh (renamed from doc/examples/bash_automatic_cd.sh) | 4 | ||||
-rw-r--r-- | examples/bash_subshell_notice.sh (renamed from doc/examples/bash_subshell_notice.sh) | 2 | ||||
-rw-r--r-- | examples/plugin_chmod_keybindings.py (renamed from doc/examples/plugin_chmod_keybindings.py) | 2 | ||||
-rw-r--r-- | examples/plugin_file_filter.py (renamed from doc/examples/plugin_file_filter.py) | 2 | ||||
-rw-r--r-- | examples/plugin_hello_world.py (renamed from doc/examples/plugin_hello_world.py) | 2 | ||||
-rw-r--r-- | examples/plugin_new_macro.py (renamed from doc/examples/plugin_new_macro.py) | 2 | ||||
-rw-r--r-- | examples/plugin_new_sorting_method.py (renamed from doc/examples/plugin_new_sorting_method.py) | 2 | ||||
-rw-r--r-- | examples/rifle_different_file_opener.conf (renamed from doc/examples/rifle_different_file_opener.conf) | 2 | ||||
-rwxr-xr-x | examples/rifle_sxiv.sh (renamed from doc/examples/rifle_sxiv.sh) | 2 | ||||
-rw-r--r-- | examples/vim_file_chooser.vim (renamed from doc/examples/vim_file_chooser.vim) | 2 | ||||
-rwxr-xr-x | ranger.py | 4 | ||||
-rw-r--r-- | ranger/__init__.py | 4 | ||||
-rw-r--r-- | ranger/api/commands.py | 3 | ||||
-rw-r--r-- | ranger/config/commands.py | 66 | ||||
-rw-r--r-- | ranger/config/rc.conf | 15 | ||||
-rw-r--r-- | ranger/config/rifle.conf | 22 | ||||
-rw-r--r-- | ranger/container/fsobject.py | 2 | ||||
-rw-r--r-- | ranger/container/tags.py | 37 | ||||
-rw-r--r-- | ranger/core/actions.py | 22 | ||||
-rw-r--r-- | ranger/core/environment.py | 111 | ||||
-rw-r--r-- | ranger/core/fm.py | 4 | ||||
-rw-r--r-- | ranger/core/linemode.py | 18 | ||||
-rw-r--r-- | ranger/core/loader.py | 7 | ||||
-rw-r--r-- | ranger/core/shared.py | 7 | ||||
-rwxr-xr-x | ranger/ext/rifle.py | 2 | ||||
-rw-r--r-- | ranger/fsobject.py | 5 | ||||
-rw-r--r-- | ranger/gui/context.py | 2 | ||||
-rw-r--r-- | ranger/gui/displayable.py | 4 | ||||
-rw-r--r-- | ranger/gui/widgets/statusbar.py | 9 | ||||
-rwxr-xr-x | setup.py | 2 |
37 files changed, 270 insertions, 200 deletions
diff --git a/AUTHORS b/AUTHORS index 1fda9164..62387efe 100644 --- a/AUTHORS +++ b/AUTHORS @@ -22,7 +22,7 @@ Copyright 2015 No Suck <admin@nosuck.org> Copyright 2015 Randy Nance <randynobx@gmail.com> Copyright 2015 Wojciech Siewierski <wojciech.siewierski@onet.pl> -Ideally, all contributors of non-trivial code are named here to the extend that +Ideally, all contributors of non-trivial code are named here to the extent that a name and e-mail address is available. Please write a mail to hut@hut.pm if your name is missing, or in case of any other issues. diff --git a/CHANGELOG b/CHANGELOG index c5237279..041a7701 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,29 @@ This log documents changes between stable versions. +2015-04-13: version 1.7.0 +* The default editor is now "vim" instead of "nano" +* Added automatic updates of tags when a file is renamed from within ranger +* Added "preview_images_method" which can be set to "iterm2" to use native + iTerm2 image previews +* Added ":rename_append" command to rename files without the file extension +* Added ":linemode" command to change the way the files are displayed + Try this out by pressing M followed by one of the suggested keys. + New linemodes can be added with ranger.api.register_linemode(). +* Added ":filter_by_inode" command to only show directories, files or links +* Added ":meta" command for managing custom file metadata +* Added ":flat" command for displaying subdirectories +* Added "solarized" colorscheme +* Added generic ability to use scope.sh for image previews +* Added video previews in scope.sh +* Added option "sort_unicode" to sort according to unicode, not ASCII +* ":mkdir" can now create multiple directory levels (like `mkdir -p`) +* ":help" (key binding "?") is now interactive +* ":find" (key binding "/") is now case insensitive by default +* "ranger --copy-config=all" now copies a short sample commands.py rather than + the full one, so that you can update ranger without having broken commands. + The full commands.py is still copied to ~/.config/ranger/commands_full.py. +* Fixed broken copying of symlinks + 2013-05-24: Version 1.6.1 * Added support for version control systems, see: http://lists.nongnu.org/archive/html/ranger-users/2013-03/msg00007.html diff --git a/README.md b/README.md index 979aa8f9..c90dbbb8 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -ranger v.1.6.1 +ranger v.1.7.0 ============== ranger is a console file manager with Emacs key bindings. It provides a minimalistic and nice curses interface with a view on the directory hierarchy. @@ -9,11 +9,11 @@ out which program to use for what file type. This file describes ranger and how to get it to run. For instructions on the usage, please read the man page. See HACKING.md for development specific -information. For configuration, check the files in ranger/config/. They -are usually installed to /usr/lib/python*/site-packages/ranger/config/ -and can be obtained with ranger's --copy-config option. The doc/examples/ -directory contains several scripts and plugins that demonstrate how ranger can -be extended or combined with other programs. +information. For configuration, check the files in ranger/config/ or copy the +default config to ~/.config/ranger with ranger's --copy-config option. The +examples/ directory contains several scripts and plugins that demonstrate how +ranger can be extended or combined with other programs. These files can be +found in the git repository or in /usr/share/doc/ranger. A note to packagers: Versions meant for packaging are listed in the changelog on the website. diff --git a/doc/ranger.1 b/doc/ranger.1 index 7c01dc26..426ec0cf 100644 --- a/doc/ranger.1 +++ b/doc/ranger.1 @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "RANGER 1" -.TH RANGER 1 "ranger-1.6.1" "03/31/2015" "ranger manual" +.TH RANGER 1 "ranger-1.7.0" "04/13/2015" "ranger manual" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l @@ -162,8 +162,13 @@ The \fI\s-1README\s0\fR contains install instructions. The file \fI\s-1HACKING\s0.md\fR contains guidelines for code modification. .PP The directory \fIdoc/configs\fR contains configuration files. They are usually -installed to \fI/usr/lib/python*/site\-packages/ranger/config\fR and can be -obtained with ranger's \-\-copy\-config option. +installed to \fI/usr/share/doc/ranger/config\fR and can be obtained with ranger's +\&\-\-copy\-config option. +.PP +The directory \fIexamples\fR contains reference implementations for ranger +plugins, sample configuration files and some programs for integrating ranger +with other software. They are usually installed to +\&\fI/usr/share/doc/ranger/examples\fR. .PP The man page of \fIrifle\fR\|(1) describes the functions of the file opener .PP @@ -320,6 +325,14 @@ Macros for file paths are generally shell-escaped so they can be used in the Additionally, if you create a key binding that uses <any>, a special statement which accepts any key, then the macro \f(CW%any\fR (or \f(CW%any0\fR, \f(CW%any1\fR, \f(CW%any2\fR, ...) can be used in the command to get the key that was pressed. +.PP +The macro \f(CW%rangerdir\fR expands to the directory of ranger's python library, you +can use it for something like this command: + alias show_commands shell less \f(CW%rangerdir\fR/config/commands.py +.PP +The macro \f(CW%space\fR expands to a space character. You can use it to add spaces to +the end of a command when needed, while preventing editors to strip spaces off +the end of the line automatically. .SS "\s-1BOOKMARKS\s0" .IX Subsection "BOOKMARKS" Type \fB<C\-x>rm<key>\fR to bookmark the current directory. You can @@ -841,6 +854,7 @@ including their parameters, excluding descriptions: \& find pattern \& flat level \& grep pattern +\& help \& linemode linemodename \& load_copy_buffer \& map key command @@ -862,6 +876,7 @@ including their parameters, excluding descriptions: \& search pattern \& search_inc pattern \& set option value +\& setintag tags option value \& setlocal [path=<path>] option value \& shell [\-FLAGS] command \& terminal @@ -994,12 +1009,16 @@ values \-2 and less are invalid. .IP "grep \fIpattern\fR" 2 .IX Item "grep pattern" Looks for a string in all marked files or directories. +.IP "help" 2 +.IX Item "help" +Provides a quick way to view ranger documentations. .IP "linemode \fIlinemodename\fR" 2 .IX Item "linemode linemodename" Sets the linemode of all files in the current directory. The linemode may be: .Sp -.Vb 5 +.Vb 6 \& "filename": display each line as "<basename>...<size>" +\& "fileinfo": display each line as "<basename>...<file(1) output>" \& "permissions": display each line as "<permissions> <owner> <group> <basename>" \& "metatitle": display metadata from .metadata.json files if \& available, fall back to the "filename" linemode if no @@ -1140,6 +1159,11 @@ doesn't work for functions and regular expressions. Valid values are: \& list | 1,2,3,4 \& none | none .Ve +.IP "setintag \fItags\fR \fIoption\fR \fIvalue\fR" 2 +.IX Item "setintag tags option value" +Assigns a new value to an option, but locally for the directories that are +marked with \fItag\fR. This means, that this option only takes effect when +visiting that directory. .IP "setlocal [path=\fIpath\fR] \fIoption\fR \fIvalue\fR" 2 .IX Item "setlocal [path=path] option value" Assigns a new value to an option, but locally for the directory given by diff --git a/doc/ranger.pod b/doc/ranger.pod index 5ebdbc98..eea82c3e 100644 --- a/doc/ranger.pod +++ b/doc/ranger.pod @@ -35,8 +35,13 @@ The F<README> contains install instructions. The file F<HACKING.md> contains guidelines for code modification. The directory F<doc/configs> contains configuration files. They are usually -installed to F</usr/lib/python*/site-packages/ranger/config> and can be -obtained with ranger's --copy-config option. +installed to F</usr/share/doc/ranger/config> and can be obtained with ranger's +--copy-config option. + +The directory F<examples> contains reference implementations for ranger +plugins, sample configuration files and some programs for integrating ranger +with other software. They are usually installed to +F</usr/share/doc/ranger/examples>. The man page of rifle(1) describes the functions of the file opener @@ -217,6 +222,14 @@ Additionally, if you create a key binding that uses <any>, a special statement which accepts any key, then the macro %any (or %any0, %any1, %any2, ...) can be used in the command to get the key that was pressed. +The macro %rangerdir expands to the directory of ranger's python library, you +can use it for something like this command: + alias show_commands shell less %rangerdir/config/commands.py + +The macro %space expands to a space character. You can use it to add spaces to +the end of a command when needed, while preventing editors to strip spaces off +the end of the line automatically. + =head2 BOOKMARKS Type B<E<lt>C-xE<gt>rm<keyE<gt>> to bookmark the current directory. You can @@ -848,6 +861,7 @@ including their parameters, excluding descriptions: find pattern flat level grep pattern + help linemode linemodename load_copy_buffer map key command @@ -869,6 +883,7 @@ including their parameters, excluding descriptions: search pattern search_inc pattern set option value + setintag tags option value setlocal [path=<path>] option value shell [-FLAGS] command terminal @@ -1024,11 +1039,16 @@ values -2 and less are invalid. Looks for a string in all marked files or directories. +=item help + +Provides a quick way to view ranger documentations. + =item linemode I<linemodename> Sets the linemode of all files in the current directory. The linemode may be: "filename": display each line as "<basename>...<size>" + "fileinfo": display each line as "<basename>...<file(1) output>" "permissions": display each line as "<permissions> <owner> <group> <basename>" "metatitle": display metadata from .metadata.json files if available, fall back to the "filename" linemode if no @@ -1183,6 +1203,12 @@ doesn't work for functions and regular expressions. Valid values are: list | 1,2,3,4 none | none +=item setintag I<tags> I<option> I<value> + +Assigns a new value to an option, but locally for the directories that are +marked with I<tag>. This means, that this option only takes effect when +visiting that directory. + =item setlocal [path=I<path>] I<option> I<value> Assigns a new value to an option, but locally for the directory given by diff --git a/doc/rifle.1 b/doc/rifle.1 index f7e9df78..95010452 100644 --- a/doc/rifle.1 +++ b/doc/rifle.1 @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "RIFLE 1" -.TH RIFLE 1 "rifle-1.6.1" "03/31/2015" "rifle manual" +.TH RIFLE 1 "rifle-1.7.0" "04/13/2015" "rifle manual" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/doc/examples/README b/examples/README index ca514853..ca514853 100644 --- a/doc/examples/README +++ b/examples/README diff --git a/doc/examples/bash_automatic_cd.sh b/examples/bash_automatic_cd.sh index 8d72c553..ac96ea12 100644 --- a/doc/examples/bash_automatic_cd.sh +++ b/examples/bash_automatic_cd.sh @@ -1,4 +1,4 @@ -# Compatible with ranger 1.4.2 through 1.6.* +# Compatible with ranger 1.4.2 through 1.7.* # # Automatically change the directory in bash after closing ranger # @@ -8,7 +8,7 @@ # original directory. function ranger-cd { - tempfile='/tmp/chosendir' + tempfile="$(mktemp)" /usr/bin/ranger --choosedir="$tempfile" "${@:-$(pwd)}" test -f "$tempfile" && if [ "$(cat -- "$tempfile")" != "$(echo -n `pwd`)" ]; then diff --git a/doc/examples/bash_subshell_notice.sh b/examples/bash_subshell_notice.sh index bc44d5a8..4c9269c4 100644 --- a/doc/examples/bash_subshell_notice.sh +++ b/examples/bash_subshell_notice.sh @@ -1,4 +1,4 @@ -# Compatible with ranger 1.5.3 through 1.6.* +# Compatible with ranger 1.5.3 through 1.7.* # # Change the prompt when you open a shell from inside ranger # diff --git a/doc/examples/plugin_chmod_keybindings.py b/examples/plugin_chmod_keybindings.py index 0ab975ed..1c9558f7 100644 --- a/doc/examples/plugin_chmod_keybindings.py +++ b/examples/plugin_chmod_keybindings.py @@ -1,4 +1,4 @@ -# Compatible with ranger 1.6.* +# Compatible with ranger 1.6.0 through ranger 1.7.* # # This plugin serves as an example for adding key bindings through a plugin. # It could replace the ten lines in the rc.conf that create the key bindings diff --git a/doc/examples/plugin_file_filter.py b/examples/plugin_file_filter.py index b9bea1f3..d5ea2d2d 100644 --- a/doc/examples/plugin_file_filter.py +++ b/examples/plugin_file_filter.py @@ -1,4 +1,4 @@ -# Compatible since ranger 1.6.1, git commit c82a8a76989c +# Compatible since ranger 1.7.0 (git commit c82a8a76989c) # # This plugin hides the directories "/boot", "/sbin", "/proc" and "/sys" unless # the "show_hidden" option is activated. diff --git a/doc/examples/plugin_hello_world.py b/examples/plugin_hello_world.py index a803e21b..b64916d4 100644 --- a/doc/examples/plugin_hello_world.py +++ b/examples/plugin_hello_world.py @@ -1,4 +1,4 @@ -# Compatible with ranger 1.6.* +# Compatible with ranger 1.6.0 through 1.7.* # # This is a sample plugin that displays "Hello World" in ranger's console after # it started. diff --git a/doc/examples/plugin_new_macro.py b/examples/plugin_new_macro.py index 159a92f2..6757e491 100644 --- a/doc/examples/plugin_new_macro.py +++ b/examples/plugin_new_macro.py @@ -1,4 +1,4 @@ -# Compatible with ranger 1.6.* +# Compatible with ranger 1.6.0 through 1.7.* # # This plugin adds the new macro %date which is substituted with the current # date in commands that allow macros. You can test it with the command diff --git a/doc/examples/plugin_new_sorting_method.py b/examples/plugin_new_sorting_method.py index 6b41b0e1..c6e35a68 100644 --- a/doc/examples/plugin_new_sorting_method.py +++ b/examples/plugin_new_sorting_method.py @@ -1,4 +1,4 @@ -# Compatible with ranger 1.6.* +# Compatible with ranger 1.6.0 through 1.7.* # # This plugin adds the sorting algorithm called 'random'. To enable it, type # ":set sort=random" or create a key binding with ":map oz set sort=random" diff --git a/doc/examples/rifle_different_file_opener.conf b/examples/rifle_different_file_opener.conf index 4a8250b8..695f27c6 100644 --- a/doc/examples/rifle_different_file_opener.conf +++ b/examples/rifle_different_file_opener.conf @@ -1,4 +1,4 @@ -# Compatible with ranger 1.6.* +# Compatible with ranger 1.6.0 through 1.7.* # # Replace your rifle.conf with this file to use xdg-open as your file opener. # This is, of course, adaptable for use with any other file opener. diff --git a/doc/examples/rifle_sxiv.sh b/examples/rifle_sxiv.sh index 6307f1c2..8cb13907 100755 --- a/doc/examples/rifle_sxiv.sh +++ b/examples/rifle_sxiv.sh @@ -1,5 +1,5 @@ #!/bin/sh -# Compatible with ranger 1.6.* +# Compatible with ranger 1.6.0 through 1.7.* # # This script searches image files in a directory, opens them all with sxiv and # sets the first argument to the first image displayed by sxiv. diff --git a/doc/examples/vim_file_chooser.vim b/examples/vim_file_chooser.vim index aa3af763..fb9b7e1b 100644 --- a/doc/examples/vim_file_chooser.vim +++ b/examples/vim_file_chooser.vim @@ -1,4 +1,4 @@ -" Compatible with ranger 1.4.2 through 1.6.* +" Compatible with ranger 1.4.2 through 1.7.* " " Add ranger as a file chooser in vim " diff --git a/ranger.py b/ranger.py index 4b2e7daa..1d7e42e1 100755 --- a/ranger.py +++ b/ranger.py @@ -9,7 +9,7 @@ # default is simply "ranger". (Not this file itself!) # The other arguments are passed to ranger. """": -tempfile='/tmp/chosendir' +tempfile="$(mktemp)" ranger="${1:-ranger}" test -z "$1" || shift "$ranger" --choosedir="$tempfile" "${@:-$(pwd)}" @@ -17,8 +17,8 @@ returnvalue=$? test -f "$tempfile" && if [ "$(cat -- "$tempfile")" != "$(echo -n `pwd`)" ]; then cd "$(cat "$tempfile")" - rm -f -- "$tempfile" fi +rm -f -- "$tempfile" return $returnvalue """ and None diff --git a/ranger/__init__.py b/ranger/__init__.py index b850f455..fa9ba033 100644 --- a/ranger/__init__.py +++ b/ranger/__init__.py @@ -13,7 +13,7 @@ import os # Information __license__ = 'GPL3' -__version__ = '1.6.1' +__version__ = '1.7.0' __author__ = __maintainer__ = 'Roman Zimbelmann' __email__ = 'hut@hut.pm' @@ -27,7 +27,7 @@ DEFAULT_PAGER = 'less' LOGFILE = '/tmp/ranger_errorlog' CACHEDIR = os.path.expanduser("~/.cache/ranger") USAGE = '%prog [options] [path]' -VERSION = 'ranger-master %s\n\nPython %s' % (__version__, sys.version) +VERSION = 'ranger-stable %s\n\nPython %s' % (__version__, sys.version) # If the environment variable XDG_CONFIG_HOME is non-empty, CONFDIR is ignored # and the configuration directory will be $XDG_CONFIG_HOME/ranger instead. diff --git a/ranger/api/commands.py b/ranger/api/commands.py index cf8d28a7..2cf96a9f 100644 --- a/ranger/api/commands.py +++ b/ranger/api/commands.py @@ -12,9 +12,6 @@ from ranger.core.shared import FileManagerAware from ranger.ext.lazy_property import lazy_property _SETTINGS_RE = re.compile(r'^\s*([^\s]+?)=(.*)$') -DELETE_WARNING = 'delete seriously? ' # COMPAT - -def alias(*_): pass # COMPAT class CommandContainer(object): def __init__(self): diff --git a/ranger/config/commands.py b/ranger/config/commands.py index a1bc7a76..6cdd5cc2 100644 --- a/ranger/config/commands.py +++ b/ranger/config/commands.py @@ -435,7 +435,8 @@ class default_linemode(Command): def tab(self): mode = self.arg(1) return (self.arg(0) + " " + linemode - for linemode in self.fm.thisfile.linemode_dict.keys()) + for linemode in self.fm.thisfile.linemode_dict.keys() + if linemode.startswith(self.arg(1))) class quit(Command): @@ -523,10 +524,16 @@ class delete(Command): self._question_callback, ('n', 'N', 'y', 'Y')) else: # no need for a confirmation, just delete + for f in self.fm.tags.tags: + if str(f).startswith(self.fm.thisfile.path): + self.fm.tags.remove(f) self.fm.delete() def _question_callback(self, answer): if answer == 'y' or answer == 'Y': + for f in self.fm.tags.tags: + if str(f).startswith(self.fm.thisfile.path): + self.fm.tags.remove(f) self.fm.delete() @@ -725,6 +732,13 @@ class rename(Command): new_name = self.rest(1) + tagged = {} + old_name = self.fm.thisfile.basename + for f in self.fm.tags.tags: + if str(f).startswith(self.fm.thisfile.path): + tagged[f] = self.fm.tags.tags[f] + self.fm.tags.remove(f) + if not new_name: return self.fm.notify('Syntax: rename <newname>', bad=True) @@ -738,6 +752,9 @@ class rename(Command): f = File(new_name) self.fm.thisdir.pointed_obj = f self.fm.thisfile = f + for t in tagged: + self.fm.tags.tags[t.replace(old_name,new_name)] = tagged[t] + self.fm.tags.dump() def tab(self): return self._tab_directory_content() @@ -830,22 +847,47 @@ class bulkrename(Command): self.fm.notify("No renaming to be done!") return - # Generate and execute script + # Generate script cmdfile = tempfile.NamedTemporaryFile() - cmdfile.write(b"# This file will be executed when you close the editor.\n") - cmdfile.write(b"# Please double-check everything, clear the file to abort.\n") + script_lines = [] + script_lines.append(b"# This file will be executed when you close the editor.\n") + script_lines.append(b"# Please double-check everything, clear the file to abort.\n") + script_lines.extend("mv -vi -- %s %s\n" % (esc(old), esc(new)) \ + for old, new in zip(filenames, new_filenames) if old != new) + script_content = "".join(script_lines) if py3: - cmdfile.write("\n".join("mv -vi -- " + esc(old) + " " + esc(new) \ - for old, new in zip(filenames, new_filenames) \ - if old != new).encode("utf-8")) + cmdfile.write(script_content.encode("utf-8")) else: - cmdfile.write("\n".join("mv -vi -- " + esc(old) + " " + esc(new) \ - for old, new in zip(filenames, new_filenames) if old != new)) + cmdfile.write(script_content) cmdfile.flush() + + # Open the script and let the user review it, then check if the script + # was modified by the user self.fm.execute_file([File(cmdfile.name)], app='editor') + cmdfile.seek(0) + script_was_edited = (script_content != cmdfile.read()) + + # Do the renaming self.fm.run(['/bin/sh', cmdfile.name], flags='w') cmdfile.close() + # Retag the files, but only if the script wasn't changed during review, + # because only then we know which are the source and destination files. + if not script_was_edited: + tags_changed = False + for old, new in zip(filenames, new_filenames): + if old != new: + oldpath = self.fm.thisdir.path + '/' + old + newpath = self.fm.thisdir.path + '/' + new + if oldpath in self.fm.tags: + old_tag = self.fm.tags.tags[oldpath] + self.fm.tags.remove(oldpath) + self.fm.tags.tags[newpath] = old_tag + tags_changed = True + if tags_changed: + self.fm.tags.dump() + else: + fm.notify("files have not been retagged") class relink(Command): """:relink <newpath> @@ -1429,7 +1471,11 @@ class meta(prompt_metadata): key = self.arg(1) metadata = self.fm.metadata.get_metadata(self.fm.thisfile.path) if key in metadata and metadata[key]: - return self.arg(0) + " " + metadata[key] + return [" ".join([self.arg(0), self.arg(1), metadata[key]])] + else: + return [self.arg(0) + " " + key for key in sorted(metadata) + if key.startswith(self.arg(1))] + class linemode(default_linemode): """ diff --git a/ranger/config/rc.conf b/ranger/config/rc.conf index 29ccdeb8..18dc8ed4 100644 --- a/ranger/config/rc.conf +++ b/ranger/config/rc.conf @@ -237,11 +237,12 @@ map <C-x>W display_log map <C-x>w taskview_open map <A-x> console -map <A-!> console shell -map <A-f> chain draw_possible_programs; console open_with +map <A-!> console shell%space +map <A-f> chain draw_possible_programs; console open_with%space # Change the line mode map <C-x>mf linemode filename +map <C-x>mi linemode fileinfo map <C-x>mp linemode permissions map <C-x>mt linemode metatitle @@ -257,7 +258,7 @@ map <F3> display_file map <F4> edit map <F5> copy map <F6> cut -map <F7> console mkdir +map <F7> console mkdir%space map <F8> console delete map <F10> exit @@ -272,7 +273,7 @@ map <PAGEDOWN> move down=1 pages=True map <PAGEUP> move up=1 pages=True map <CR> move right=1 #map <DELETE> console delete -map <INSERT> console touch +map <INSERT> console touch%space copymap <UP> <C-p> copymap <DOWN> <C-n> @@ -315,7 +316,7 @@ map <C-x>wn shell -f echo -n %f | xsel -i; xsel -o | xsel -i -b # Filesystem Operations map <C-x>= chmod -map <A-d> console rename +map <A-d> console rename%space map <C-e> eval fm.open_console('rename ' + fm.thisfile.basename) map <C-a> eval fm.open_console('rename ' + fm.thisfile.basename, position=7) @@ -336,7 +337,7 @@ map <C-x><A-w>a copy mode=add map <C-x><A-w>r copy mode=remove # Searching -map <C-x>s console search_inc +map <C-x>s console search_inc%space map <C-s> search_next map <C-r> search_next forward=False @@ -392,7 +393,7 @@ map <C-x>zP toggle_option preview_directories map <C-x>zs toggle_option sort_case_insensitive map <C-x>zu toggle_option autoupdate_cumulative_size map <C-x>zv toggle_option use_preview_script -map <C-x>zf console filter +map <C-x>zf console filter%space # Bookmarks map <C-x>rb<any> enter_bookmark %any diff --git a/ranger/config/rifle.conf b/ranger/config/rifle.conf index 20727458..0dcc41b4 100644 --- a/ranger/config/rifle.conf +++ b/ranger/config/rifle.conf @@ -132,17 +132,6 @@ mime ^video, terminal, !X, has mplayer2 = mplayer2 -- "$@" mime ^video, terminal, !X, has mplayer = mplayer -- "$@" #------------------------------------------- -# Image Viewing: -#------------------------------------------- -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 eog, X, flag f = eog -- "$@" -mime ^image, has eom, X, flag f = eom -- "$@" -mime ^image, has gimp, X, flag f = gimp -- "$@" -ext xcf, X, flag f = gimp -- "$@" - -#------------------------------------------- # Documents #------------------------------------------- ext pdf, has llpp, X, flag f = llpp "$@" @@ -168,6 +157,17 @@ ext djvu, has evince, X, flag f = evince -- "$@" ext djvu, has atril, X, flag f = atril -- "$@" #------------------------------------------- +# Image Viewing: +#------------------------------------------- +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 eog, X, flag f = eog -- "$@" +mime ^image, has eom, X, flag f = eom -- "$@" +mime ^image, has gimp, X, flag f = gimp -- "$@" +ext xcf, X, flag f = gimp -- "$@" + +#------------------------------------------- # Archives #------------------------------------------- # This requires atool diff --git a/ranger/container/fsobject.py b/ranger/container/fsobject.py index 131e2304..1bf08e20 100644 --- a/ranger/container/fsobject.py +++ b/ranger/container/fsobject.py @@ -86,7 +86,7 @@ class FileSystemObject(FileManagerAware, SettingsAware): _linemode = DEFAULT_LINEMODE linemode_dict = dict( (linemode.name, linemode()) for linemode in - [DefaultLinemode, TitleLinemode, PermissionsLinemode] + [DefaultLinemode, TitleLinemode, PermissionsLinemode, FileInfoLinemode] ) def __init__(self, path, preload=None, path_is_abs=False, basename_is_rel_to=None): diff --git a/ranger/container/tags.py b/ranger/container/tags.py index 7ecef603..098ae9e3 100644 --- a/ranger/container/tags.py +++ b/ranger/container/tags.py @@ -109,3 +109,40 @@ class Tags(object): def __nonzero__(self): return True __bool__ = __nonzero__ + + +class TagsDummy(Tags): + """A dummy Tags class for use with `ranger --clean`. + + It acts like there are no tags and avoids writing any changes. + """ + + def __init__(self, filename): + self.tags = dict() + + def __contains__(self, item): + return False + + def add(self, *items, **others): + pass + + def remove(self, *items, **others): + pass + + def toggle(self, *items, **others): + pass + + def marker(self, item): + return self.default_tag + + def sync(self): + pass + + def dump(self): + pass + + def _compile(self, f): + pass + + def _parse(self, f): + pass diff --git a/ranger/core/actions.py b/ranger/core/actions.py index c7bdcfec..58f7aa20 100644 --- a/ranger/core/actions.py +++ b/ranger/core/actions.py @@ -21,8 +21,7 @@ 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, ASK_COMMAND -from ranger.core.shared import FileManagerAware, EnvironmentAware, \ - SettingsAware +from ranger.core.shared import FileManagerAware, SettingsAware from ranger.core.tab import Tab from ranger.container.file import File from ranger.core.loader import CommandLoader, CopyLoader @@ -36,7 +35,7 @@ class _MacroTemplate(string.Template): delimiter = ranger.MACRO_DELIMITER idpattern = r"[_a-z0-9]*" -class Actions(FileManagerAware, EnvironmentAware, SettingsAware): +class Actions(FileManagerAware, SettingsAware): # -------------------------- # -- Basic Commands # -------------------------- @@ -210,6 +209,7 @@ class Actions(FileManagerAware, EnvironmentAware, SettingsAware): macros = {} macros['rangerdir'] = ranger.RANGERDIR + macros['space'] = ' ' if self.fm.thisfile: macros['f'] = self.fm.thisfile.relative_path @@ -306,13 +306,17 @@ class Actions(FileManagerAware, EnvironmentAware, SettingsAware): (line, str(e)), bad=True) def execute_file(self, files, **kw): - """Execute a file. + """Uses the "rifle" module to open/execute a file - app is the name of a method in Applications, without the "app_" - flags is a string consisting of runner.ALLOWED_FLAGS - mode is a positive integer. - Both flags and mode specify how the program is run.""" - # TODO: docstring out of date + Arguments are the same as for ranger.ext.rifle.Rifle.execute: + + files: a list of file objects (not strings!) + number: a number to select which way to open the file, in case there + are multiple choices + label: a string to select an opening method by its label + flags: a string specifying additional options, see `man rifle` + mimetyle: pass the mimetype to rifle, overriding its own guess + """ mode = kw['mode'] if 'mode' in kw else 0 diff --git a/ranger/core/environment.py b/ranger/core/environment.py deleted file mode 100644 index fddb8f9f..00000000 --- a/ranger/core/environment.py +++ /dev/null @@ -1,111 +0,0 @@ -# This file is part of ranger, the console file manager. -# License: GNU GPL version 3, see the file "AUTHORS" for details. - -# THIS WHOLE FILE IS OBSOLETE AND EXISTS FOR BACKWARDS COMPATIBILITIY - -import os -from ranger.ext.signals import SignalDispatcher -from ranger.core.shared import SettingsAware, FileManagerAware - -# COMPAT -class Environment(SettingsAware, FileManagerAware, SignalDispatcher): - def __init__(self, path): - SignalDispatcher.__init__(self) - - def _get_copy(self): return self.fm.copy_buffer - def _set_copy(self, obj): self.fm.copy_buffer = obj - copy = property(_get_copy, _set_copy) - - def _get_cut(self): return self.fm.do_cut - def _set_cut(self, obj): self.fm.do_cut = obj - cut = property(_get_cut, _set_cut) - - def _get_keymaps(self): return self.fm.ui.keymaps - def _set_keymaps(self, obj): self.fm.ui.keymaps = obj - keymaps = property(_get_keymaps, _set_keymaps) - - def _get_keybuffer(self): return self.fm.ui.keybuffer - def _set_keybuffer(self, obj): self.fm.ui.keybuffer = obj - keybuffer = property(_get_keybuffer, _set_keybuffer) - - def _get_username(self): return self.fm.username - def _set_username(self, obj): self.fm.username = obj - username = property(_get_username, _set_username) - - def _get_hostname(self): return self.fm.hostname - def _set_hostname(self, obj): self.fm.hostname = obj - hostname = property(_get_hostname, _set_hostname) - - def _get_home_path(self): return self.fm.home_path - def _set_home_path(self, obj): self.fm.home_path = obj - home_path = property(_get_home_path, _set_home_path) - - def _get_get_directory(self): return self.fm.get_directory - def _set_get_directory(self, obj): self.fm.get_directory = obj - get_directory = property(_get_get_directory, _set_get_directory) - - def _get_garbage_collect(self): return self.fm.garbage_collect - def _set_garbage_collect(self, obj): self.fm.garbage_collect = obj - garbage_collect = property(_get_garbage_collect, _set_garbage_collect) - - def _get_cwd(self): return self.fm.thisdir - def _set_cwd(self, obj): self.fm.thisdir = obj - cwd = property(_get_cwd, _set_cwd) - - def _get_cf(self): return self.fm.thisfile - def _set_cf(self, obj): self.fm.thisfile = obj - cf = property(_get_cf, _set_cf) - - def _get_history(self): return self.fm.thistab.history - def _set_history(self, obj): self.fm.thistab.history = obj - history = property(_get_history, _set_history) - - def _get_last_search(self): return self.fm.thistab.last_search - def _set_last_search(self, obj): self.fm.thistab.last_search = obj - last_search = property(_get_last_search, _set_last_search) - - def _get_path(self): return self.fm.thistab.path - def _set_path(self, obj): self.fm.thistab.path = obj - path = property(_get_path, _set_path) - - def _get_pathway(self): return self.fm.thistab.pathway - def _set_pathway(self, obj): self.fm.thistab.pathway = obj - pathway = property(_get_pathway, _set_pathway) - - def _get_enter_dir(self): return self.fm.thistab.enter_dir - def _set_enter_dir(self, obj): self.fm.thistab.enter_dir = obj - enter_dir = property(_get_enter_dir, _set_enter_dir) - - def _get_at_level(self): return self.fm.thistab.at_level - def _set_at_level(self, obj): self.fm.thistab.at_level = obj - at_level = property(_get_at_level, _set_at_level) - - def _get_get_selection(self): return self.fm.thistab.get_selection - def _set_get_selection(self, obj): self.fm.thistab.get_selection = obj - get_selection = property(_get_get_selection, _set_get_selection) - - def _get_assign_cursor_positions_for_subdirs(self): - return self.fm.thistab.assign_cursor_positions_for_subdirs - def _set_assign_cursor_positions_for_subdirs(self, obj): - self.fm.thistab.assign_cursor_positions_for_subdirs = obj - assign_cursor_positions_for_subdirs = property( - _get_assign_cursor_positions_for_subdirs, - _set_assign_cursor_positions_for_subdirs) - - def _get_ensure_correct_pointer(self): - return self.fm.thistab.ensure_correct_pointer - def _set_ensure_correct_pointer(self, obj): - self.fm.thistab.ensure_correct_pointer = obj - ensure_correct_pointer = property(_get_ensure_correct_pointer, - _set_ensure_correct_pointer) - - def _get_history_go(self): return self.fm.thistab.history_go - def _set_history_go(self, obj): self.fm.thistab.history_go = obj - history_go = property(_get_history_go, _set_history_go) - - def _set_cf_from_signal(self, signal): - self.fm._cf = signal.new - - def get_free_space(self, path): - stat = os.statvfs(path) - return stat.f_bavail * stat.f_frsize diff --git a/ranger/core/fm.py b/ranger/core/fm.py index c95ec905..0ba0f546 100644 --- a/ranger/core/fm.py +++ b/ranger/core/fm.py @@ -15,7 +15,7 @@ import sys import ranger.api from ranger.core.actions import Actions from ranger.core.tab import Tab -from ranger.container.tags import Tags +from ranger.container.tags import Tags, TagsDummy from ranger.gui.ui import UI from ranger.container.bookmarks import Bookmarks from ranger.core.runner import Runner @@ -100,6 +100,8 @@ class FM(Actions, SignalDispatcher): if not ranger.arg.clean and self.tags is None: self.tags = Tags(self.confpath('tagged')) + elif ranger.arg.clean: + self.tags = TagsDummy("") if self.bookmarks is None: if ranger.arg.clean: diff --git a/ranger/core/linemode.py b/ranger/core/linemode.py index 7993af82..56fd3522 100644 --- a/ranger/core/linemode.py +++ b/ranger/core/linemode.py @@ -3,6 +3,7 @@ # License: GNU GPL version 3, see the file "AUTHORS" for details. # Author: Wojciech Siewierski <wojciech.siewierski@onet.pl>, 2015 +import sys from abc import * DEFAULT_LINEMODE = "filename" @@ -84,3 +85,20 @@ class PermissionsLinemode(LinemodeBase): def infostring(self, file, metadata): return "" + + +class FileInfoLinemode(LinemodeBase): + name = "fileinfo" + + def filetitle(self, file, metadata): + return file.relative_path + + def infostring(self, file, metadata): + if not file.is_directory: + from subprocess import check_output + fileinfo = check_output(["file", "-bL", file.path]).strip() + if sys.version_info[0] >= 3: + fileinfo = fileinfo.decode("utf-8") + return fileinfo + else: + raise NotImplementedError diff --git a/ranger/core/loader.py b/ranger/core/loader.py index 86a591f0..8eda544f 100644 --- a/ranger/core/loader.py +++ b/ranger/core/loader.py @@ -85,6 +85,13 @@ class CopyLoader(Loadable, FileManagerAware): else: self.description = "moving files from: " + self.one_file.dirname for f in self.copy_buffer: + for tf in self.fm.tags.tags: + if tf == f.path or str(tf).startswith(f.path): + tag = self.fm.tags.tags[tf] + self.fm.tags.remove(tf) + self.fm.tags.tags[tf.replace(f.path, self.original_path \ + + '/' + f.basename)] = tag + self.fm.tags.dump() for _ in shutil_g.move(src=f.path, dst=self.original_path, overwrite=self.overwrite): diff --git a/ranger/core/shared.py b/ranger/core/shared.py index ab76b511..177ba15d 100644 --- a/ranger/core/shared.py +++ b/ranger/core/shared.py @@ -16,10 +16,3 @@ class SettingsAware(object): @staticmethod def _setup(settings): SettingsAware.settings = settings - -class EnvironmentAware(object): # COMPAT - """DO NOT USE. This is for backward compatibility only.""" - @lazy_property - def env(self): - from ranger.core.environment import Environment - return Environment(".") diff --git a/ranger/ext/rifle.py b/ranger/ext/rifle.py index ddbfed07..b75b38b2 100755 --- a/ranger/ext/rifle.py +++ b/ranger/ext/rifle.py @@ -19,7 +19,7 @@ import re from subprocess import Popen, PIPE import sys -__version__ = 'rifle 1.6.1' +__version__ = 'rifle 1.7.0' # Options and constants that a user might want to change: DEFAULT_PAGER = 'less' diff --git a/ranger/fsobject.py b/ranger/fsobject.py deleted file mode 100644 index 2edaaf79..00000000 --- a/ranger/fsobject.py +++ /dev/null @@ -1,5 +0,0 @@ -# THIS WHOLE FILE IS OBSOLETE AND EXISTS FOR BACKWARDS COMPATIBILITIY - -from ranger.container.fsobject import FileSystemObject, BAD_INFO -from ranger.container.file import File -from ranger.container.directory import Directory diff --git a/ranger/gui/context.py b/ranger/gui/context.py index 2ad27434..e5aef06c 100644 --- a/ranger/gui/context.py +++ b/ranger/gui/context.py @@ -11,7 +11,7 @@ CONTEXT_KEYS = ['reset', 'error', 'badinfo', 'good', 'bad', 'space', 'permissions', 'owner', 'group', 'mtime', 'nlink', 'scroll', 'all', 'bot', 'top', 'percentage', 'filter', - 'marked', 'tagged', 'tag_marker', 'cut', 'copied', + 'flat', 'marked', 'tagged', 'tag_marker', 'cut', 'copied', 'help_markup', # COMPAT 'seperator', 'key', 'special', 'border', # COMPAT 'title', 'text', 'highlight', 'bars', 'quotes', 'tab', 'loaded', diff --git a/ranger/gui/displayable.py b/ranger/gui/displayable.py index 7e4290ee..d3adfe50 100644 --- a/ranger/gui/displayable.py +++ b/ranger/gui/displayable.py @@ -1,10 +1,10 @@ # This file is part of ranger, the console file manager. # License: GNU GPL version 3, see the file "AUTHORS" for details. -from ranger.core.shared import FileManagerAware, EnvironmentAware +from ranger.core.shared import FileManagerAware from ranger.gui.curses_shortcuts import CursesShortcuts -class Displayable(EnvironmentAware, FileManagerAware, CursesShortcuts): +class Displayable(FileManagerAware, CursesShortcuts): """Displayables are objects which are displayed on the screen. This is just the abstract class, defining basic operations diff --git a/ranger/gui/widgets/statusbar.py b/ranger/gui/widgets/statusbar.py index 9ff331a0..f5824d99 100644 --- a/ranger/gui/widgets/statusbar.py +++ b/ranger/gui/widgets/statusbar.py @@ -242,8 +242,15 @@ class StatusBar(Widget): max_pos = len(target) - self.column.hei base = 'scroll' + right.add(" ", "space") + + if self.fm.thisdir.flat: + right.add("flat=", base, 'flat') + right.add(str(self.fm.thisdir.flat), base, 'flat') + right.add(", ", "space") + if self.fm.thisdir.filter: - right.add(" f=`", base, 'filter') + right.add("f=`", base, 'filter') right.add(self.fm.thisdir.filter.pattern, base, 'filter') right.add("', ", "space") diff --git a/setup.py b/setup.py index c646f3fb..1e074f8d 100755 --- a/setup.py +++ b/setup.py @@ -34,7 +34,7 @@ if __name__ == '__main__': _findall('doc/config/colorschemes')), ('share/doc/ranger/config', _findall('doc/config')), ('share/doc/ranger/tools', _findall('doc/tools')), - ('share/doc/ranger/examples', _findall('doc/examples')), + ('share/doc/ranger/examples', _findall('examples')), ], package_data={'ranger': ['data/*', 'config/rc.conf', 'config/rifle.conf']}, |