168 lines
5.7 KiB
Python
168 lines
5.7 KiB
Python
# -*- coding: utf-8 -*-
|
|
|
|
from ranger.api.commands import *
|
|
|
|
class bulkrename(Command):
|
|
""":bulkrename
|
|
|
|
This command opens a list of selected files in an external editor.
|
|
After you edit and save the file, it will generate a shell script
|
|
which does bulk renaming according to the changes you did in the file.
|
|
|
|
This shell script is opened in an editor for you to review.
|
|
After you close it, it will be executed.
|
|
"""
|
|
def execute(self):
|
|
import sys
|
|
import tempfile
|
|
from ranger.container.file import File
|
|
from ranger.ext.shell_escape import shell_escape as esc
|
|
py3 = sys.version_info[0] >= 3
|
|
|
|
## CUSTOM: change editor here.
|
|
local_ed='emc'
|
|
|
|
# Create and edit the file list
|
|
filenames = [f.relative_path for f in self.fm.thistab.get_selection()]
|
|
listfile = tempfile.NamedTemporaryFile(delete=False)
|
|
listpath = listfile.name
|
|
|
|
if py3:
|
|
listfile.write("\n".join(filenames).encode("utf-8"))
|
|
else:
|
|
listfile.write("\n".join(filenames))
|
|
listfile.close()
|
|
self.fm.execute_file([File(listpath)], app=local_ed)
|
|
listfile = open(listpath, 'r')
|
|
new_filenames = listfile.read().split("\n")
|
|
listfile.close()
|
|
os.unlink(listpath)
|
|
if all(a == b for a, b in zip(filenames, new_filenames)):
|
|
self.fm.notify("No renaming to be done!")
|
|
return
|
|
|
|
# Generate script
|
|
cmdfile = tempfile.NamedTemporaryFile()
|
|
script_lines = []
|
|
script_lines.append("# This file will be executed when you close the editor.\n")
|
|
script_lines.append("# 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(script_content.encode("utf-8"))
|
|
else:
|
|
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=local_ed)
|
|
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")
|
|
|
|
import os
|
|
from ranger.core.loader import CommandLoader
|
|
class extracthere(Command):
|
|
def execute(self):
|
|
""" Extract copied files to current directory """
|
|
copied_files = tuple(self.fm.env.copy)
|
|
|
|
if not copied_files:
|
|
return
|
|
|
|
def refresh(_):
|
|
cwd = self.fm.env.get_directory(original_path)
|
|
cwd.load_content()
|
|
|
|
one_file = copied_files[0]
|
|
cwd = self.fm.env.cwd
|
|
original_path = cwd.path
|
|
au_flags = ['-X', cwd.path]
|
|
au_flags += self.line.split()[1:]
|
|
au_flags += ['-e']
|
|
|
|
self.fm.env.copy.clear()
|
|
self.fm.env.cut = False
|
|
if len(copied_files) == 1:
|
|
descr = "extracting: " + os.path.basename(one_file.path)
|
|
else:
|
|
descr = "extracting files from: " + os.path.basename(one_file.dirname)
|
|
obj = CommandLoader(args=['aunpack'] + au_flags \
|
|
+ [f.path for f in copied_files], descr=descr)
|
|
|
|
obj.signal_bind('after', refresh)
|
|
self.fm.loader.add(obj)
|
|
|
|
class mkcd(Command):
|
|
"""
|
|
:mkcd <dirname>
|
|
|
|
Creates a directory with the name <dirname> and enters it.
|
|
"""
|
|
|
|
def execute(self):
|
|
from os.path import join, expanduser, lexists
|
|
from os import makedirs
|
|
import re
|
|
|
|
dirname = join(self.fm.thisdir.path, expanduser(self.rest(1)))
|
|
if not lexists(dirname):
|
|
makedirs(dirname)
|
|
|
|
match = re.search('^/|^~[^/]*/', dirname)
|
|
if match:
|
|
self.fm.cd(match.group(0))
|
|
dirname = dirname[match.end(0):]
|
|
|
|
for m in re.finditer('[^/]+', dirname):
|
|
s = m.group(0)
|
|
if s == '..' or (s.startswith('.') and not self.fm.settings['show_hidden']):
|
|
self.fm.cd(s)
|
|
else:
|
|
## We force ranger to load content before calling `scout`.
|
|
self.fm.thisdir.load_content(schedule=False)
|
|
self.fm.execute_console('scout -ae ^{}$'.format(s))
|
|
else:
|
|
self.fm.notify("file/directory exists!", bad=True)
|
|
|
|
|
|
class toggle_flat(Command):
|
|
"""
|
|
:toggle_flat
|
|
|
|
Flattens or unflattens the directory view.
|
|
"""
|
|
|
|
def execute(self):
|
|
if self.fm.thisdir.flat == 0:
|
|
self.fm.thisdir.unload()
|
|
self.fm.thisdir.flat = -1
|
|
self.fm.thisdir.load_content()
|
|
else:
|
|
self.fm.thisdir.unload()
|
|
self.fm.thisdir.flat = 0
|
|
self.fm.thisdir.load_content()
|