tagomatic 0.1.7 → 0.1.8

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -19,6 +19,7 @@ rdoc
19
19
  pkg
20
20
 
21
21
  ## PROJECT::SPECIFIC
22
+ /.idea/.rakeTasks
22
23
  /.idea/encodings.xml
23
24
  /.idea/inspectionProfiles/
24
25
  /.idea/misc.xml
@@ -1,5 +1,5 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
- <project version="4">
2
+ <project relativePaths="false" version="4">
3
3
  <component name="ProjectModuleManager">
4
4
  <modules>
5
5
  <module fileurl="file://$PROJECT_DIR$/.idea/tagomatic.iml" filepath="$PROJECT_DIR$/.idea/tagomatic.iml" />
@@ -8,11 +8,14 @@
8
8
  <source manual="true" />
9
9
  </requirement>
10
10
  </component>
11
- <component name="NewModuleRootManager">
11
+ <component name="NewModuleRootManager" inherit-compiler-output="false">
12
12
  <content url="file://$MODULE_DIR$" />
13
13
  <orderEntry type="inheritedJdk" />
14
14
  <orderEntry type="sourceFolder" forTests="false" />
15
15
  <orderEntry type="library" name="[gem] ruby-mp3info (v0.6.13, /usr/lib/ruby/gems/1.8/gems/ruby-mp3info-0.6.13)" level="application" />
16
16
  </component>
17
+ <component name="RModuleSettingsStorage">
18
+ <RMODULE_SETTINGS_STORAGE_ID NAME="NUMBER" VALUE="0" />
19
+ </component>
17
20
  </module>
18
21
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.7
1
+ 0.1.8
@@ -17,7 +17,7 @@ module Tagomatic
17
17
  return nil unless matchdata
18
18
  return nil unless matchdata.captures.size == @mapping.size
19
19
  @tags = {}
20
- 0.upto(@mapping.size) do |index|
20
+ 0.upto(@mapping.size - 1) do |index|
21
21
  value = matchdata.captures[index]
22
22
  value = normalize(value) if value
23
23
  @tags[@mapping[index]] = value
@@ -48,9 +48,11 @@ module Tagomatic
48
48
  def valid_double_match_with_same_value?(base_tag, again_tag)
49
49
  return true unless @tags.has_key?(again_tag)
50
50
  return false unless @tags.has_key?(base_tag)
51
- return @tags[base_tag] == @tags[again_tag]
51
+ return @tags[base_tag].casecmp(@tags[again_tag]) == STRING_CASECMP_IS_EQUAL
52
52
  end
53
53
 
54
+ STRING_CASECMP_IS_EQUAL = 0
55
+
54
56
  end
55
57
 
56
58
  end
@@ -5,8 +5,10 @@ module Tagomatic
5
5
  PREFIXES = [
6
6
  "%g/%a/%b-%y",
7
7
  "%g/%a/%b %Y",
8
+ "%g/%a/%b %y",
8
9
  "%g/%a/%y-%b",
9
10
  "%g/%a/%Y %b",
11
+ "%g/%a/%y %b",
10
12
  "%g/%a/%b",
11
13
  ]
12
14
 
@@ -17,6 +19,9 @@ module Tagomatic
17
19
  "(disc%d)/",
18
20
  "(disk%d)/",
19
21
  "(cd%d)/",
22
+ "-disc%d/",
23
+ "-disk%d/",
24
+ "-cd%d/",
20
25
  " disc%d/",
21
26
  " disk%d/",
22
27
  " cd%d/",
@@ -7,6 +7,7 @@ require 'tagomatic/options_parser'
7
7
  require 'tagomatic/scanner'
8
8
  require 'tagomatic/system_configuration'
9
9
  require 'tagomatic/tagger'
10
+ require 'tagomatic/tags_processing_chain'
10
11
 
11
12
  module Tagomatic
12
13
 
@@ -20,10 +21,12 @@ module Tagomatic
20
21
  register :logger => Tagomatic::Logger.new(get_options)
