nwn-lib 0.4.12 → 0.5.0

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.
@@ -21,7 +21,7 @@ module NWN::Gff::Scripting
21
21
  catch(:exit) {
22
22
  begin
23
23
  run_on.instance_eval $code
24
- rescue => e
24
+ rescue
25
25
  raise
26
26
  end
27
27
  }
@@ -1,5 +1,3 @@
1
- require 'iconv'
2
-
3
1
  module NWN
4
2
  SETTING_DEFAULT_VALUES = {
5
3
  'NWN_LIB_IN_ENCODING' => 'ISO-8859-1',
@@ -51,20 +49,12 @@ module NWN
51
49
 
52
50
  # Converts text from native format (such as json) to Gff (required by NWN).
53
51
  def self.iconv_native_to_gff text
54
- if IconvState[:in] != NWN.setting(:in_encoding) ||
55
- IconvState[:out] != NWN.setting(:out_encoding)
56
- IconvState[:in_i] = Iconv.new(NWN.setting(:in_encoding), NWN.setting(:out_encoding))
57
- end
58
- IconvState[:in_i].iconv(text)
52
+ text.encode(NWN.setting(:out_encoding))
59
53
  end
60
54
 
61
55
  # Converts text from Gff format to native/external, such as json (usually UTF-8).
62
56
  def self.iconv_gff_to_native text
63
- if IconvState[:in] != NWN.setting(:in_encoding) ||
64
- IconvState[:out] != NWN.setting(:out_encoding)
65
- IconvState[:out_i] = Iconv.new(NWN.setting(:out_encoding), NWN.setting(:in_encoding))
66
- end
67
- IconvState[:out_i].iconv(text)
57
+ text.encode('UTF-8')
68
58
  end
69
59
  end
70
60
 
@@ -1,5 +1,3 @@
1
- require 'shellwords'
2
-
3
1
  class Integer
4
2
  # Returns the level that this amount experience resolves to.
5
3
  # Depends on a set-up TwoDA::Cache, and reads from <tt>exptable</tt>.
@@ -41,8 +39,17 @@ module NWN
41
39
  end
42
40
 
43
41
  def method_missing meth, *args
44
- if idx = @table.columns.index(meth.to_s.downcase) || idx = @table.columns.index(meth.to_s)
45
- if meth.to_s =~ /=$/
42
+ col = meth.to_s
43
+ assignment = if col =~ /(.+?)=$/
44
+ col = $1
45
+ true
46
+ else
47
+ false
48
+ end
49
+
50
+ if idx = @table.columns.index(col.downcase) ||
51
+ idx = @table.columns.index(col)
52
+ if assignment
46
53
  self[idx] = args.shift or raise ArgumentError,
47
54
  "Need a paramenter for assignments .."
48
55
  else
@@ -120,9 +127,9 @@ module NWN
120
127
 
121
128
  header = data.shift
122
129
 
123
- header = Shellwords.shellwords(header.strip)
130
+ header = colsplit(header.strip)
124
131
  data.map! {|line|
125
- Shellwords.shellwords(line.strip)
132
+ colsplit(line.strip)
126
133
  }
127
134
 
128
135
  new_row_data = []
@@ -277,6 +284,7 @@ module NWN
277
284
  row.each_with_index {|cell, column_idx|
278
285
  cell = "****" if cell == ""
279
286
  cell = '"%s"' % cell if cell =~ /\s/
287
+ cell = cell.to_s
280
288
  rv << cell + " " * (max_cell_size_by_column[column_idx] - cell.size)
281
289
  }
282
290
  ret << rv.join("").rstrip
@@ -296,6 +304,35 @@ module NWN
296
304
  @newline
297
305
  end)
298
306
  end
