nwn-lib 0.1 → 0.2

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/CHANGELOG ADDED
@@ -0,0 +1,8 @@
1
+ === 0.2
2
+
3
+ * Add TwoDA reading/writing support.
4
+ * nwn-gff-print supports kivinen-style ____type printing.
5
+ === 0.1
6
+
7
+ * Add basic functionality for reading and writing arbitary gff files.
8
+ * Binaries: nwn-gff-print for simple display of gff files.
data/Rakefile CHANGED
@@ -9,7 +9,7 @@ include FileUtils
9
9
  # Configuration
10
10
  ##############################################################################
11
11
  NAME = "nwn-lib"
12
- VERS = "0.1"
12
+ VERS = "0.2"
13
13
  CLEAN.include ["**/.*.sw?", "pkg", ".config", "rdoc", "coverage"]
14
14
  RDOC_OPTS = ["--quiet", "--line-numbers", "--inline-source", '--title', \
15
15
  'nwn-lib: a ruby library for accessing NWN resource files', \
@@ -18,7 +18,7 @@ RDOC_OPTS = ["--quiet", "--line-numbers", "--inline-source", '--title', \
18
18
  Rake::RDocTask.new do |rdoc|
19
19
  rdoc.rdoc_dir = "rdoc"
20
20
  rdoc.options += RDOC_OPTS
21
- rdoc.rdoc_files.add ["README", "COPYING", "CHANGELOG", "doc/*.rdoc", "lib/**/*.rb"]
21
+ rdoc.rdoc_files.add ["README", "CHANGELOG", "COPYING", "doc/*.rdoc", "lib/**/*.rb"]
22
22
  end
23
23
 
24
24
  desc "Packages up nwn-lib"
@@ -30,7 +30,7 @@ spec = Gem::Specification.new do |s|
30
30
  s.version = VERS
31
31
  s.platform = Gem::Platform::RUBY
32
32
  s.has_rdoc = true
33
- s.extra_rdoc_files = ["README", "COPYING"] + Dir["doc/*.rdoc"]
33
+ s.extra_rdoc_files = ["README", "CHANGELOG", "COPYING"] + Dir["doc/*.rdoc"]
34
34
  s.rdoc_options += RDOC_OPTS + ["--exclude", "^(examples|extras)\/"]
35
35
  s.summary = "a ruby library for accessing Neverwinter Nights resource files"
36
36
  s.description = s.summary
@@ -39,7 +39,7 @@ spec = Gem::Specification.new do |s|
39
39
  s.homepage = "http://nwn-lib.elv.es"
40
40
  s.executables = ["nwn-gff-print"]
41
41
  s.required_ruby_version = ">= 1.8.4"
42
- s.files = %w(COPYING README Rakefile) + Dir.glob("{bin,doc,spec,lib}/**/*")
42
+ s.files = %w(COPYING CHANGELOG README Rakefile) + Dir.glob("{bin,doc,spec,lib}/**/*")
43
43
  s.require_path = "lib"
44
44
  s.bindir = "bin"
45
45
  end
data/bin/nwn-gff-print CHANGED
@@ -5,6 +5,7 @@ require 'nwn/gff'
5
5
  require 'yaml'
6
6
 
7
7
  format = nil
8
+ types_too = false
8
9
 
9
10
  OptionParser.new do |o|
10
11
  o.banner = "Usage: nwn-gff-print [options] file/- [path]"
@@ -14,6 +15,9 @@ OptionParser.new do |o|
14
15
  o.on "-k", "--kivinen", "Dump as kivinens dump format (like the perl tools)" do
15
16
  format = :kivinen
16
17
  end
18
+ o.on "-t", "--types", "Dump types as well (only applies to -k, for now)" do
19
+ types_too = true
20
+ end
17
21
  end.parse!
18
22
 
19
23
  file = ARGV.shift or begin
@@ -40,46 +44,11 @@ if path
40
44
  end
41
45
  end
42
46
 
43
- def k_format_struct s, prefix = "/", &block
44
- if s.is_a?(NWN::Gff::Gff)
45
- s = NWN::Gff::Element.new("", :struct, s.root_struct)
46
- end
47
- if s.is_a?(Array)
48
- v = NWN::Gff::Element.new("(unlabeled list)", :list, s)
49
- end
50
- if s.is_a?(NWN::Gff::Struct)
51
- s = NWN::Gff::Element.new("(unlabeled struct)", :struct, s)
52
- end
53
- case s.type
54
- when :struct
55
- s.value.each {|k,v|
56
- k_format_struct v, prefix + s.label + (s.label == "" ? "" : "/") do |l,v|
57
- yield(l, v)
58
- end
59
- }
60
- when :cexolocstr
61
- s.value.each {|vv|
62
- yield(prefix + s.label + "/" + vv.language.to_s, vv.text)
63
- }
64
- yield(prefix + s.label + ". ___string_ref", s._str_ref)
65
- when :list
66
- s.value.each_with_index {|vv, idx|
67
- vv.each {|kkk, vvv|
68
- k_format_struct vvv, prefix + s.label + "[#{idx}]/" do |l,v|
69
- yield(l,v)
70
- end
71
- }
72
- }
73
- else
74
- yield(prefix + s.label, s.value)
75
- end
76
- end
77
-
78
47
  case format
79
48
  when :yaml
80
49
  y g
81
50
  when :kivinen
82
- k_format_struct g do |label, value|
51
+ NWN::Gff.kivinen_format g, "/", types_too do |label, value|
83
52
  puts "%s:\t%s" % [label, value]
84
53
  end
85
54
  else
data/lib/nwn/gff.rb CHANGED
@@ -55,7 +55,61 @@ module NWN
55
55
  :float => 'f',
56
56
  :double => 'd',
57
57
  }.freeze
58
+
59
+ # Parses +s+ as an arbitary GFF object and yields for each field found,
60
+ # with the proper prefix.
61
+ def self.kivinen_format s, prefix = "/", types_too = false, &block
62
+ if s.is_a?(NWN::Gff::Gff)
63
+ if types_too
64
+ yield("/ ____file_type", s.type)
65
+ yield("/ ____file_version", s.version)
66
+ end
67
+ s = NWN::Gff::Element.new("", :struct, s.root_struct)
68
+ end
69
+
70
+ if s.is_a?(Array)
71
+ v = NWN::Gff::Element.new("(unlabeled list)", :list, s)
72
+ end
73
+
74
+ if s.is_a?(NWN::Gff::Struct)
75
+ yield(prefix + " ____struct_type", s.struct_id) if types_too
76
+ s = NWN::Gff::Element.new("(unlabeled struct)", :struct, s)
77
+ end
78
+
79
+ case s.type
80
+ when :struct
81
+ yield(prefix + " ____struct_type", s.value.struct_id) if types_too
82
+ s.value.each {|k,v|
83
+ kivinen_format v, prefix + s.label + (s.label == "" ? "" : "/"), types_too do |l,v|
84
+ yield(l, v)
85
+ end
86
+ }
87
+
88
+ when :cexolocstr
89
+
90
+ s.value.each {|vv|
91
+ yield(prefix + s.label + "/" + vv.language.to_s, vv.text)
92
+ }
93
+ yield(prefix + s.label + ". ___string_ref", s._str_ref)
94
+
95
+ when :list
96
+ s.value.each_with_index {|vv, idx|
97
+ vv.each {|kkk, vvv|
98
+ kivinen_format vvv, prefix + s.label + "[#{idx}]/", types_too do |l,v|
99
+ yield(l,v)
100
+ end
101
+ }
102
+ }
103
+ else
104
+ yield(prefix + s.label, s.value)
105
+ end
106
+
107
+ if types_too && s.label != ""
108
+ yield(prefix + s.label + ". ____type", Types.index(s.type).to_s)
109
+ end
110
+ end
58
111
  end
112
+
59
113
  end
60
114
 
61
115
  # A GFF object encapsulates a whole GFF identity, with a type,
data/lib/nwn/twoda.rb CHANGED
@@ -1,9 +1,104 @@
1
+ require 'shellwords'
2
+
1
3
  module NWN
2
4
  module TwoDA
3
5
  class Table
4
- end
5
6
 
6
- class Reader
7
+ # An array of all column names present in this 2da table.
8
+ attr_reader :columns
9
+
10
+ # An array of row arrays, without headers.
11
+ attr_reader :rows
12
+
13
+
14
+ # Creates a new Table object from a given file.
15
+ #
16
+ # [+file+] A readable, valid .2da file.
17
+ def self.new_from_file file
18
+ self.new IO.read(file)
19
+ end
20
+
21
+
22
+ # Parses a string that represents a valid 2da definition.
23
+ def initialize bytes
24
+ magic, empty, header, *data = *bytes.split(/\r?\n/).map {|v| v.strip }
25
+
26
+ raise ArgumentError, "Not valid 2da: No valid header found" if
27
+ magic != "2DA V2.0"
28
+
29
+ raise ArgumentError,
30
+ "Not avalid 2da: Second line should be empty." unless
31
+ empty == ""
32
+
33
+ header = Shellwords.shellwords(header.strip)
34
+ data.map! {|line|
35
+ Shellwords.shellwords(line.strip)
36
+ }
37
+
38
+ data.each_with_index {|row, idx|
39
+ raise ArgumentError, "2da non-continoous: row #{idx} has a non-matching ID #{row[0]}." if idx != row[0].to_i
40
+ # [1..-1]: Strip off the ID
41
+ data[idx] = row = row[1..-1]
42
+
43
+ raise ArgumentError,
44
+ "Row #{idx} does not have the appropriate amount of cells (has: #{row.size}, want: #{header.size})." if
45
+ row.size != header.size
46
+ }
47
+
48
+ @columns = header
49
+ @rows = data
50
+ end
51
+
52
+
53
+ # Retrieve data by row.
54
+ #
55
+ # [+row+] The row to retrieve (starts at 0)
56
+ # [+column+] The column to retrieve (name or id), or nil for all columns.
57
+ def by_row row, column = nil
58
+ column = column_name_to_id column
59
+ column.nil? ? @rows[row.to_i] : @rows[row.to_i][column]
60
+ end
61
+
62
+
63
+ # Retrieve data by column.
64
+ #
65
+ # [+column+] The column to retrieve (name or id).
66
+ # [+row+] The row to retrieve (starts at 0), or nil for all rows.
67
+ def by_col column, row = nil
68
+ column = column_name_to_id column
69
+ raise ArgumentError, "column must not be nil." if column.nil?
70
+ row.nil? ? @rows.map {|v| v[column] } : @rows[row.to_i][column]
71
+ end
72
+
73
+
74
+ # Translate a column name to its array offset; will validate
75
+ # and raise an ArgumentError if the given argument is invalid
76
+ # or the column cannot be resolved.
77
+ def column_name_to_id column
78
+ case column
79
+ when String
80
+ @columns.index(column) or raise ArgumentError, "Not a valid column name: #{column}"
81
+ when Fixnum
82
+ column
83
+ when NilClass
84
+ nil
85
+ else
86
+ raise ArgumentError, "Invalid column type: #{column} as #{column.class}"
87
+ end
88
+ end
89
+
90
+ # Returns this table as a valid 2da to be written to a file.
91
+ def to_2da
92
+ ret = []
93
+ ret << "2DA V2.0"
94
+ ret << ""
95
+ ret << @columns.join("\t")
96
+ @rows.each_with_index {|row, idx|
97
+ ret << [idx].concat(row).join("\t")
98
+ }
99
+ ret.join("\r\n")
100
+ end
101
+
7
102
  end
8
103
  end
9
104
  end
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.0
3
3
  specification_version: 1
4
4
  name: nwn-lib
5
5
  version: !ruby/object:Gem::Version
6
- version: "0.1"
7
- date: 2008-06-28 00:00:00 +02:00
6
+ version: "0.2"
7
+ date: 2008-06-29 00:00:00 +02:00
8
8
  summary: a ruby library for accessing Neverwinter Nights resource files
9
9
  require_paths:
10
10
  - lib
@@ -30,10 +30,10 @@ authors:
30
30
  - Bernhard Stoeckner
31
31
  files:
32
32
  - COPYING
33
+ - CHANGELOG
33
34
  - README
34
35
  - Rakefile
35
36
  - bin/nwn-gff-print
36
- - bin/nwn-gff-set
37
37
  - spec/spec.opts
38
38
  - spec/rcov.opts
39
39
  - lib/nwn
@@ -53,6 +53,7 @@ rdoc_options:
53
53
  - ^(examples|extras)/
54
54
  extra_rdoc_files:
55
55
  - README
56
+ - CHANGELOG
56
57
  - COPYING
57
58
  executables:
58
59
  - nwn-gff-print
data/bin/nwn-gff-set DELETED
@@ -1,87 +0,0 @@
1
- #!/usr/bin/ruby
2
- require 'rubygems'
3
- require 'optparse'
4
- require 'nwn/gff'
5
- require 'yaml'
6
-
7
- format = nil
8
-
9
- OptionParser.new do |o|
10
- o.banner = "Usage: nwn-gff-print [options] file/- [path]"
11
- o.on "-y", "--yaml", "Dump as yaml" do
12
- format = :yaml
13
- end
14
- o.on "-k", "--kivinen", "Dump as kivinens dump format (like the perl tools)" do
15
- format = :kivinen
16
- end
17
- end.parse!
18
-
19
- file = ARGV.shift or begin
20
- $stderr.puts "Required argument: filename to process, or - for stdin (try -h)."
21
- exit 1
22
- end
23
-
24
- path = ARGV.shift
25
-
26
- if file == "-"
27
- bytes = $stdin.read
28
- else
29
- bytes = IO.read(file)
30
- end
31
-
32
- g = NWN::Gff::Reader.read(bytes)
33
-
34
- if path
35
- begin
36
- g = g[path]
37
- rescue Exception => e
38
- $stderr.puts "Error: " + e.to_s
39
- exit 1
40
- end
41
- end
42
-
43
- def k_format_struct s, prefix = "/", &block
44
- if s.is_a?(NWN::Gff::Gff)
45
- s = NWN::Gff::Element.new("", :struct, s.root_struct)
46
- end
47
- if s.is_a?(Array)
48
- v = NWN::Gff::Element.new("(unlabeled list)", :list, s)
49
- end
50
- if s.is_a?(NWN::Gff::Struct)
51
- s = NWN::Gff::Element.new("(unlabeled struct)", :struct, s)
52
- end
53
- case s.type
54
- when :struct
55
- s.value.each {|k,v|
56
- k_format_struct v, prefix + s.label + (s.label == "" ? "" : "/") do |l,v|
57
- yield(l, v)
58
- end
59
- }
60
- when :cexolocstr
61
- s.value.each {|vv|
62
- yield(prefix + s.label + "/" + vv.language.to_s, vv.text)
63
- }
64
- yield(prefix + s.label + ". ___string_ref", s._str_ref)
65
- when :list
66
- s.value.each_with_index {|vv, idx|
67
- vv.each {|kkk, vvv|
68
- k_format_struct vvv, prefix + s.label + "[#{idx}]/" do |l,v|
69
- yield(l,v)
70
- end
71
- }
72
- }
73
- else
74
- yield(prefix + s.label, s.value)
75
- end
76
- end
77
-
78
- case format
79
- when :yaml
80
- y g
81
- when :kivinen
82
- k_format_struct g do |label, value|
83
- puts "%s:\t%s" % [label, value]
84
- end
85
- else
86
- puts "Unknown format; try -h"
87
- end