21
22
  register :scanner => Tagomatic::Scanner.new(get_options, get_parser, get_local_options_matcher_factory, get_logger)
22
23
  register :format_matcher_factory => Tagomatic::ObjectFactory.new
24
+ register :tags_processor_factory => Tagomatic::ObjectFactory.new
25
+ register :tags_processor_chain => Tagomatic::TagsProcessingChain.new(get_options, get_tags_processor_factory, get_logger)
23
26
  register :compiler => Tagomatic::FormatCompiler.new(get_format_matcher_factory, get_logger)
24
27
  register :mp3info => Tagomatic::Mp3InfoWrapper.new
25
28
  register :info_updater_factory => Tagomatic::ObjectFactory.new
26
- register :tagger => Tagomatic::Tagger.new(get_options, get_compiler, get_mp3info, get_info_updater_factory, get_logger)
29
+ register :tagger => Tagomatic::Tagger.new(get_options, get_compiler, get_tags_processor_chain, get_mp3info, get_info_updater_factory, get_logger)
27
30
  end
28
31
 
29
32
  parser = configuration[:parser]
@@ -1,6 +1,10 @@
1
1
  require 'tagomatic/format_matcher'
2
2
  require 'tagomatic/info_updater'
3
3
  require 'tagomatic/local_options_matcher'
4
+ require 'tagomatic/tag_cleaner'
5
+ require 'tagomatic/tag_normalizer'
6
+ require 'tagomatic/tag_setter'
7
+ require 'tagomatic/url_remover'
4
8
 
5
9
  module Tagomatic
6
10
 
@@ -18,6 +22,22 @@ module Tagomatic
18
22
  Tagomatic::InfoUpdater.new(*arguments)
19
23
  end
20
24
 
25
+ def create_url_remover(*arguments)
26
+ Tagomatic::UrlRemover.new(*arguments)
27
+ end
28
+
29
+ def create_tag_cleaner(*arguments)
30
+ Tagomatic::TagCleaner.new(*arguments)
31
+ end
32
+
33
+ def create_tag_normalizer(*arguments)
34
+ Tagomatic::TagNormalizer.new(*arguments)
35
+ end
36
+
37
+ def create_tag_setter(*arguments)
38
+ Tagomatic::TagSetter.new(*arguments)
39
+ end
40
+
21
41
  end
22
42
 
23
43
  end
@@ -13,6 +13,7 @@ module Tagomatic
13
13
  self[:guess] = false
14
14
  self[:list] = false
15
15
  self[:recurse] = false
16
+ self[:removeurls] = false
16
17
  self[:showtags] = false
17
18
  self[:underscores] = false
18
19
  self[:verbose] = false
@@ -73,6 +73,9 @@ module Tagomatic
73
73
  opts.on("-r", "--[no-]recurse", "Scan for files recursively.") do |recurse|
74
74
  @options[:recurse] = recurse
75
75
  end
76
+ opts.on( "--[no-]removeurls", "Remove URLs from file names.") do |removeurls|
77
+ @options[:removeurls] = removeurls
78
+ end
76
79
  opts.on("-u", "--[no-]underscores", "Replace underscores with spaces before processing a file name.") do |underscores|
77
80
  @options[:underscores] = underscores
78
81
  end