307
+
308
+ private
309
+
310
+ def colsplit(line)
311
+ line = String.new(line) rescue
312
+ raise(ArgumentError, "Argument must be a string")
313
+ line.lstrip!
314
+ words = []
315
+ until line.empty?
316
+ field = ''
317
+ loop do
318
+ if line.sub!(/\A"(([^"\\]|\\.)*)"/, '') then
319
+ snippet = $1.gsub(/\\(.)/, '\1')
320
+ elsif line =~ /\A"/ then
321
+ raise ArgumentError, "Unmatched double quote: #{line}"
322
+ elsif line.sub!(/\A\\(.)?/, '') then
323
+ snippet = $1 || '\\'
324
+ elsif line.sub!(/\A([^\s\\"]+)/, '') then
325
+ snippet = $1
326
+ else
327
+ line.lstrip!
328
+ break
329
+ end
330
+ field.concat(snippet)
331
+ end
332
+ words.push(field)
333
+ end
334
+ words
335
+ end
299
336
  end
300
337
 
301
338
  # An alias for TwoDA::Cache.get
@@ -312,7 +349,8 @@ module NWN
312
349
  # Call this on application startup.
313
350
  # path spec is a colon-separated list of paths, just like $PATH.
314
351
  def self.setup root_directories
315
- @_roots = root_directories.split(':').compact.reject {|x| "" == x.strip }
352
+ @_roots = root_directories.split(File::PATH_SEPARATOR).
353
+ compact.reject {|x| "" == x.strip }
316
354
  end
317
355
 
318
356
  # Get the 2da file with the given name. +name+ is without extension.
@@ -327,7 +365,7 @@ module NWN
327
365
 
328
366
  def self.read_2da name # :nodoc:
329
367
  @_roots.each {|root|
330
- file = root + '/' + name + '.2da'
368
+ file = root + File::SEPARATOR + name + '.2da'
331
369
  next unless FileTest.exists?(file)
332
370
  return Table.parse(IO.read(file))
333
371
  }
@@ -0,0 +1,3 @@
1
+ module NWN
2
+ VERSION = "0.5.0"
3
+ end
@@ -17,7 +17,7 @@ private
17
17
  struct.data_version != NWN::Gff::Struct::DEFAULT_DATA_VERSION
18
18
  end
19
19
 
20
- struct.sort.each {|(k,v)|
20
+ struct.sort.each {|(*,v)|
21
21
  s << field_to_xml(v)
22
22
  }
23
23
  s
@@ -33,12 +33,12 @@ private
33
33
  e['name'] = field.field_label
34
34
  e['type'] = case @format
35
35
  when :modpacker
36
- NWN::Gff::Types.index(field.field_type).to_s
36
+ NWN::Gff::Types.key(field.field_type).to_s
37
37
  when :nxml
38
38
  field.field_type.to_s
39
39
  end
40
40
 
41
- vv = case field.field_type
41
+ case field.field_type
42
42
  when :cexolocstr
43
43
  case @format
44
44
  when :modpacker
@@ -1,5 +1,6 @@
1
1
  # This file contains all YAML-specific loading and dumping code.
2
2
  require 'yaml'
3
+ Psych::ENGINE.yamler = 'syck'
3
4
 
4
5
  module NWN::Gff::Handler::YAML
5
6
  # These field types can never be inlined in YAML.
@@ -0,0 +1,18 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/nwn/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Bernhard Stoeckner"]
6
+ gem.email = ["n@e-ix.net"]
7
+ gem.description = %q{Neverwinter Nights 1/2 file formats ruby library}
8
+ gem.summary = gem.description
9
+ gem.homepage = "https://github.com/niv/nwn-lib"
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "nwn-lib"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = NWN::VERSION
17
+ gem.required_ruby_version = '>= 1.9.1'
18
+ end
@@ -1,9 +1,14 @@
1
1
  #!/usr/bin/env nwn-dsl
2
2
  # vim: ft=ruby
3
3
 
4
- ARGV.each {|f|
5
- log "Working on #{f} .."
6
- t = TwoDA::Table.parse(IO.read(f))
7
- File.open(f, "wb") {|n| n.puts t.to_2da }
8
- log "done."
9
- }
4
+ if ARGV.size == 0
5
+ t = TwoDA::Table.parse($stdin.read)
6
+ $stdout.puts t.to_2da
7
+ else
8
+ ARGV.each {|f|
9
+ log "Working on #{f} .."
10
+ t = TwoDA::Table.parse(IO.read(f))
11
+ File.open(f, "wb") {|n| n.puts t.to_2da }
12
+ log "done."
13
+ }
14
+ end
@@ -1,16 +1,16 @@
1
1
  require File.join(File.dirname(__FILE__), 'spec_helper')
2
2
 
3
3
  describe "nwn-dsl" do
4
- it_should_behave_like "bin helper"
4
+ include BinHelper
5
5
 
6
6
  it "runs empty scripts" do
7
- t = Tempfile.new(@tmp)
7
+ t = Tempfile.new(["nwn-lib", "dsl"])
8
8
  t.close
9
9
  run(t.path)
10
10
  end
11
11
 
12
12
  it "runs want/need scripts" do
13
- t = Tempfile.new(@tmp)
13
+ t = Tempfile.new(["nwn-lib", "dsl"])
14
14
  t.write("need ARGV.shift, :bic")
15
15
  t.close
16
16
  run_bin(t.path, WELLFORMED_GFF_PATH) do |i,o,e|
@@ -22,7 +22,7 @@ describe "nwn-dsl" do
22
22
  end
23
23
 
24
24
  it "logs to stderr" do
25
- t = Tempfile.new(@tmp)
25
+ t = Tempfile.new(["nwn-lib", "dsl"])
26
26
  t.write("log 'hey'")
27
27
  t.close
28
28
  run_bin(t.path, WELLFORMED_GFF_PATH) do |i,o,e|
@@ -1,38 +1,33 @@
1
1
  require File.join(File.dirname(__FILE__), 'spec_helper')
2
2
 
3
3
  describe "nwn-erf" do
4
- it_should_behave_like "bin helper"
5
-
4
+ include BinHelper
6
5
  # Create temporary testcase files.
7
6
  before do
8
- @target = File.join(@tmp, "nwn-lib-spec-target.erf")
7
+ @tmpdir = Dir.mktmpdir
8
+
9
+ @target = File.join(@tmpdir, "nwn-lib-spec-target.erf")
9
10
 
10
11
  @tmp0s = []
11
12
  @tmp1s = []
12
13
  for x in %w{aaa.tga bbbb.erf ccc.bmp 44.txt} do
13
- File.open(File.join(@tmp, x), "w") do |fn|
14
+ File.open(File.join(@tmpdir, x), "w") do |fn|
14
15
  fn.write(x)
15
16
  end
16
- @tmp0s << File.join(@tmp, x)
17
+ @tmp0s << File.join(@tmpdir, x)
17
18
  end
18
19
  for x in %w{bbbbbbbbbbbbbbbbbbbb.bmp} do
19
- File.open(File.join(@tmp, x), "w") do |fn|
20
+ File.open(File.join(@tmpdir, x), "w") do |fn|
20
21
  fn.write(x)
21
22
  end
22
- @tmp1s << File.join(@tmp, x)
23
+ @tmp1s << File.join(@tmpdir, x)
23
24
  end
24
25
  @tmp0s.sort!
25
26
  @tmp1s.sort!
26
27
  end
27
28
 
28
29
  after do
29
- @tmp0s.each {|f|
30
- File.unlink(f.path) rescue nil
31
- }
32
- @tmp1s.each {|f|
33
- File.unlink(f.path) rescue nil
34
- }
35
- File.unlink(@target) rescue nil
30
+ FileUtils.rm_r @tmpdir
36
31
  end
37
32
 
38
33
  it "packs -0" do
@@ -66,35 +61,35 @@ describe "nwn-erf" do
66
61
  it "extracts -0" do
67
62
  run("-c", "-f", @target, *@tmp0s)
68
63
  @tmp0s.each {|f| File.unlink(f) }
69
- run("-v", "-x", "-f", @target)
64
+ run("-x", "-f", @target)
70
65
  @tmp0s.each {|f| FileTest.exists?(f).should == true }
71
- @tmp0s.each {|f| IO.read(f).should == File.basename(f) }
66
+ @tmp0s.each {|f| IO.read(f, :encoding => "BINARY").should == File.basename(f) }
72
67
  end
73
68
 
74
69
  it "extracts -1" do
75
70
  workon = @tmp0s + @tmp1s
76
71
  run("-1", "-c", "-f", @target, *workon)
77
72
  workon.each {|f| File.unlink(f) }
78
- run("-v", "-x", "-f", @target)
73
+ run("-x", "-f", @target)
79
74
  workon.each {|f| FileTest.exists?(f).should == true }
80
- workon.each {|f| IO.read(f).should == File.basename(f) }
75
+ workon.each {|f| IO.read(f, :encoding => "BINARY").should == File.basename(f) }
81
76
  end
82
77
 
83
78
  it "creates haks" do
84
79
  run("-H", "-c", "-f", @target, *@tmp0s)
85
- IO.read(@target).should =~ /^HAK/
80
+ IO.read(@target, :encoding => "BINARY").should =~ /^HAK/
86
81
  end
87
82
 
88
83
  it "creates mods" do
89
84
  run("-M", "-c", "-f", @target, *@tmp0s)
90
- IO.read(@target).should =~ /^MOD/
85
+ IO.read(@target, :encoding => "BINARY").should =~ /^MOD/
91
86
  end
92
87
 
93
88
  it "creates erfs (by default)" do
94
89
  run("-E", "-c", "-f", @target, *@tmp0s)
95
- IO.read(@target).should =~ /^ERF/
90
+ IO.read(@target, :encoding => "BINARY").should =~ /^ERF/
96
91
  run("-c", "-f", @target, *@tmp0s)
97
- IO.read(@target).should =~ /^ERF/
92
+ IO.read(@target, :encoding => "BINARY").should =~ /^ERF/
98
93
  end
99
94
 
100
95
  it "adds files from existing archives" do
@@ -1,7 +1,15 @@
1
1
  require File.join(File.dirname(__FILE__), 'spec_helper')
2
2
 
3
3
  describe "nwn-gff" do
4
- it_should_behave_like "bin helper"
4
+ include BinHelper
5
+
6
+ before do
7
+ @tmpdir = Dir.mktmpdir
8
+ end
9
+
10
+ after do
11
+ FileUtils.rm_r(@tmpdir)
12
+ end
5
13
 
6
14
  NWN::Gff::InputFormats.each do |in_format, handler|
7
15
  inf = in_format.to_s
@@ -11,7 +19,7 @@ describe "nwn-gff" do
11
19
 
12
20
  it "converts #{inf} to #{otf}" do
13
21
  # prepare the temp file
14
- t = Tempfile.new(@tmp)
22
+ t = Tempfile.new('nwn-gff', @tmpdir)
15
23
  t.close
16
24
 
17
25
  run("-lg", "-i", WELLFORMED_GFF_PATH, "-k", inf, "-o", t.path)
@@ -22,7 +30,7 @@ describe "nwn-gff" do
22
30
  end
23
31
 
24
32
  it "supports none GNU-style backup" do
25
- t = Tempfile.new(@tmp)
33
+ t = Tempfile.new('nwn-gff', @tmpdir)
26
34
  t.close
27
35
  run("-b", "none", "-lg", "-i", WELLFORMED_GFF_PATH, "-kg", "-o", t.path)
28
36
  FileTest.exists?(t.path).should == true
@@ -30,7 +38,7 @@ describe "nwn-gff" do
30
38
  end
31
39
 
32
40
  it "supports numbered GNU-style backup" do
33
- t = Tempfile.new(@tmp)
41
+ t = Tempfile.new('nwn-gff', @tmpdir)
34
42
  t.close
35
43
 
36
44
  run("-b", "numbered", "-lg", "-i", WELLFORMED_GFF_PATH, "-kg", "-o", t.path)
@@ -49,7 +57,7 @@ describe "nwn-gff" do
49
57
  end
50
58
 
51
59
  it "supports existing with no numbered backups GNU-style backup" do
52
- t = Tempfile.new(@tmp)
60
+ t = Tempfile.new('nwn-gff', @tmpdir)
53
61
  t.close
54
62
 
55
63
  FileTest.exists?(t.path + "~").should == false
@@ -74,7 +82,7 @@ describe "nwn-gff" do
74
82
 
75
83
 
76
84
  it "supports simple GNU-style backup" do
77
- t = Tempfile.new(@tmp)
85
+ t = Tempfile.new('nwn-gff', @tmpdir)
78
86
  t.close
79
87
 
80
88
  FileTest.exists?(t.path + "~").should == false
@@ -1,6 +1,6 @@
1
1
  require File.join(File.dirname(__FILE__), 'spec_helper')
2
2
 
3
- describe "Erf::Erf", :shared => true do
3
+ shared_examples_for "Erf::Erf" do
4
4
  def wellformed_verify binary, expect_locstr = true
5
5
  t = Erf::Erf.new(StringIO.new binary)
6
6
 
@@ -40,6 +40,7 @@ describe "Erf::Erf", :shared => true do
40
40
  it "reproduces correct ERF binary data" do
41
41
  t = Erf::Erf.new(StringIO.new @erf)
42
42
  io = StringIO.new
43
+ io.set_encoding 'BINARY'
43
44
  t.write_to(io)
44
45
  io.seek(0)
45
46
  n = io.read
@@ -20,4 +20,13 @@ describe "Gff::Field" do
20
20
  NWN.setting(:resref16, nil)
21
21
  end
22
22
  end
23
+
24
+ describe ":void" do
25
+ it "stores data in binary" do
26
+ gff = Gff::Struct.new do |root|
27
+ root.add_void 'Test', "\xde\xad\xbe\xef"
28
+ end.to_gff
29
+ gff.index("\xde\xad\xbe\xef").should_not be_nil
30
+ end
31
+ end
23
32
  end
@@ -20,8 +20,7 @@ describe "Gff.read/write API" do
20
20
  :yaml => %w{yml yaml},
21
21
  :json => %w{json},
22
22
  :nxml => %w{nxml},
23
- :kivinen => %w{k kivinen},
24
- :marshal => %w{marshal}
23
+ :kivinen => %w{k kivinen}
25
24
  }.each {|expect, arr|
26
25
  arr.each {|ext|
27
26
  it "guesses the file format #{expect} for extension #{ext} correctly" do
@@ -1,6 +1,6 @@
1
1
  require File.join(File.dirname(__FILE__), 'spec_helper')
2
2
 
3
- describe "Key::Key", :shared => true do
3
+ shared_examples_for "Key::Key" do
4
4
  def wellformed_verify binary
5
5
  t = Key::Key.new(StringIO.new(binary), Dir.tmpdir)
6
6
 
@@ -13,7 +13,7 @@ describe "Kivinen Support" do
13
13
  label.should == w[0]
14
14
  case entry
15
15
  when Float
16
- entry.should be_close(w[1], 0.001)
16
+ entry.should be_within(0.001).of(w[1])
17
17
  else
18
18
  entry.should == w[1]
19
19
  end