nwn-lib 0.1 → 0.2

Sign up to get free protection for your applications and to get access to all the features.
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