Skip to content

Instantly share code, notes, and snippets.

@haxwithaxe
Last active December 17, 2021 16:13
Show Gist options
  • Save haxwithaxe/be3425dc41a0874e0b3ae3a4ab881a26 to your computer and use it in GitHub Desktop.
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
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