diff options
author | Christian Zangl <laktak@cdak.net> | 2019-10-04 22:04:50 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-10-04 22:04:50 +0200 |
commit | cda581b3bbc47dab9873359233c7b94a268111a1 (patch) | |
tree | fba06109ea51583dc5d59c6840298a85da631ab0 /ranger | |
parent | 34ec0780589a257b061e04be12ea3e101ad83c4f (diff) | |
parent | 7338801c355e72354ec73beee798c21c46757b03 (diff) | |
download | ranger-cda581b3bbc47dab9873359233c7b94a268111a1.tar.gz |
Merge branch 'master' into paste_conflict
Diffstat (limited to 'ranger')
-rwxr-xr-x | ranger/config/commands.py | 115 | ||||
-rw-r--r-- | ranger/config/rc.conf | 10 | ||||
-rw-r--r-- | ranger/config/rifle.conf | 12 | ||||
-rw-r--r-- | ranger/container/settings.py | 5 | ||||
-rw-r--r-- | ranger/core/actions.py | 2 | ||||
-rw-r--r-- | ranger/core/main.py | 10 | ||||
-rwxr-xr-x | ranger/data/scope.sh | 1 | ||||
-rw-r--r-- | ranger/gui/widgets/statusbar.py | 6 |
8 files changed, 147 insertions, 14 deletions
diff --git a/ranger/config/commands.py b/ranger/config/commands.py index 9cbf5f2e..0eae4e19 100755 --- a/ranger/config/commands.py +++ b/ranger/config/commands.py @@ -572,7 +572,7 @@ class default_linemode(Command): class quit(Command): # pylint: disable=redefined-builtin """:quit - Closes the current tab, if there's only one tab. + Closes the current tab, if there's more than one tab. Otherwise quits if there are no tasks in progress. """ def _exit_no_work(self): @@ -591,7 +591,7 @@ class quit(Command): # pylint: disable=redefined-builtin class quit_bang(Command): """:quit! - Closes the current tab, if there's only one tab. + Closes the current tab, if there's more than one tab. Otherwise force quits immediately. """ name = 'quit!' @@ -699,6 +699,64 @@ class delete(Command): self.fm.delete(files) +class trash(Command): + """:trash + + Tries to move the selection or the files passed in arguments (if any) to + the trash, using rifle rules with label "trash". + The arguments use a shell-like escaping. + + "Selection" is defined as all the "marked files" (by default, you + can mark files with space or v). If there are no marked files, + use the "current file" (where the cursor is) + + When attempting to trash non-empty directories or multiple + marked files, it will require a confirmation. + """ + + allow_abbrev = False + escape_macros_for_shell = True + + def execute(self): + import shlex + from functools import partial + + def is_directory_with_files(path): + return os.path.isdir(path) and not os.path.islink(path) and len(os.listdir(path)) > 0 + + if self.rest(1): + files = shlex.split(self.rest(1)) + many_files = (len(files) > 1 or is_directory_with_files(files[0])) + else: + cwd = self.fm.thisdir + tfile = self.fm.thisfile + if not cwd or not tfile: + self.fm.notify("Error: no file selected for deletion!", bad=True) + return + + # relative_path used for a user-friendly output in the confirmation. + files = [f.relative_path for f in self.fm.thistab.get_selection()] + many_files = (cwd.marked_items or is_directory_with_files(tfile.path)) + + confirm = self.fm.settings.confirm_on_delete + if confirm != 'never' and (confirm != 'multiple' or many_files): + self.fm.ui.console.ask( + "Confirm deletion of: %s (y/N)" % ', '.join(files), + partial(self._question_callback, files), + ('n', 'N', 'y', 'Y'), + ) + else: + # no need for a confirmation, just delete + self.fm.execute_file(files, label='trash') + + def tab(self, tabnum): + return self._tab_directory_content() + + def _question_callback(self, files, answer): + if answer == 'y' or answer == 'Y': + self.fm.execute_file(files, label='trash') + + class jump_non(Command): """:jump_non [-FLAGS...] @@ -1244,7 +1302,7 @@ class copycmap(copymap): class copytmap(copymap): - """:copycmap <keys> <newkeys1> [<newkeys2>...] + """:copytmap <keys> <newkeys1> [<newkeys2>...] Copies a "taskview" keybinding from <keys> to <newkeys> """ @@ -1263,30 +1321,69 @@ class unmap(Command): self.fm.ui.keymaps.unbind(self.context, arg) -class cunmap(unmap): +class uncmap(unmap): + """:uncmap <keys> [<keys2>, ...] + + Remove the given "console" mappings + """ + context = 'console' + + +class cunmap(uncmap): """:cunmap <keys> [<keys2>, ...] Remove the given "console" mappings + + DEPRECATED in favor of uncmap. """ - context = 'browser' + def execute(self): + self.fm.notify("cunmap is deprecated in favor of uncmap!") + super(cunmap, self).execute() -class punmap(unmap): - """:punmap <keys> [<keys2>, ...] + +class unpmap(unmap): + """:unpmap <keys> [<keys2>, ...] Remove the given "pager" mappings """ context = 'pager' -class tunmap(unmap): - """:tunmap <keys> [<keys2>, ...] +class punmap(unpmap): + """:punmap <keys> [<keys2>, ...] + + Remove the given "pager" mappings + + DEPRECATED in favor of unpmap. + """ + + def execute(self): + self.fm.notify("punmap is deprecated in favor of unpmap!") + super(punmap, self).execute() + + +class untmap(unmap): + """:untmap <keys> [<keys2>, ...] Remove the given "taskview" mappings """ context = 'taskview' +class tunmap(untmap): + """:tunmap <keys> [<keys2>, ...] + + Remove the given "taskview" mappings + + DEPRECATED in favor of untmap. + """ + + def execute(self): + self.fm.notify("tunmap is deprecated in favor of untmap!") + super(tunmap, self).execute() + + class map_(Command): """:map <keysequence> <command> diff --git a/ranger/config/rc.conf b/ranger/config/rc.conf index f559290d..e557d4de 100644 --- a/ranger/config/rc.conf +++ b/ranger/config/rc.conf @@ -67,6 +67,9 @@ set vcs_backend_hg disabled set vcs_backend_bzr disabled set vcs_backend_svn disabled +# Truncate the long commit messages to this length when shown in the statusbar. +set vcs_msg_length 50 + # Use one of the supported image preview protocols set preview_images false @@ -301,6 +304,11 @@ set freeze_files false # Print file sizes in bytes instead of the default human-readable format. set size_in_bytes false +# Warn at startup if RANGER_LEVEL env var is greater than 0, in other words +# give a warning when you nest ranger in a subshell started by ranger. +# Special value "error" makes the warning more visible. +set nested_ranger_warning true + # =================================================================== # == Local Options # =================================================================== @@ -396,6 +404,7 @@ map <F5> copy map <F6> cut map <F7> console mkdir%space map <F8> console delete +#map <F8> console trash map <F10> exit # In case you work on a keyboard with dvorak layout @@ -483,6 +492,7 @@ map p`<any> paste dest=%any_path map p'<any> paste dest=%any_path map dD console delete +map dT console trash map dd cut map ud uncut diff --git a/ranger/config/rifle.conf b/ranger/config/rifle.conf index a90646e2..f04d1031 100644 --- a/ranger/config/rifle.conf +++ b/ranger/config/rifle.conf @@ -264,5 +264,15 @@ label wallpaper, number 14, mime ^image, has feh, X = feh --bg-fill "$1" label editor, !mime ^text, !ext xml|json|csv|tex|py|pl|rb|js|sh|php = ${VISUAL:-$EDITOR} -- "$@" label pager, !mime ^text, !ext xml|json|csv|tex|py|pl|rb|js|sh|php = "$PAGER" -- "$@" -# The very last action, so that it's never triggered accidentally, is to execute a program: + +###################################################################### +# The actions below are left so low down in this file on purpose, so # +# they are never triggered accidentally. # +###################################################################### + +# Execute a file as program/script. mime application/x-executable = "$1" + +# Move the file to trash using trash-cli. +label trash, has trash-put = trash-put -- "$@" +label trash = mkdir -p -- ${XDG_DATA_DIR:-$HOME/.ranger}/ranger-trash; mv -- "$@" ${XDG_DATA_DIR:-$HOME/.ranger}/ranger-trash diff --git a/ranger/container/settings.py b/ranger/container/settings.py index 478f6124..6fc2da5e 100644 --- a/ranger/container/settings.py +++ b/ranger/container/settings.py @@ -58,6 +58,7 @@ ALLOWED_SETTINGS = { 'max_history_size': (int, type(None)), 'metadata_deep_search': bool, 'mouse_enabled': bool, + 'nested_ranger_warning': str, 'one_indexed': bool, 'open_all_images': bool, 'padding_right': bool, @@ -93,6 +94,7 @@ ALLOWED_SETTINGS = { 'vcs_backend_git': str, 'vcs_backend_hg': str, 'vcs_backend_svn': str, + 'vcs_msg_length': int, 'viewmode': str, 'w3m_delay': float, 'w3m_offset': int, @@ -105,6 +107,7 @@ ALLOWED_VALUES = { 'confirm_on_delete': ['multiple', 'always', 'never'], 'draw_borders': ['none', 'both', 'outline', 'separators'], 'line_numbers': ['false', 'absolute', 'relative'], + 'nested_ranger_warning': ['true', 'false', 'error'], 'one_indexed': [False, True], 'preview_images_method': ['w3m', 'iterm2', 'terminology', 'urxvt', 'urxvt-full', 'kitty', @@ -276,7 +279,7 @@ class Settings(SignalDispatcher, FileManagerAware): if path: if path not in self._localsettings: try: - regex = re.compile(path) + regex = re.compile(re.escape(path)) except re.error: # Bad regular expression return self._localregexes[path] = regex diff --git a/ranger/core/actions.py b/ranger/core/actions.py index 96829f27..ed99f1c6 100644 --- a/ranger/core/actions.py +++ b/ranger/core/actions.py @@ -1608,10 +1608,10 @@ class Actions( # pylint: disable=too-many-instance-attributes,too-many-public-m def delete(self, files=None): # XXX: warn when deleting mount points/unseen marked files? - self.notify("Deleting!") # COMPAT: old command.py use fm.delete() without arguments if files is None: files = (fobj.path for fobj in self.thistab.get_selection()) + self.notify("Deleting {}!".format(", ".join(files))) files = [os.path.abspath(path) for path in files] for path in files: # Untag the deleted files. diff --git a/ranger/core/main.py b/ranger/core/main.py index 23648677..aefaacbc 100644 --- a/ranger/core/main.py +++ b/ranger/core/main.py @@ -180,6 +180,16 @@ def main( for command in args.cmd: fm.execute_console(command) + if int(os.environ[level]) > 1: + warning = 'Warning:' + nested_warning = "You're in a nested ranger instance!" + warn_when_nested = fm.settings.nested_ranger_warning.lower() + if warn_when_nested == 'true': + fm.notify(' '.join((warning, nested_warning)), bad=False) + elif warn_when_nested == 'error': + fm.notify(' '.join((warning.upper(), nested_warning + '!!')), + bad=True) + if ranger.args.profile: import cProfile import pstats diff --git a/ranger/data/scope.sh b/ranger/data/scope.sh index 306eeed0..eb09b2bf 100755 --- a/ranger/data/scope.sh +++ b/ranger/data/scope.sh @@ -45,7 +45,6 @@ HIGHLIGHT_STYLE=${HIGHLIGHT_STYLE:-pablo} HIGHLIGHT_OPTIONS="--replace-tabs=${HIGHLIGHT_TABWIDTH} --style=${HIGHLIGHT_STYLE} ${HIGHLIGHT_OPTIONS:-}" PYGMENTIZE_STYLE=${PYGMENTIZE_STYLE:-autumn} - handle_extension() { case "${FILE_EXTENSION_LOWER}" in ## Archive diff --git a/ranger/gui/widgets/statusbar.py b/ranger/gui/widgets/statusbar.py index 71064ed4..fd44613e 100644 --- a/ranger/gui/widgets/statusbar.py +++ b/ranger/gui/widgets/statusbar.py @@ -212,7 +212,11 @@ class StatusBar(Widget): # pylint: disable=too-many-instance-attributes left.add_space() left.add(directory.vcs.rootvcs.head['date'].strftime(self.timeformat), 'vcsdate') left.add_space() - left.add(directory.vcs.rootvcs.head['summary'], 'vcscommit') + summary_length = self.settings.vcs_msg_length or 50 + left.add( + directory.vcs.rootvcs.head['summary'][:summary_length], + 'vcscommit' + ) def _get_owner(self, target): uid = target.stat.st_uid |