Last active
December 17, 2021 16:13
-
-
Save haxwithaxe/be3425dc41a0874e0b3ae3a4ab881a26 to your computer and use it in GitHub Desktop.
An exersise to get ruby back in my brain. Partial reimplementation of https://github.com/haxwithaxe/tagit
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'fileutils' | |
require 'optparse' | |
def parse_args() | |
options = {method: :move, new_tags: [], remove_tags: []} | |
OptionParser.new do |opts| | |
opts.banner = 'usage: tagit -f FILE,FILE,... [-t TAG,TAG,...] [-r TAG,TAG,...] [-c|-l|-m]' | |
opts.on('-l', '--link') do | |
options[:method] = :link | |
end | |
opts.on('-c', '--copy') do | |
options[:method] = :copy | |
end | |
opts.on('-m', '--move') do | |
options[:method] = :move | |
end | |
opts.on('-f file1,file2,file3', '--files file1,file2,file3', Array) do |files| | |
options[:files] = files | |
end | |
opts.on('-t tag1,tag2,tag3', '--tags tag1,tag2,tag3', Array) do |tags| | |
options[:new_tags] = tags | |
end | |
opts.on('-r tag1,tag2,tag3', '--remove-tags tag1,tag2,tag3', Array) do |tags| | |
options[:remove_tags] = tags | |
end | |
end.parse! | |
if not options[:files] | |
puts('Files must be specifide.') | |
exit(1) | |
end | |
return options | |
end | |
def parse_filename(filename) | |
tags = [] | |
ext = '' | |
match_for_tagged = /(.*)\._tags.(.*)\._tags(\.[^.]*)?$/.match(filename) | |
if match_for_tagged | |
base = match_for_tagged[1] | |
tags = match_for_tagged[2].split('.') | |
if match_for_tagged[3] | |
ext = match_for_tagged[3] | |
end | |
return base, tags, ext | |
end | |
match_for_with_ext = /(.*)(\.[^.]*)$/.match(filename) | |
if match_for_with_ext | |
base = match_for_with_ext[1] | |
ext = match_for_with_ext[2] | |
return base, tags, ext | |
end | |
return filename, tags, ext | |
end | |
def reconsile_tags(new_tags, old_tags, remove_tags) | |
tags = new_tags + old_tags | |
tags.sort! | |
tags.uniq! | |
for tag in remove_tags do | |
begin | |
tags.delete_at(tags.index(tag)) | |
rescue TypeError | |
# Do nothing | |
end | |
end | |
return tags | |
end | |
def assemble_filename(base, tags, ext) | |
if not tags or tags.length == 0 | |
return "#{base}#{ext}" | |
end | |
return "#{base}._tags.#{tags.join('.')}._tags#{ext}" | |
end | |
def copy_tag_file(filename, new_tags, remove_tags) | |
base, existing_tags, ext = parse_filename(filename) | |
Dir.glob(assemble_filename(base, ['*'], ext)).each do |file| | |
_, tags, _ = parse_filename(file) | |
existing_tags += tags | |
if file != filename | |
File.delete(file) | |
end | |
end | |
uniq_tags = reconsile_tags(new_tags, existing_tags, remove_tags) | |
dest = assemble_filename(base, uniq_tags, ext) | |
if dest != filename | |
FileUtils.cp(filename, dest) | |
end | |
end | |
def link_tag_file(filename, new_tags, remove_tags) | |
base, existing_tags, ext = parse_filename(filename) | |
Dir.glob(assemble_filename(base, ['*'], ext)).each do |file| | |
if File.symlink?(file) | |
_, tags, _ = parse_filename(file) | |
existing_tags += tags | |
File.delete(file) | |
end | |
end | |
uniq_tags = reconsile_tags(new_tags, existing_tags, remove_tags) | |
dest = assemble_filename(base, uniq_tags, ext) | |
if dest != filename | |
File.symlink(filename, dest) | |
end | |
end | |
def move_tag_file(filename, new_tags, remove_tags) | |
base, existing_tags, ext = parse_filename(filename) | |
uniq_tags = reconsile_tags(new_tags, existing_tags, remove_tags) | |
FileUtils.mv(filename, assemble_filename(base, uniq_tags, ext)) | |
end | |
def main() | |
args = parse_args() | |
begin | |
case args[:method] | |
when :copy | |
args[:files].each do |file| | |
copy_tag_file(file, args[:new_tags], args[:remove_tags]) | |
end | |
when :link | |
args[:files].each do |file| | |
link_tag_file(file, args[:new_tags], args[:remove_tags]) | |
end | |
else | |
args[:files].each do |file| | |
move_tag_file(file, args[:new_tags], args[:remove_tags]) | |
end | |
end | |
rescue Errno::ENOENT, Errno::EACCES => err | |
puts(err) | |
end | |
end | |
main |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment