Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

POC for an extensible bulk command #2109

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open

Conversation

nfraprado
Copy link

This is a proof-of-concept for a new bulk command that is basically a generic version of bulkrename that can be extended by the user, that is, it provides an interface for the user to add custom functions that query and edit any attribute of multiple files at once.

ISSUE TYPE

  • Improvement/feature implementation

CHECKLIST

  • The CONTRIBUTING document has been read [REQUIRED]
  • All changes follow the code style [REQUIRED]
  • All new and existing tests pass [REQUIRED]
  • Changes require config files to be updated
    • Config files have been updated
  • Changes require documentation to be updated
    • Documentation has been updated
  • Changes require tests to be updated
    • Tests have been updated

DESCRIPTION

The bulkrename command provides a convenient way to edit an attribute of multiple files at once, but it is also very limited since it can only be used for renaming the files.

The new bulk command requires that the user adds two functions: one that gets the attribute for the file, and another that generates the shell script command that makes the change of the file attribute to the new one set by the user.

So the user can extend this command by providing the functions that handle the specific attribute they want to change, and the bulk command handles the common stuff that was already done by bulkrename: open the editor with the attribute for each file in each line, get the changes made by the user on exit, create a shell script with the commands for each attribute changed and finally execute the script for the changes to take effect.

MOTIVATION AND CONTEXT

This brings more flexibility and use cases for the useful but limited bulkrename.

TESTING

As an example of usage, two functions were implemented that use the bulk command, id3art and id3tit. They use the eyeD3 program to edit the artist and title ID3 tags of mp3 files, respectively.

To illustrate the usage, the users can for example: in ranger, select multiple mp3 files that they want to change the artist ID3 tag, type :bulk id3art, the editor will open up with the artist of each music file in each line.
After editing and closing, a shell script opens up with the eyeD3 commands that change the artist tag of each one that was modified.
Finally, after reviewing this script and closing, the changes take place.

IMAGES / VIDEOS

Nícolas F. R. A. Prado added 2 commits September 23, 2020 14:04
This is similar to the bulkrename command but it isn't limited to
renaming files, it can change any attribute.

Custom attributes can be added by adding a new class with two methods,
`get_attribute` and `get_change_attribute_cmd`.
The first one receives the file and should return a string representing
the current attribute value.
The second one receives the file, the old attribute value and the new
attribute value as changed by the user, and should return the string
with the command that will be run by the shell script to change the
attribute value from the old one to new one.

Finally, the object should be added as an entry in the `bulk`
dictionary, mapping the attribute name, as it should be passed as a
parameter to the `bulk` ranger command, to the object containing those
two functions.
As an example of the usage of the new bulk command, add attributes
id3art and id3tit which use eyeD3 to edit the id3 artist tag, and id3
title tag, respectively.
Copy link
Member

@toonn toonn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks promising. I'm secretly hoping we can replace bulkrename with this, aliasing it.

ranger/config/commands.py Outdated Show resolved Hide resolved
ranger/config/commands.py Outdated Show resolved Hide resolved
from ranger.ext.shell_escape import shell_escape as esc
return "eyeD3 -t %s %s" % (esc(new), esc(file))

bulk = {'id3art': id3art(),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, would be nice if this worked more like image preview methods, where you can register a method. That way this code wouldn't have to be copied and edited but people could you define a class and register.

Copy link
Author

@nfraprado nfraprado Sep 26, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed it is better. I too found using this dictionary cumbersome, but didn't know which better interface to use.

I now have added a new ext/bulk.py file containing the same interface used in the image preview methods but for these bulk commands. I was going to add it all inside the bulk(Command) class but decorator definition doesn't seem to work inside classes, or I'm doing something wrong. But it looked a little too chaotic anyway, so I moved everything to the new file (except for the commands).

I also made the id3_artist and id3_title bulk commands extend a base BulkCommand class. That way users can use the base class as reference for which functions need to be implemented and which are the parameters.
This got me thinking though, if the user should already extend this base class, we could require only BulkCommand to be extended and not the decorator to also be used to register a bulk command. This would remove the ability to have the class named differently from its nickname (which can be passed to the decorator), but this is already the case for ranger's commands.

ranger/config/commands.py Outdated Show resolved Hide resolved
@nfraprado
Copy link
Author

Thank you for reviewing, @toonn .

Some thoughts and my TODO list for this:

  • When I based this code in bulkrename, I removed the last bit where it retags the files, since it is only useful when files are being renamed, and not for every other attribute changes. If we're expecting this to replace bulkrename and be totally compatible, we should add it be back and have a property in each BulkCommand saying that it moves/renames files, so the retagging can occur for those cases.
  • We still need to add tab completion for this command but should be pretty easy using the already available tab function.
  • Until now I have referred to the bulk(Command) as the "bulk command" and to id3_artist and id3_title as "bulk commands", but this is very confusing both in the code and when writing about. Instead of "bulk commands" I thought of these alternatives: "bulk attributes" or "bulk subcommands". Suggestions?

@toonn
Copy link
Member

toonn commented Sep 27, 2020

Hmm, you're right about the retagging. Maybe a general "post command hook?" That way you can define the actions that need to be taken after the command completes. Which could be a "Blah blah finished!" message by default but be overridden with retagging for example.

I think bulk subcommands is going to be the most straightforward terminology, Attributes works well in many cases but might not in all cases, like paths aren't really attributes of files.

@nfraprado
Copy link
Author

Hmm, you're right about the retagging. Maybe a general "post command hook?" That way you can define the actions that need to be taken after the command completes. Which could be a "Blah blah finished!" message by default but be overridden with retagging for example.

Yes, that sounds even better. I'll add that as a third function in the BulkCommand class then, and also implement bulkrename using it to make sure it works ok.

I think bulk subcommands is going to be the most straightforward terminology, Attributes works well in many cases but might not in all cases, like paths aren't really attributes of files.

Sounds good. I'll rename the code to use that terminology.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants