tagomatic 0.1.7 → 0.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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