@@ -0,0 +1,25 @@
1
+ module Tagomatic
2
+
3
+ class TagCleaner
4
+
5
+ def process(tags_hash)
6
+ artist = tags_hash['a']
7
+ artist = Regexp.compile("[ -]*#{Regexp.escape(artist)}[ -]*", Regexp::IGNORECASE) if artist
8
+
9
+ album = tags_hash['b']
10
+ album = album.sub(artist, '') if artist and album
11
+ tags_hash['b'] = album unless album.nil? or album.empty?
12
+
13
+ album = Regexp.compile("[ -]*#{Regexp.escape(album)}[ -]*", Regexp::IGNORECASE) if album
14
+
15
+ title = tags_hash['t']
16
+ title = title.sub(artist, '') if artist and title
17
+ title = title.sub(album, '') if album and title
18
+ tags_hash['t'] = title unless title.nil? or title.empty?
19
+
20
+ tags_hash
21
+ end
22
+
23
+ end
24
+
25
+ end
@@ -0,0 +1,50 @@
1
+ module Tagomatic
2
+
3
+ class TagNormalizer
4
+
5
+ def process(tags_hash)
6
+ normalized = Hash.new
7
+ tags_hash.each do |tag, value|
8
+ next unless value
9
+
10
+ split_by_spaces_and_underscores value
11
+ strip_dashes_and_brackets
12
+ drop_empty_words
13
+ capitalize_words
14
+
15
+ normalized[tag] = get_resulting_value
16
+ end
17
+ normalized
18
+ end
19
+
20
+ def split_by_spaces_and_underscores(value)
21
+ @parts = value.split(NORMALIZER_SPLIT_REGEX)
22
+ end
23
+
24
+ def strip_dashes_and_brackets
25
+ @parts.map! { |part| part.sub(NORMALIZER_STRIP_LEFT, '').sub(NORMALIZER_STRIP_RIGHT, '') }
26
+ end
27
+
28
+ def drop_empty_words
29
+ @parts = @parts.select { |part| not part.empty? }
30
+ end
31
+
32
+ def capitalize_words
33
+ @parts.map! { |part| part.capitalize }
34
+ end
35
+
36
+ def get_resulting_value
37
+ @parts.join(' ')
38
+ end
39
+
40
+ NORMALIZER_SPLIT_REGEX = /[ _-]+/
41
+
42
+ NORMALIZER_LEFT_LITERALS = Regexp.escape('-([.')
43
+ NORMALIZER_RIGHT_LITERALS = Regexp.escape('-)].')
44
+
45
+ NORMALIZER_STRIP_LEFT = /^[#{NORMALIZER_LEFT_LITERALS}]+\s*/
46
+ NORMALIZER_STRIP_RIGHT = /\s*[#{NORMALIZER_RIGHT_LITERALS}]+$/
47
+
48
+ end
49
+
50
+ end
@@ -0,0 +1,22 @@
1
+ module Tagomatic
2
+
3
+ class TagSetter
4
+
5
+ def initialize(options)
6
+ @options = options
7
+ end
8
+
9
+ def process(tags_hash)
10
+ tags_hash[:a] if @options[:artist]
11
+ tags_hash[:b] if @options[:album]
12
+ tags_hash[:d] if @options[:discnum]
13
+ tags_hash[:g] if @options[:genre]
14
+ tags_hash[:n] if @options[:tracknum]
15
+ tags_hash[:t] if @options[:title]
16
+ tags_hash[:y] if @options[:year]
17
+ tags_hash
18
+ end
19
+
20
+ end
21
+
22
+ end
@@ -12,9 +12,10 @@ module Tagomatic
12
12
  include Tagomatic::Tags
13
13
  include Tagomatic::KnownFormats
14
14
 
15
- def initialize(options, compiler, mp3info, info_updater_factory, logger)
15
+ def initialize(options, compiler, tags_processor_chain, mp3info, info_updater_factory, logger)
16
16
  @options = options
17
17
  @compiler = compiler
18
+ @tags_processor_chain = tags_processor_chain
18
19
  @mp3info = mp3info
19
20
  @info_updater_factory = info_updater_factory
20
21
  @logger = logger
@@ -26,9 +27,7 @@ module Tagomatic
26
27
  prepare_for_current_file(file_path)
27
28
  replace_underscores if @options[:underscores]
28
29
  apply_formats
29
- clean_tags if @options[:cleantags]
30
- normalize_tags
31
- apply_forced_tags
30
+ run_processor_chain
32
31
  try_updating_mp3file
33
32
  end
34
33
 
@@ -100,46 +99,9 @@ module Tagomatic
100
99
  formats.map! { |f| f.is_a?(FormatMatcher) ? f : @compiler.compile_format(f) }
101
100
  end
102
101
 
103
- def clean_tags
104
- return if @tags.nil? or @tags.empty?
105
-
106
- artist = @tags['a']
107
- artist = Regexp.compile("[ -]*#{Regexp.escape(artist)}[ -]*", Regexp::IGNORECASE) if artist
108
-
109
- album = @tags['b']
110
- album = album.sub(artist, '') if artist and album
111
- @tags['b'] = album unless album.nil? or album.empty?
112
-
113
- album = Regexp.compile("[ -]*#{Regexp.escape(album)}[ -]*", Regexp::IGNORECASE) if album
114
-
115
- title = @tags['t']
116
- title = title.sub(artist, '') if artist and title
117
- title = title.sub(album, '') if album and title
118
- @tags['t'] = title unless title.nil? or title.empty?
119
- end
120
-
121
- def normalize_tags
122
- return if @tags.nil? or @tags.empty?
123
-
124
- normalized = Hash.new
125
- @tags.each do |tag, value|
126
- next if value.nil?
127
- parts = value.gsub('_', ' ').split(' ')
128
- capitalized = parts.map {|p| p.capitalize}
129
- normalized[tag] = capitalized.join(' ')
130
- end
131
- @tags = normalized
132
- end
133
-
134
- def apply_forced_tags
102
+ def run_processor_chain
135
103
  @tags ||= Hash.new
136
- @tags[:album] if @options[:album]
137
- @tags[:artist] if @options[:artist]
138
- @tags[:discnum] if @options[:discnum]
139
- @tags[:genre] if @options[:genre]
140
- @tags[:title] if @options[:title]
141
- @tags[:tracknum] if @options[:tracknum]
142
- @tags[:year] if @options[:year]
104
+ @tags_processor_chain.process!(@tags)
143
105
  end
144
106
 
145
107
  def try_updating_mp3file
@@ -31,9 +31,9 @@ module Tagomatic
31
31
  FORMAT_ID_SURROUNDED_YEAR = 'Y'
32
32
 
33
33
  FORMAT_REGEXP_ARTIST = '([^\/]+)'
34
- FORMAT_REGEXP_ARTIST_AGAIN = FORMAT_REGEXP_ARTIST
34
+ FORMAT_REGEXP_ARTIST_AGAIN = '([^-\/]+)' # do not allow dashes - 'AGAIN' is used mostly in file name part
35
35
  FORMAT_REGEXP_ALBUM = '([^\/]+)'
36
- FORMAT_REGEXP_ALBUM_AGAIN = FORMAT_REGEXP_ALBUM
36
+ FORMAT_REGEXP_ALBUM_AGAIN = '([^-\/]+)' # do not allow dashes - 'AGAIN' is used mostly in file name part
37
37
  FORMAT_REGEXP_DISC = '\s*([0-9]+)\s*'
38
38
  FORMAT_REGEXP_GENRE = '([^\/]+)'
39
39
  FORMAT_REGEXP_IGNORE = '([^\/]+)'
@@ -41,7 +41,7 @@ module Tagomatic
41
41
  FORMAT_REGEXP_TITLE = '([^\/]+)'
42
42
  FORMAT_REGEXP_WHITESPACE = '\s*'
43
43
  FORMAT_REGEXP_EXTENDED_WHITESPACE = '[\s\-_\.]*'
44
- FORMAT_REGEXP_YEAR = '\s*([0-9]+)\s*'
44
+ FORMAT_REGEXP_YEAR = '\s*([0-9]{4})\s*'
45
45
  FORMAT_REGEXP_SURROUNDED_YEAR = '\s*[\(\[]([0-9]+)[\)\]]\s*'
46
46
 
47
47
  end
@@ -0,0 +1,32 @@
1
+ module Tagomatic
2
+
3
+ class TagsProcessingChain
4
+
5
+ def initialize(options, tags_processor_factory, logger)
6
+ @options = options
7
+ @tags_processor_factory = tags_processor_factory
8
+ @logger = logger
9
+ end
10
+
11
+ def process!(tags_hash)
12
+ return if tags_hash.nil? or tags_hash.empty?
13
+ chain = create_processor_chain
14
+ chain.each do |processor|
15
+ tags_hash.merge! processor.process(tags_hash)
16
+ end
17
+ end
18
+
19
+ protected
20
+
21
+ def create_processor_chain
22
+ chain = []
23
+ chain << @tags_processor_factory.create_url_remover if @options[:removeurls]
24
+ chain << @tags_processor_factory.create_tag_cleaner if @options[:cleantags]
25
+ chain << @tags_processor_factory.create_tag_normalizer
26
+ chain << @tags_processor_factory.create_tag_setter(@options)
27
+ chain
28
+ end
29
+
30
+ end
31
+
32
+ end
@@ -0,0 +1,16 @@
1
+ module Tagomatic
2
+
3
+ class UrlRemover
4
+
5
+ def process(tags_hash)
6
+ result = {}
7
+ tags_hash.each do |tag,value|
8
+ next unless value
9
+ result[tag] = value.gsub(/www\.[^\.]+\.[a-z]{2,4}/, '').gsub(/ by [a-zA-Z0-9]+[\w ]/, '')
10
+ end
11
+ result
12
+ end
13
+
14
+ end
15
+
16
+ end
@@ -0,0 +1,22 @@
1
+ 01-I__m A Steady Rollin' Man.mp3
2
+ 02-From four Until late.mp3
3
+ 03-Dead Shrimp Blues.mp3
4
+ 04-Little Queen of Spades.mp3
5
+ 05-They re Red Hot.mp3
6
+ 06-Preachin The Blues.mp3
7
+ 07-Hellhound On My Trail.mp3
8
+ 08-Travelling Riversida Blues.mp3
9
+ 09-Malted Milk.mp3
10
+ 10-Milkcow s Calf Blues.mp3
11
+ 11-Drunken Hearted Man.mp3
12
+ 12-Cross road Blues.mp3
13
+ 13-Come On Into My Kitchen.mp3
14
+ 14-When You Got A Good Friend.mp3
15
+ 15-32-20 Blues.mp3
16
+ 16-Phonograph Blues.mp3
17
+ 17-Last Fair Deal Gone Down.mp3
18
+ 18-Stop Breakin Down Blues.mp3
19
+ 19-Terraplane Blues.mp3
20
+ 20-Walkin' Blues.mp3
21
+ 21-Love In Vain Blues.mp3
22
+ 22-Rambling On My Mind.mp3
@@ -4,7 +4,6 @@ require 'shoulda'
4
4
 
5
5
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
6
  $LOAD_PATH.unshift(File.dirname(__FILE__))
7
- require 'tagomatic'
8
7
 
9
8
  class Test::Unit::TestCase
10
9
  end
@@ -0,0 +1,19 @@
1
+ require 'helper'
2
+
3
+ require 'tagomatic/tag_normalizer'
4
+
5
+ class TestTagNormalizer < Test::Unit::TestCase
6
+ context "A TagNormalizer" do
7
+ setup do
8
+ @tag_normalizer = Tagomatic::TagNormalizer.new
9
+ end
10
+
11
+ should "do something" do
12
+ test_tags = {:a => 'the artist', :b => 'the album - ', :t => '. title track - by lupo -'}
13
+ result = @tag_normalizer.process(test_tags)
14
+ assert_equal 'The Artist', result[:a]
15
+ assert_equal 'The Album', result[:b]
16
+ assert_equal 'Title Track By Lupo', result[:t]
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ require 'helper'
2
+
3
+ require 'tagomatic/url_remover'
4
+
5
+ class TestUrlRemover < Test::Unit::TestCase
6
+ context "A UrlRemover" do
7
+ setup do
8
+ @url_remover = Tagomatic::UrlRemover.new
9
+ end
10
+
11
+ should "remove URLs from tag values" do
12
+ test_tags = {:a => 'the artist', :b => 'the album - www.albumses.net', :t => 'title track - www.nowhere.org by lupo'}
13
+ result = @url_remover.process(test_tags)
14
+ assert_equal 'the artist', result[:a]
15
+ assert_equal 'the album - ', result[:b]
16
+ assert_equal 'title track - ', result[:t]
17
+ end
18
+ end
19
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tagomatic
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.7
4
+ version: 0.1.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Lukic
@@ -99,7 +99,6 @@ extra_rdoc_files:
99
99
  files:
100
100
  - .document
101
101
  - .gitignore
102
- - .idea/.rakeTasks
103
102
  - .idea/ant.xml
104
103
  - .idea/compiler.xml
105
104
  - .idea/dictionaries/dl.xml
@@ -128,13 +127,20 @@ files:
128
127
  - lib/tagomatic/options_parser.rb
129
128
  - lib/tagomatic/scanner.rb
130
129
  - lib/tagomatic/system_configuration.rb
130
+ - lib/tagomatic/tag_cleaner.rb
131
+ - lib/tagomatic/tag_normalizer.rb
132
+ - lib/tagomatic/tag_setter.rb
131
133
  - lib/tagomatic/tagger.rb
132
134
  - lib/tagomatic/tags.rb
135
+ - lib/tagomatic/tags_processing_chain.rb
136
+ - lib/tagomatic/url_remover.rb
133
137
  - lib/tasks/test_data.rb
134
138
  - test/data/mp3_template_file
135
139
  - test/data/sorted/80s/Peter_Schilling/1982 Fehler im System/album.dat
140
+ - test/data/sorted/Rock/Peter_Green/Peter_Green-Me_And_The_Devil-2001/album.dat
136
141
  - test/helper.rb
137
- - test/test_tagomatic.rb
142
+ - test/tagomatic/test_tag_normalizer.rb
143
+ - test/tagomatic/test_url_remover.rb
138
144
  has_rdoc: true
139
145
  homepage: http://github.com/DanielLukic/tagomatic
140
146
  licenses: []
@@ -165,4 +171,5 @@ specification_version: 3
165
171
  summary: Simple command-line mp3 tagger based on mp3info gem. Supports folder-specific configuration files.
166
172
  test_files:
167
173
  - test/helper.rb
168
- - test/test_tagomatic.rb
174
+ - test/tagomatic/test_url_remover.rb
175
+ - test/tagomatic/test_tag_normalizer.rb
@@ -1,7 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <Settings><!--This file was automatically generated by Ruby plugin.
3
- You are allowed to:
4
- 1. Remove rake task
5
- 2. Add existing rake tasks
6
- To add existing rake tasks automatically delete this file and reload the project.
7
- --><RakeGroup description="" fullCmd="" taksId="rake"><RakeTask description="Remove rcov products for rcov" fullCmd="clobber_rcov" taksId="clobber_rcov" /><RakeTask description="Remove rdoc products" fullCmd="clobber_rdoc" taksId="clobber_rdoc" /><RakeTask description="Analyze code coverage with tests" fullCmd="rcov" taksId="rcov" /><RakeTask description="Build the rdoc HTML Files" fullCmd="rdoc" taksId="rdoc" /><RakeTask description="Force a rebuild of the RDOC files" fullCmd="rerdoc" taksId="rerdoc" /><RakeTask description="Run tests" fullCmd="test" taksId="test" /><RakeTask description="" fullCmd="clobber" taksId="clobber" /><RakeTask description="" fullCmd="default" taksId="default" /><RakeTask description="" fullCmd="rdoc/index.html" taksId="rdoc/index.html" /></RakeGroup></Settings>
@@ -1,7 +0,0 @@
1
- require 'helper'
2
-
3
- class TestTagomatic < Test::Unit::TestCase
4
- should "probably rename this file and start testing for real" do
5
- flunk "hey buddy, you should probably rename this file and start testing for real"
6
- end
7
- end