lc_callnumber 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 080e05e9e7c6084e500e3fb0ca2d827c4dc52474
4
+ data.tar.gz: 222d0cce1e42df11b29496b191da1ed60ae37e42
5
+ SHA512:
6
+ metadata.gz: 3291b552acdb8d6339d0043ac0cbe66e0e906f4b007c3e04a4dcc972a4947e299930bb1c66bbb999a6bb8510d0b55ec6b2611e59dc9aafe7f76077c70bcd76c5
7
+ data.tar.gz: 8d5840f2a39cbcee9aedb56135b7b556c2eb046615224331c4c40ff97bdbb59f08602154f2e5d9ff22831c03620d2ef95511d0cd6d182ec04eb81fd7229e425c
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ bundler_args: --without documentation
3
+ rvm:
4
+ - 1.9.3
5
+ - 2.1
6
+ - jruby-19mode
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in lc_callnumber.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Bill Dueber
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,91 @@
1
+ [![Build Status](https://secure.travis-ci.org/billdueber/lc_callnumber.png)](http://travis-ci.org/billdueber/lc_callnumber)
2
+
3
+ # LCCallNumber
4
+
5
+ Very simple attempt to work with Library of Congress Call Numbers (_nee_ Classification Numbers).
6
+ Includes simple getters/setters and a PEG parser.
7
+
8
+
9
+ ## Things that aren't yet done
10
+
11
+ * Normalization: create a string that can be compared with other normalized strings to correctly order the call numbers
12
+ * Implement `<=>` so call number object can be compared.
13
+ * Much better testing
14
+
15
+
16
+ ## Parts of an LC Call Number
17
+
18
+ LC Call Numbers are used in libraries to classify and order books and other items.
19
+
20
+ Some (increasingly complex) samples are:
21
+
22
+ * A1
23
+ * A1.2 .B3
24
+ * A1.2 .B3 .C4
25
+ * A1.2 .B3 1990
26
+ * A1.2 1888 .B3 .C4 2000
27
+ * A1.2 .A54 21st 2010
28
+
29
+ The OCLC has [a page explaining how LC Call Numbers are composed](http://www.oclc.org/bibformats/en/0xx/050.html), which you should reference if you feel the need.
30
+
31
+ For purposes of this class, an LC Call Number consists of the following parts. Only the first two are required; everything else is optional.
32
+
33
+ * __Letter(s).__ One or more letters
34
+ * __Digit(s).__ One or more digits, optionally with a decimal point.
35
+ * __Doon1 (_Date Or Other Number_)__. Relatively rare as these things go, a DOON is used to represent the date the work is _about_ (as opposed to, say, the year it was published) or, in some cases, an identifier for an army division or group (say, "12th" for the US Army Twelfth Infantry).
36
+ * __First cutter__. The first "Cutter Number" consisting of a letter followed by one or more digits. The first cutter is always supposed to be preceded by a dot, but, you know, isn't always.
37
+ * __Doon2__. Another date or other number
38
+ * __"Extra" Cutters__. The 2nd through Nth Cutter numbers, lumped together because we don't have to worry about them getting interspersed with doons.
39
+ * __Year__. The year of publication
40
+ * __"Rest"__. Everything and anything else.
41
+
42
+ ## Usage
43
+
44
+ In general, you won't be building these things up by hand; you'll try to parse them.
45
+
46
+ Note that in the case below, while in theory this could be a callnumber with a single cutter followed by a doon2 and no year, we presume the '1990' is a year and don't call it a doon.
47
+
48
+ ~~~ruby
49
+
50
+ require 'lc_callnumber'
51
+
52
+ lc = LCCallNumber.parse('A1.2 .B3 1990') #=> LCCallNumber::CallNumber
53
+ lc.letters #=> 'A'
54
+ lc.digits #=> 1.2 (as a float for a float; int if there's no decimal)
55
+ lc.doon1 #=> nil
56
+ lc.firstcutter #=> Cutter<letter=>'B', digits=>'3', dot=>true>
57
+ lc.extra_cutters #=> []
58
+ lc.year #=> 1990
59
+ lc.rest #=> nil
60
+
61
+ lc = LCCallNumber.parse('A .B3') #=> LCCallNumber::UnparseableCallNumber
62
+ lc.valid? #=> false
63
+
64
+ ~~~
65
+
66
+
67
+ ## Installation
68
+
69
+ Add this line to your application's Gemfile:
70
+
71
+ gem 'lc_callnumber'
72
+
73
+ And then execute:
74
+
75
+ $ bundle
76
+
77
+ Or install it yourself as:
78
+
79
+ $ gem install lc_callnumber
80
+
81
+
82
+
83
+
84
+
85
+ ## Contributing
86
+
87
+ 1. Fork it
88
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
89
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
90
+ 4. Push to the branch (`git push origin my-new-feature`)
91
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ end
7
+
8
+ task :default => :test
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'lc_callnumber/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "lc_callnumber"
8
+ spec.version = LCCallNumber::VERSION
9
+ spec.authors = ["Bill Dueber"]
10
+ spec.email = ["bill@dueber.com"]
11
+ spec.description = %q{Work with LC Call (Classification) Numbers}
12
+ spec.summary = %q{Work with LC Call (Classification) Numbers, including an attempt to parse them out from a string to their component parts}
13
+ spec.homepage = "https://github.com/billdueber/lc_callnumber"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency 'parslet'
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.3"
24
+ spec.add_development_dependency "rake"
25
+ spec.add_development_dependency "minitest"
26
+ end
@@ -0,0 +1,214 @@
1
+ require 'lc_callnumber/parser'
2
+
3
+ module LCCallNumber
4
+
5
+ @parser = Parser.new
6
+ @transformer = Transform.new
7
+
8
+ def self.parse(i)
9
+ return UnparseableCallNumber.new(i) if i.nil?
10
+ i.chomp!
11
+ i.strip!
12
+ orig = i
13
+ i.gsub!(/\[(.+)\]/, "$1")
14
+ i.gsub!('\\', ' ')
15
+
16
+ # We also have a bunch that start with a slash and have slashes where you'd
17
+ # expect logical breaks. Don't know why.
18
+
19
+ if i =~ /\A\//
20
+ i.gsub!('/', ' ')
21
+ end
22
+
23
+ # Ditch leading + or *
24
+ i.gsub!(/\A[+*]/, '')
25
+
26
+ # Strip off any leading/trailing spaces and upcase it
27
+ i.strip!
28
+ i.upcase!
29
+
30
+ # Don't bother if it starts with a number, four letters, or the string 'law'
31
+ # Don't bother if there's no numbers at all
32
+ if (/\A\d/.match i) or
33
+ (/\A[[:alpha:]]{4}/.match i) or
34
+ (/\ALAW/i.match i) or
35
+ !(/\d/.match i)
36
+ return UnparseableCallNumber.new(orig)
37
+ end
38
+
39
+ begin
40
+ p = @parser.parse(i)
41
+ # puts p
42
+ lc = @transformer.apply(p)
43
+ lc.original_string = orig
44
+ return lc
45
+ rescue Parslet::ParseFailed => e
46
+ return UnparseableCallNumber.new(orig)
47
+ end
48
+ end
49
+
50
+
51
+
52
+
53
+
54
+
55
+
56
+ # The "lead" -- initial letter(s) and digit(s)
57
+ class Lead
58
+ attr_accessor :letters, :digits
59
+ def initialize(l, d)
60
+ @letters = l
61
+ @digits = d
62
+ end
63
+ def inspect
64
+ "Lead<#{letters}, #{digits.inspect}>"
65
+ end
66
+ end
67
+
68
+ # A generic "Decimal" part, where we keep the
69
+ # integer and fractional parts separate so
70
+ # we can construct a string more easily
71
+
72
+ class Decimal
73
+ attr_accessor :intpart, :fractpart
74
+ def initialize(i, f=nil)
75
+ @intpart = i
76
+ @fractpart = f
77
+ end
78
+
79
+ def to_num
80
+ fractpart ? "#{intpart}.#{fractpart}".to_f : intpart.to_i
81
+ end
82
+
83
+ def to_s
84
+ fractpart ? "#{intpart}.#{fractpart}" : intpart
85
+ end
86
+
87
+
88
+ def inspect
89
+ if fractpart
90
+ "#{intpart}:#{fractpart}"
91
+ else
92
+ "#{intpart}"
93
+ end
94
+ end
95
+ end
96
+
97
+ # A "Cutter" is a single letter followed by one or more digits
98
+ # It is sometimes preceded by a decimal point. We note whether or not
99
+ # we got a decimal point because it may be a hint as to whether or not
100
+ # we're actually looking at a Cutter.
101
+
102
+ class Cutter
103
+ attr_accessor :letter, :digits, :dot
104
+ def initialize(l,d, dot=nil)
105
+ @letter = l
106
+ @digits = d
107
+ @dot = !dot.nil?
108
+ end
109
+
110
+ def inspect
111
+ "Cut<#{letter},#{digits}>"
112
+ end
113
+
114
+ def to_s
115
+ "#{letter}#{digits}"
116
+ end
117
+ end
118
+
119
+
120
+ # Some call numbers have a year, infantry division, etc. preceeding
121
+ # and/or following the first cutter. We take all three as a unit so
122
+ # we can deal with edge cases more easily.
123
+ #
124
+ # "doon" in this case is "Date Or Other Number"
125
+
126
+ class FirstCutterSet
127
+ attr_accessor :doon1, :cutter, :doon2
128
+ def initialize(d1, cutter, d2)
129
+ @doon1 = d1
130
+ @doon2 = d2
131
+ @cutter = cutter
132
+ end
133
+ end
134
+
135
+ # Bring it all together in the callnumber
136
+ # We feed it the parts we have, and then reassign fields based on
137
+ # what we have.
138
+ #
139
+ # To wit:
140
+ # Q123 .C4 1990 --- published in 1990
141
+ # Q123 .C4 1990 .D5 2003 -- published in 2003 with a 2nd doon of 1990
142
+
143
+
144
+ class CallNumber
145
+
146
+ attr_accessor :letters, :digits, :doon1, :firstcutter, :doon2,
147
+ :extra_cutters, :year, :rest
148
+ attr_accessor :original_string
149
+
150
+
151
+ def initialize(lead, fcset=nil, ec=[], year=nil, rest=nil)
152
+ @letters = lead.letters
153
+ @digits = lead.digits.to_num
154
+
155
+ if fcset
156
+ @doon1 = fcset.doon1
157
+ @doon2 = fcset.doon2
158
+ @firstcutter = fcset.cutter
159
+ end
160
+
161
+ @extra_cutters = ec
162
+ @year = year
163
+ @rest = rest
164
+
165
+ @rest.strip! if @rest
166
+
167
+ self.reassign_fields
168
+ end
169
+
170
+ def reassign_fields
171
+ # If we've got a doon2, but no year and no extra cutters,
172
+ # put the doon2 in the year
173
+
174
+ if doon2 and (doon2=~ /\A\d+\Z/) and extra_cutters.empty? and year.nil?
175
+ @year = @doon2
176
+ @doon2 = nil
177
+ end
178
+ end
179
+
180
+ def inspect
181
+ header = %w(letters digits doon1 cut1 doon2 othercut)
182
+ actual = [letters,digits,doon1,firstcutter,doon2,extra_cutters.join(','),year,rest].map{|x| x.to_s}
183
+ fmt = '%-7s %-9s %-6s %-6s %-6s %-20s year=%-6s rest=%-s'
184
+ [('%-7s %-9s %-6s %-6s %-6s %-s' % header), (fmt % actual)].join("\n")
185
+
186
+ end
187
+
188
+
189
+ def valid?
190
+ @letters && @digits
191
+ end
192
+
193
+ end
194
+
195
+ class UnparseableCallNumber < CallNumber
196
+
197
+ def initialize(str)
198
+ self.original_string = str
199
+ self.extra_cutters = []
200
+ end
201
+
202
+ def valid?
203
+ false
204
+ end
205
+
206
+ end
207
+
208
+
209
+
210
+ end
211
+
212
+
213
+
214
+
@@ -0,0 +1,113 @@
1
+ require 'parslet'
2
+ require 'lc_callnumber/lcc'
3
+
4
+ module LCCallNumber
5
+ class Parser < Parslet::Parser
6
+ rule(:space) { match('\s').repeat(1) }
7
+ rule(:space?) { space.maybe }
8
+ rule(:dot) { str('.') }
9
+ rule(:dot?) { dot.maybe }
10
+
11
+ rule(:digit) { match('\d') }
12
+ rule(:digits) { digit.repeat(1) }
13
+ rule(:digits?) { digits.maybe }
14
+
15
+ rule(:year) { digits }
16
+
17
+ rule(:firstletter) { match('(?i:[A-HJ-NP-VZ])') }
18
+ rule(:letter) { match('(?i:[A-Z])') }
19
+ rule(:a2) { firstletter >> letter.maybe }
20
+ rule(:a3) {
21
+ match['K'] >> letter.repeat(2) |
22
+ str('DAW') |
23
+ str('DJK')
24
+ }
25
+
26
+ rule(:alpha) {
27
+ a3 |
28
+ a2
29
+ }
30
+
31
+ # Numeric string may or may not have a dot
32
+ rule(:numstring) {
33
+ digits.as(:intpart) >> (dot >> digits.as(:fractpart)).maybe
34
+ }
35
+
36
+ # So, the "lead" is what I'm calling the necessary part of the callnumber,
37
+ # the letter(s) and following number
38
+ rule(:lead) {
39
+ (alpha.as(:alpha) >> space? >> numstring.as(:numbers)).as(:lead)
40
+ #|
41
+ #(alpha.as(:alpha) >> space).as(:lead)
42
+ }
43
+
44
+
45
+ # "Date or other number" -- need to take into account 1st, 2nd, etc.
46
+ # Should probably restrict this so that, e.g., you can't have "2rd"
47
+ # but for now this is sufficient.
48
+ rule(:suffix) {
49
+ str('ST') |
50
+ str('ND') |
51
+ str('RD') |
52
+ str('TH')
53
+ }
54
+
55
+ rule(:doon) {
56
+ dot? >> digits.as(:digits) >> space? >> suffix.as(:suffix) |
57
+ digits.as(:digits)
58
+ }
59
+ rule(:doon?) { doon.maybe }
60
+
61
+ # Cutter is a letter followed by numbers
62
+ rule(:dotcutter) { (dot.as(:dot) >> letter.as(:letter) >> digits.as(:digits)).as(:cutter) }
63
+ rule(:odotcutter) { ((dot.maybe).as(:dot) >> letter.as(:letter) >> digits.as(:digits)).as(:cutter) }
64
+
65
+ # # Firstcutter has to have a dot
66
+ # rule(:dotcutter) { dot >> cutter }
67
+ # rule(:odotcutter) { (dot.maybe).as(:dot) >> cutter}
68
+
69
+ # The first cutter set can have doons on either side
70
+ rule(:firstcutterset) {
71
+ ((doon >> space).maybe).as(:doon1) >> odotcutter.as(:cutter) >> ((space >> doon).maybe).as(:doon2)
72
+ }
73
+
74
+ # Other cutters may or may not have a dot
75
+ rule(:extracutters) {
76
+ (space? >> odotcutter).repeat(0)
77
+ }
78
+
79
+ rule(:cutters) {
80
+ odotcutter >> extracutters
81
+ }
82
+
83
+ # The rest of it, if there is anything but spaces
84
+ rule(:rest) {
85
+ space? >> any.repeat(1)
86
+ }
87
+
88
+ rule(:lcclass) {
89
+ lead >> space? >> (firstcutterset).as(:fcset) >> extracutters.as(:ec) >> ((space >> year.as(:yeardigits)).maybe).as(:year) >> (rest.maybe).as(:rest) |
90
+ lead >> ((space >> year.as(:yeardigits)).maybe).as(:year) >> (rest.maybe).as(:rest)
91
+ }
92
+ root(:lcclass)
93
+ end
94
+
95
+
96
+
97
+ class Transform < Parslet::Transform
98
+ rule(:intpart=>simple(:i), :fractpart=>simple(:f)) { Decimal.new(i,f) }
99
+ rule(:intpart=>simple(:i)) { Decimal.new(i,nil) }
100
+
101
+ rule(:alpha=>simple(:a), :numbers=>simple(:n)) { @a = Lead.new(a.to_s,n) }
102
+ rule(:digits=>simple(:d), :suffix=>simple(:s)) {"#{d}#{s}"}
103
+ rule(:digits=>simple(:d)) { d.to_s }
104
+ rule(:doon => simple(:d)) { d.to_s.strip }
105
+ rule(:cutter => {:dot=>simple(:dot), :letter=>simple(:l), :digits=>simple(:d)}) { Cutter.new(l.to_s,d.to_s, !(dot.nil?))}
106
+
107
+ rule(:doon1=>simple(:d1), :doon2=>simple(:d2), :cutter=>simple(:c)) { FirstCutterSet.new(d1, c, d2)}
108
+ rule(:yeardigits => simple(:y)) { y.nil? ? nil : y.to_s.strip}
109
+ rule(:lead=>simple(:l), :fcset=>simple(:fc), :ec=>sequence(:ec), :year=>simple(:year), :rest=>simple(:rest)) { CallNumber.new(l,fc,ec,year,rest.to_s)}
110
+ rule(:lead=>simple(:l), :year=>simple(:year), :rest=>simple(:rest)) {CallNumber.new(l,nil,[],year,rest.to_s)}
111
+ end
112
+
113
+ end
@@ -0,0 +1,3 @@
1
+ module LCCallNumber
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,4 @@
1
+ require "lc_callnumber/version"
2
+ require 'lc_callnumber/lcc'
3
+ require 'lc_callnumber/parser'
4
+
@@ -0,0 +1,13 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+ require 'lc_callnumber'
3
+
4
+
5
+ def test_data(relative_path)
6
+ return File.expand_path(File.join("test_data", relative_path), File.dirname(__FILE__))
7
+ end
8
+
9
+ require 'minitest/spec'
10
+ require 'minitest/autorun'
11
+
12
+
13
+
@@ -0,0 +1,26 @@
1
+ #Tab-delimited file, exported from https://docs.google.com/spreadsheet/ccc?key=0AvHn-9AM-38ldE5TYjFvWFFTdnU5emltMEhuQzEyRnc#gid=0
2
+ # String Letter(s) Number Doon1 Cutter1 Doon2 Other,Cutters PubYear Rest
3
+ A1 A 1
4
+ A1 .C2 A 1 C2
5
+ A1 C2 A 1 C2
6
+ A10.4 A 10.4
7
+ A10.4 C345 A 10.4 C345
8
+ A1 1990 A 1 1990
9
+ A 1 C22 A 1 C22
10
+ BF 173 .F889 F92 BF 173 F889 F92
11
+ HD7123 .A5 1970 b HD 7123 A5 1970 b
12
+ PJ5054.B5N44 I83 PJ 5054 B5 N44,I83
13
+ DA 690 .B8 A3 v.25 DA 690 B8 A3 v.25
14
+ PN 1995.9 .N3 N75 1970 PN 1995.9 N3 N75 1970
15
+ D570.3 28th .P96 D 570.3 28TH P96
16
+ UA704 .C9 12 th R89 UA 704 C9 12th R89
17
+ E517.5 21st .A54 E 517.5 21st A54
18
+ D761.1 .1st L36 D 761.1 1st L36
19
+ G 9801 .A4 s250 .G4 ST5-8/11 G 9801 A4 S250,G4 ST5-8/11
20
+ HD 8039 .R52 I4 I42 HD 8039 R52 I4,I42
21
+ ND 623 .L58 A43 1970 ND 623 L58 A43 1970
22
+ DK265.8.L4 L573 DK 265.8 L4 L573
23
+ A1 1888 .B2 1990 A 1 1888 B2 1990
24
+ A1 B2 1888 1990 A 1 B2 1888 1990
25
+ A1 1888 B2 12th A 1 1888 B2 12TH
26
+ A1 B2 1990 v.3 A 1 B2 1990 v.3
@@ -0,0 +1,32 @@
1
+ require 'minitest_helper'
2
+
3
+ describe "Metadata" do
4
+ it "has a version number" do
5
+ assert ::LCCallNumber::VERSION
6
+ end
7
+ end
8
+
9
+ describe "Basics" do
10
+ it "can parse all the items in the basics file" do
11
+ File.open(test_data('basics.txt')).each_line do |line|
12
+ next if line =~ /\A#/
13
+ next unless line =~ /\S/
14
+ line.chomp!
15
+ orig,letters,digits,doon1,c1,doon2,other_cutters,pubyear,rest = line.split(/\t/).map{|s| s.upcase.strip.to_s}
16
+ lc = LCCallNumber.parse(orig)
17
+ assert_equal letters.to_s, lc.letters, "#{orig} -> letters #{lc.inspect}"
18
+ assert_equal digits.to_s, lc.digits.to_s, "#{orig} -> numbers #{lc.inspect}"
19
+ assert_equal doon1.to_s, lc.doon1.to_s, "#{orig} -> doon1 #{lc.inspect}"
20
+ assert_equal c1.to_s, lc.firstcutter.to_s, "#{orig} -> first cutter #{lc.inspect}"
21
+ assert_equal doon2.to_s, lc.doon2.to_s, "#{orig} -> doon2 #{lc.inspect}"
22
+ assert_equal other_cutters.to_s.split(/\s*,\s*/), lc.extra_cutters.map(&:to_s), "#{orig} -> extra_cutters #{lc.inspect}"
23
+ assert_equal pubyear.to_s, lc.year.to_s, "#{orig} -> year #{lc.inspect}"
24
+ assert_equal rest.to_s, lc.rest.to_s, "#{orig} -> rest #{lc.inspect}"
25
+
26
+ end
27
+
28
+ end
29
+ end
30
+
31
+
32
+
metadata ADDED
@@ -0,0 +1,118 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lc_callnumber
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Bill Dueber
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-01-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: parslet
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.3'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: minitest
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: Work with LC Call (Classification) Numbers
70
+ email:
71
+ - bill@dueber.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".gitignore"
77
+ - ".travis.yml"
78
+ - Gemfile
79
+ - LICENSE.txt
80
+ - README.md
81
+ - Rakefile
82
+ - lc_callnumber.gemspec
83
+ - lib/lc_callnumber.rb
84
+ - lib/lc_callnumber/lcc.rb
85
+ - lib/lc_callnumber/parser.rb
86
+ - lib/lc_callnumber/version.rb
87
+ - test/minitest_helper.rb
88
+ - test/test_data/basics.txt
89
+ - test/test_lc_callnumber.rb
90
+ homepage: https://github.com/billdueber/lc_callnumber
91
+ licenses:
92
+ - MIT
93
+ metadata: {}
94
+ post_install_message:
95
+ rdoc_options: []
96
+ require_paths:
97
+ - lib
98
+ required_ruby_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ required_rubygems_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ requirements: []
109
+ rubyforge_project:
110
+ rubygems_version: 2.2.0
111
+ signing_key:
112
+ specification_version: 4
113
+ summary: Work with LC Call (Classification) Numbers, including an attempt to parse
114
+ them out from a string to their component parts
115
+ test_files:
116
+ - test/minitest_helper.rb
117
+ - test/test_data/basics.txt
118
+ - test/test_lc_callnumber.rb