dgd-tools 0.1.7 → 0.1.12
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +5 -1
- data/README.md +16 -4
- data/dgd-tools.gemspec +1 -0
- data/exe/dgd-manifest +72 -60
- data/exe/skotos-xml-diff +1 -0
- data/lib/dgd-tools/dgd-doc.rb +56 -0
- data/lib/dgd-tools/dgd_grammar.tt +373 -0
- data/lib/dgd-tools/dgd_grammar_support.rb +36 -0
- data/lib/dgd-tools/manifest.rb +84 -26
- data/lib/dgd-tools/skotos_xml_obj.rb +18 -5
- data/lib/dgd-tools/version.rb +1 -1
- metadata +19 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ed7c35c57fad646f3083312c2c4a0d3b2ed1dcc9fa0d7f95f4b2c89d49ddadba
|
4
|
+
data.tar.gz: 8124dbf072f51dfd84ba1bde82fe60e3521d20b7eb53ef8dc413b8d31f78a57b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0db04c0632d1ee81659be61f9d5341602f1112a148577b32f89fe9d327ec607910d979e2843cd3b6466269fdb7bb11ddd1c5eda29a111f019e6e753d5619c7bb
|
7
|
+
data.tar.gz: 0b888a3f260a47cf77d3024555cdb38322b646ce016511a5edc7331ae6b0e43852c6f698e2fdf0a022071a763e31ebdfbb22e30d9cdc7a673036b8d549d6ea28
|
data/Gemfile.lock
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
dgd-tools (0.1.
|
4
|
+
dgd-tools (0.1.11)
|
5
5
|
nokogiri (~> 1.10.5)
|
6
6
|
optimist (~> 3.0.1)
|
7
|
+
treetop
|
7
8
|
|
8
9
|
GEM
|
9
10
|
remote: https://rubygems.org/
|
@@ -13,7 +14,10 @@ GEM
|
|
13
14
|
nokogiri (1.10.10)
|
14
15
|
mini_portile2 (~> 2.4.0)
|
15
16
|
optimist (3.0.1)
|
17
|
+
polyglot (0.3.5)
|
16
18
|
rake (12.3.3)
|
19
|
+
treetop (1.6.11)
|
20
|
+
polyglot (~> 0.3)
|
17
21
|
|
18
22
|
PLATFORMS
|
19
23
|
ruby
|
data/README.md
CHANGED
@@ -20,7 +20,7 @@ You can find example "goods" (library) files under the "goods" subdirectory of t
|
|
20
20
|
|
21
21
|
## WOE Objects and skotos-xml-diff
|
22
22
|
|
23
|
-
SkotOS-based games use an XML format for in-game objects
|
23
|
+
SkotOS-based games use an XML format for in-game objects ("/base/obj/thing"), which is [documented in SkotOS-Doc](https://ChatTheatre.github.io/SkotOS-Doc). The skotos-xml-diff utility will diff between Things or directories of Things.
|
24
24
|
|
25
25
|
See SkotOS-Doc for more detail about how this can be used with a SkotOS game.
|
26
26
|
|
@@ -30,15 +30,21 @@ Run "skotos-xml-diff --help" for a list of options. You can tell it to ignore wh
|
|
30
30
|
|
31
31
|
You would normally install DGDTools directly: `gem install dgd-tools`.
|
32
32
|
|
33
|
-
|
33
|
+
If you have a Ruby Gemfile or gems.rb that uses it, you can "bundle install" as normal.
|
34
34
|
|
35
35
|
## Usage
|
36
36
|
|
37
|
-
If you have a DGD application that uses DGD Manifest, run `dgd-manifest install` to download its dependencies and create a fully-assembled DGD directory for it. You can also `dgd-manifest test` to make sure its dependencies are downloaded and satisfied without building an application directory.
|
37
|
+
If you have a DGD application that uses DGD Manifest, run `dgd-manifest install` to download its dependencies and create a clean, fully-assembled DGD directory for it. You can also `dgd-manifest test` to make sure its dependencies are downloaded and satisfied without building an application directory. After the initial install, "dgd-manifest update" will avoid deleting any files you may have added.
|
38
|
+
|
39
|
+
NOTE: "dgd-manifest install" will delete any extra files you may have created in the DGD root. "dgd-manifest update" will not. Neither of these is always the right answer.
|
38
40
|
|
39
41
|
That fully-assembled DGD directory is named ".root". To run your dgd server, type "dgd-manifest server".
|
40
42
|
|
41
|
-
|
43
|
+
## Creating a New DGD Manifest App
|
44
|
+
|
45
|
+
You can type "dgd-manifest new my_app_name" to create a new application using the appropriate DGD manifest structure. This is an easy way to set up an appropriate .gitignore file and similar.
|
46
|
+
|
47
|
+
You can, of course, do the same without the command if you like.
|
42
48
|
|
43
49
|
## Using DGD Manifest with your DGD Application
|
44
50
|
|
@@ -94,6 +100,12 @@ Here's what those look like:
|
|
94
100
|
}
|
95
101
|
```
|
96
102
|
|
103
|
+
Fields in the Goods file are the same as fields in unbundled_goods.
|
104
|
+
|
105
|
+
## Implementation Limits
|
106
|
+
|
107
|
+
Right now it's not possible to use the same repo multiple times with different branches. So for instance, you can't use one branch of ChatTheatre/SkotOS for your main library while using a different branch of it for some other library. For this reason, it's recommended that you extract smaller libraries into their own repositories rather than keeping multiple libraries in the same repo.
|
108
|
+
|
97
109
|
## Development
|
98
110
|
|
99
111
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests.
|
data/dgd-tools.gemspec
CHANGED
data/exe/dgd-manifest
CHANGED
@@ -1,70 +1,82 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
+
require "optimist"
|
3
4
|
require "dgd-tools/manifest"
|
4
5
|
|
5
|
-
|
6
|
-
ARGV.push "install"
|
7
|
-
end
|
6
|
+
SUB_COMMANDS = %w(new test install update server)
|
8
7
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
8
|
+
OPTS = Optimist::options do
|
9
|
+
version "DGD-tools version #{DGD::VERSION}"
|
10
|
+
banner <<BANNER
|
11
|
+
Use dgd.manifest to assemble your DGD application.
|
13
12
|
|
14
|
-
|
15
|
-
|
16
|
-
dgd
|
13
|
+
Available subcommands:
|
14
|
+
new [project_name]: create a new DGD-manifest project
|
15
|
+
test: make sure the dgd.manifest file is well-formed and usable
|
16
|
+
install: compile the DGD application to a config file and a root directory
|
17
|
+
update: copy files into generated root directory but do *not* clear 'extra' files (e.g. user data)
|
18
|
+
server: run DGD with the generated root and configuration
|
17
19
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
exit
|
20
|
+
Available options:
|
21
|
+
BANNER
|
22
|
+
opt :verbose, "Print verbose output where available"
|
23
|
+
stop_on SUB_COMMANDS
|
23
24
|
end
|
24
25
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
when "update"
|
55
|
-
|
56
|
-
|
26
|
+
ARGV.push("install") if ARGV.size == 0
|
27
|
+
cmd = ARGV.shift
|
28
|
+
cmd_opts = case cmd
|
29
|
+
when "test"
|
30
|
+
#Optimist::options do
|
31
|
+
# opt :harsh, "check as exactly as possible"
|
32
|
+
#end
|
33
|
+
|
34
|
+
unless File.exist?("dgd.manifest")
|
35
|
+
raise "I don't see a dgd.manifest file in this directory!"
|
36
|
+
end
|
37
|
+
puts "Running dgd.manifest installer..."
|
38
|
+
repo = DGD::Manifest::Repo.new
|
39
|
+
repo.manifest_file("dgd.manifest")
|
40
|
+
repo.precheck(".", verbose: OPTS[:verbose])
|
41
|
+
puts "Verified Manifest packages: this looks likely correct."
|
42
|
+
|
43
|
+
when "install"
|
44
|
+
unless File.exist?("dgd.manifest")
|
45
|
+
raise "I don't see a dgd.manifest file in this directory!"
|
46
|
+
end
|
47
|
+
puts "Running DGD Manifest installer..."
|
48
|
+
repo = DGD::Manifest::Repo.new
|
49
|
+
repo.manifest_file("dgd.manifest")
|
50
|
+
current_dir = File.expand_path(".")
|
51
|
+
repo.precheck(current_dir, verbose: OPTS[:verbose])
|
52
|
+
repo.assemble_app(current_dir, verbose: OPTS[:verbose])
|
53
|
+
puts "Assembled DGD application into #{current_dir}"
|
54
|
+
|
55
|
+
when "update"
|
56
|
+
unless File.exist?("dgd.manifest")
|
57
|
+
raise "I don't see a dgd.manifest file in this directory!"
|
58
|
+
end
|
59
|
+
puts "Running DGD Manifest installer..."
|
60
|
+
repo = DGD::Manifest::Repo.new
|
61
|
+
repo.manifest_file("dgd.manifest")
|
62
|
+
current_dir = File.expand_path(".")
|
63
|
+
repo.precheck(current_dir, verbose: OPTS[:verbose])
|
64
|
+
repo.update_app(current_dir, verbose: OPTS[:verbose])
|
65
|
+
puts "Updated DGD application in #{current_dir}"
|
66
|
+
|
67
|
+
when "server"
|
68
|
+
puts "Starting DGD server..."
|
69
|
+
DGD::Manifest.system_call("~/.dgd-tools/dgd/bin/dgd dgd.config")
|
70
|
+
|
71
|
+
when "new"
|
72
|
+
unless ARGV.size == 1
|
73
|
+
puts "Usage: dgd-manifest new [project name]"
|
74
|
+
Optimist::die "Must supply exactly one argument to dgd-manifest new!"
|
75
|
+
end
|
76
|
+
appdir = DGD::Manifest::AppDirectory.new(File.expand_path ARGV[0])
|
77
|
+
appdir.name = ARGV[0]
|
78
|
+
appdir.create!
|
79
|
+
|
80
|
+
else
|
81
|
+
Optimist::die "Unknown subcommand: #{cmd.inspect}"
|
57
82
|
end
|
58
|
-
puts "Running DGD Manifest installer..."
|
59
|
-
repo = DGD::Manifest::Repo.new
|
60
|
-
repo.manifest_file("dgd.manifest")
|
61
|
-
current_dir = File.expand_path(".")
|
62
|
-
repo.precheck(current_dir)
|
63
|
-
repo.update_app(current_dir)
|
64
|
-
puts "Updated DGD application in #{current_dir}"
|
65
|
-
when "server"
|
66
|
-
puts "Starting DGD server..."
|
67
|
-
DGD::Manifest.system_call("~/.dgd-tools/dgd/bin/dgd dgd.config")
|
68
|
-
else
|
69
|
-
raise "Unrecognised #{$0} command: #{ARGV[0].inspect}!"
|
70
|
-
end
|
data/exe/skotos-xml-diff
CHANGED
@@ -14,6 +14,7 @@ Usage:
|
|
14
14
|
skotos-xml-diff [options] <file_or_dir_1> <file_or_dir_2>
|
15
15
|
where [options] are:
|
16
16
|
BANNER
|
17
|
+
opt :version, "Print DGD version and exit"
|
17
18
|
opt :merry_only, "Only diff Merry scripts"
|
18
19
|
opt :ignore_whitespace, "Ignore whitespace in final diff"
|
19
20
|
opt :ignore_types, "Comma-separated list of XML node types to ignore (e.g. Combat:Base,Base:Exit)", type: :string
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require "dgd-tools/version"
|
2
|
+
|
3
|
+
require "treetop"
|
4
|
+
|
5
|
+
require_relative "dgd_grammar_support"
|
6
|
+
Treetop.load "#{__dir__}/dgd_grammar.tt"
|
7
|
+
|
8
|
+
# Preprocessor incantation: cpp -C -I. -D__DGD__ name_of_file.c
|
9
|
+
|
10
|
+
module DGD; end
|
11
|
+
|
12
|
+
module DGD::Doc
|
13
|
+
|
14
|
+
class SourceFile
|
15
|
+
attr_reader :parser
|
16
|
+
|
17
|
+
def initialize(path, dgd_root:)
|
18
|
+
unless File.exist?(path)
|
19
|
+
raise "No such source file for DGD::Doc::Sourcefile: #{path.inspect}"
|
20
|
+
end
|
21
|
+
|
22
|
+
@parser = DGDGrammarParser.new
|
23
|
+
@path = path
|
24
|
+
@dgd_root = dgd_root
|
25
|
+
|
26
|
+
parse_contents
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def parse_contents
|
32
|
+
preproc_output = `cpp -C -I#{@dgd_root}/include -D__DGD__ #{@path}`
|
33
|
+
preproc_output.gsub!(/\n+/, "\n") # The preprocessor often winds up leaving a lot of newlines from various sources
|
34
|
+
preproc_output.gsub!(/^# \d+ ".*"\w*\d*$/, "")
|
35
|
+
data = @parser.parse(preproc_output)
|
36
|
+
if data
|
37
|
+
clean_tree(data)
|
38
|
+
#puts data.inspect
|
39
|
+
else
|
40
|
+
puts @parser.failure_reason
|
41
|
+
puts @parser.failure_line
|
42
|
+
puts @parser.failure_column
|
43
|
+
|
44
|
+
#puts "Preproc output was:#{preproc_output}\n\n\n"
|
45
|
+
raise "Parse error!"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def clean_tree(root_node)
|
50
|
+
return if(root_node.elements.nil?)
|
51
|
+
root_node.elements.each {|node| self.clean_tree(node) }
|
52
|
+
root_node.elements.delete_if {|node| node.class.name == "Treetop::Runtime::SyntaxNode" && node.text_value.size < 20 }
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,373 @@
|
|
1
|
+
grammar DGDGrammar
|
2
|
+
rule source_file
|
3
|
+
ws (inherit ws)* (top_level_decl ws)*
|
4
|
+
end
|
5
|
+
|
6
|
+
rule inherit
|
7
|
+
("private" WS)? "inherit" WS (ident WS)? ('object' WS)? string_exp ws ';' <Inherit>
|
8
|
+
end
|
9
|
+
|
10
|
+
rule top_level_decl
|
11
|
+
data_decl / func_decl
|
12
|
+
end
|
13
|
+
|
14
|
+
rule ident
|
15
|
+
[a-zA-Z_] [a-zA-Z_0-9]* <Identifier>
|
16
|
+
end
|
17
|
+
|
18
|
+
rule c_comment
|
19
|
+
'/*'
|
20
|
+
(
|
21
|
+
!'*/'
|
22
|
+
(. / "\n")
|
23
|
+
)*
|
24
|
+
'*/'
|
25
|
+
end
|
26
|
+
|
27
|
+
rule preproc_hash_line
|
28
|
+
"\n"? "# " decimal " "+ simple_string (" "+ decimal)? "\n"
|
29
|
+
end
|
30
|
+
|
31
|
+
rule simple_string
|
32
|
+
'"' (
|
33
|
+
!["\n\\]
|
34
|
+
.
|
35
|
+
)*
|
36
|
+
'"' <StringLiteral>
|
37
|
+
end
|
38
|
+
|
39
|
+
rule complex_string
|
40
|
+
'"' ( ((!["\n\\] ) .) / . )+ '"' <StringLiteral>
|
41
|
+
end
|
42
|
+
|
43
|
+
rule simple_char
|
44
|
+
"'" ((!['\n\\]) .)+ "'" <CharLiteral>
|
45
|
+
end
|
46
|
+
|
47
|
+
rule complex_char
|
48
|
+
"'" (((!['\n\\]) .) / ("\\" .))+ "'" <CharLiteral>
|
49
|
+
end
|
50
|
+
|
51
|
+
rule decimal
|
52
|
+
[1-9] [0-9]* <DecimalLiteral>
|
53
|
+
end
|
54
|
+
|
55
|
+
rule octal
|
56
|
+
'0' [0-7]* <OctalLiteral>
|
57
|
+
end
|
58
|
+
|
59
|
+
rule hexadecimal
|
60
|
+
'0' [xX] [a-fA-F0-9]+ <HexadecimalLiteral>
|
61
|
+
end
|
62
|
+
|
63
|
+
rule float
|
64
|
+
([0-9]+ "." [0-9]+ ([eE] [-+]? [0-9]+)?) <FloatLiteral> /
|
65
|
+
("." [0-9]+ ([eE] [-+]? [0-9]+)?) <FloatLiteral> /
|
66
|
+
([0-9]+ [eE] [-+]? [0-9]+) <FloatLiteral>
|
67
|
+
end
|
68
|
+
|
69
|
+
rule single_WS
|
70
|
+
[ \t\v\f\r\n] / c_comment / preproc_hash_line
|
71
|
+
end
|
72
|
+
|
73
|
+
rule ws
|
74
|
+
single_WS*
|
75
|
+
end
|
76
|
+
|
77
|
+
rule WS
|
78
|
+
single_WS+
|
79
|
+
end
|
80
|
+
|
81
|
+
rule string
|
82
|
+
simple_string /
|
83
|
+
complex_string
|
84
|
+
end
|
85
|
+
|
86
|
+
rule string_exp
|
87
|
+
string /
|
88
|
+
'(' ws composite_string ws ')'
|
89
|
+
end
|
90
|
+
|
91
|
+
rule composite_string
|
92
|
+
string_exp / string_exp '+' composite_string
|
93
|
+
end
|
94
|
+
|
95
|
+
rule klass
|
96
|
+
(class_spec WS)* class_spec
|
97
|
+
end
|
98
|
+
|
99
|
+
rule class_spec
|
100
|
+
'private' / 'static' / 'atomic' / 'nomask' / 'varargs'
|
101
|
+
end
|
102
|
+
|
103
|
+
rule type_spec
|
104
|
+
'int' / 'float' / 'string' / 'object' / 'mapping' / 'mixed' / 'void'
|
105
|
+
end
|
106
|
+
|
107
|
+
rule stars
|
108
|
+
('*' ws)*
|
109
|
+
end
|
110
|
+
|
111
|
+
rule formals
|
112
|
+
# If you put these in a different order with '' and 'void' first, parses start failing. That seems bad.
|
113
|
+
formal_list (ws '...')? / '' / 'void'
|
114
|
+
end
|
115
|
+
|
116
|
+
rule formal_list
|
117
|
+
formal (ws ',' ws formal)*
|
118
|
+
end
|
119
|
+
|
120
|
+
rule formal
|
121
|
+
class_type data_declarator /
|
122
|
+
ident
|
123
|
+
end
|
124
|
+
|
125
|
+
rule data_decl
|
126
|
+
class_type WS declarators ws ';' <DataDecl>
|
127
|
+
end
|
128
|
+
|
129
|
+
rule func_decl
|
130
|
+
class_type WS function_declarator ws compound_statement <FuncDecl> /
|
131
|
+
klass WS function_name ws '(' ws formals ws ')' ws compound_statement <FuncDecl>
|
132
|
+
end
|
133
|
+
|
134
|
+
rule class_type
|
135
|
+
(class_spec WS)* type_spec /
|
136
|
+
(class_spec WS)* 'object' list_exp
|
137
|
+
end
|
138
|
+
|
139
|
+
rule data_declarator
|
140
|
+
stars ws ident
|
141
|
+
end
|
142
|
+
|
143
|
+
rule function_name
|
144
|
+
ident /
|
145
|
+
'operator' ws '+' /
|
146
|
+
'operator' ws '-' /
|
147
|
+
'operator' ws '*' /
|
148
|
+
'operator' ws '/' /
|
149
|
+
'operator' ws '%' /
|
150
|
+
'operator' ws '&' /
|
151
|
+
'operator' ws '^' /
|
152
|
+
'operator' ws '|' /
|
153
|
+
'operator' ws '<' /
|
154
|
+
'operator' ws '>' /
|
155
|
+
'operator' ws '>=' /
|
156
|
+
'operator' ws '<=' /
|
157
|
+
'operator' ws '<<' /
|
158
|
+
'operator' ws '>>' /
|
159
|
+
'operator' ws '~' /
|
160
|
+
'operator' ws '++' /
|
161
|
+
'operator' ws '--' /
|
162
|
+
'operator' ws '[' ws ']' /
|
163
|
+
'operator' ws '[' ws ']' ws '=' /
|
164
|
+
'operator' ws '[' ws '..' ws ']'
|
165
|
+
end
|
166
|
+
|
167
|
+
rule function_declarator
|
168
|
+
stars ws function_name ws '(' ws formals ws ')'
|
169
|
+
end
|
170
|
+
|
171
|
+
rule declarator
|
172
|
+
function_declarator / data_declarator
|
173
|
+
end
|
174
|
+
|
175
|
+
rule declarators
|
176
|
+
declarator (ws ',' ws declarator)*
|
177
|
+
end
|
178
|
+
|
179
|
+
rule locals
|
180
|
+
(ws data_decl ws)*
|
181
|
+
end
|
182
|
+
|
183
|
+
rule statements
|
184
|
+
(ws statement ws)*
|
185
|
+
end
|
186
|
+
|
187
|
+
rule statement
|
188
|
+
'if' ws '(' ws list_exp ws ')' ws statement (WS 'else' statement)? /
|
189
|
+
'do' WS statement WS 'while' ws '(' ws list_exp ws ')' ws ';' /
|
190
|
+
'while' ws '(' ws list_exp ws ')' ws statement /
|
191
|
+
'for' ws '(' ws list_exp? ws ';' ws list_exp? ws ';' ws list_exp? ws ')' ws statement /
|
192
|
+
'rlimits' ws '(' ws list_exp ws ';' ws list_exp ws ')' ws compound_statement /
|
193
|
+
'catch' ws compound_statement ws ':' statement /
|
194
|
+
'catch' ws compound_statement /
|
195
|
+
'switch' ws '(' ws list_exp ws ')' ws compound_statement /
|
196
|
+
'case' WS exp ws ':' ws statement /
|
197
|
+
'case' WS exp ws '..' ws exp ws ':' statement /
|
198
|
+
'default' ws ':' ws statement /
|
199
|
+
'goto' WS ident ws ';' /
|
200
|
+
'break' ws ';' /
|
201
|
+
'continue' ws ';' /
|
202
|
+
'return' WS list_exp WS ';' /
|
203
|
+
'return' ws ';' /
|
204
|
+
ident ws ':' ws statement / # label statement
|
205
|
+
list_exp /
|
206
|
+
compound_statement /
|
207
|
+
';'
|
208
|
+
end
|
209
|
+
|
210
|
+
rule compound_statement
|
211
|
+
'{' ws locals ws statements ws '}'
|
212
|
+
end
|
213
|
+
|
214
|
+
rule function_call
|
215
|
+
('::' ws function_name) /
|
216
|
+
(ident ws '::' ws function_name) /
|
217
|
+
function_name
|
218
|
+
end
|
219
|
+
|
220
|
+
rule list_exp
|
221
|
+
exp ws ',' ws list_exp /
|
222
|
+
exp
|
223
|
+
end
|
224
|
+
|
225
|
+
rule exp
|
226
|
+
cond_exp ws '=' ws exp /
|
227
|
+
cond_exp ws '+=' ws exp /
|
228
|
+
cond_exp ws '-=' ws exp /
|
229
|
+
cond_exp ws '*=' ws exp /
|
230
|
+
cond_exp ws '/=' ws exp /
|
231
|
+
cond_exp ws '%=' ws exp /
|
232
|
+
cond_exp ws '<<=' ws exp /
|
233
|
+
cond_exp ws '>>=' ws exp /
|
234
|
+
cond_exp ws '&=' ws exp /
|
235
|
+
cond_exp ws '^=' ws exp /
|
236
|
+
cond_exp ws '|=' ws exp /
|
237
|
+
cond_exp
|
238
|
+
end
|
239
|
+
|
240
|
+
rule cond_exp
|
241
|
+
or_exp ws '?' ws list_exp ws ':' ws cond_exp / or_exp
|
242
|
+
end
|
243
|
+
|
244
|
+
rule or_exp
|
245
|
+
and_exp ws '||' ws or_exp / and_exp
|
246
|
+
end
|
247
|
+
|
248
|
+
rule and_exp
|
249
|
+
bitor_exp ws '&&' ws and_exp / bitor_exp
|
250
|
+
end
|
251
|
+
|
252
|
+
rule bitor_exp
|
253
|
+
bitxor_exp ws '|' ws bitor_exp / bitxor_exp
|
254
|
+
end
|
255
|
+
|
256
|
+
rule bitxor_exp
|
257
|
+
bitand_exp ws '^' ws bitxor_exp / bitand_exp
|
258
|
+
end
|
259
|
+
|
260
|
+
rule bitand_exp
|
261
|
+
equ_exp ws '&' bitand_exp / equ_exp
|
262
|
+
end
|
263
|
+
|
264
|
+
rule equ_exp
|
265
|
+
rel_exp ws '==' ws equ_exp /
|
266
|
+
rel_exp ws '!=' ws equ_exp /
|
267
|
+
rel_exp
|
268
|
+
end
|
269
|
+
|
270
|
+
rule rel_exp
|
271
|
+
shift_exp ws '<' ws rel_exp /
|
272
|
+
shift_exp ws '>' ws rel_exp /
|
273
|
+
shift_exp ws '<=' ws rel_exp /
|
274
|
+
shift_exp ws '>=' ws rel_exp /
|
275
|
+
shift_exp
|
276
|
+
end
|
277
|
+
|
278
|
+
rule shift_exp
|
279
|
+
add_exp ws '<<' ws shift_exp /
|
280
|
+
add_exp ws '>>' ws shift_exp /
|
281
|
+
add_exp
|
282
|
+
end
|
283
|
+
|
284
|
+
rule add_exp
|
285
|
+
mult_exp ws '+' ws add_exp /
|
286
|
+
mult_exp ws '-' ws add_exp /
|
287
|
+
mult_exp
|
288
|
+
end
|
289
|
+
|
290
|
+
rule mult_exp
|
291
|
+
cast_exp ws '*' ws mult_exp /
|
292
|
+
cast_exp ws '/' ws mult_exp /
|
293
|
+
cast_exp ws '%' ws mult_exp /
|
294
|
+
cast_exp
|
295
|
+
end
|
296
|
+
|
297
|
+
rule cast_exp
|
298
|
+
'(' ws class_type ws stars ws ')' ws cast_exp /
|
299
|
+
prefix_exp
|
300
|
+
end
|
301
|
+
|
302
|
+
rule prefix_exp
|
303
|
+
'++' ws cast_exp /
|
304
|
+
'--' ws cast_exp /
|
305
|
+
'+' ws cast_exp /
|
306
|
+
'-' ws cast_exp /
|
307
|
+
'!' ws cast_exp /
|
308
|
+
'~' ws cast_exp /
|
309
|
+
postfix_exp
|
310
|
+
end
|
311
|
+
|
312
|
+
rule postfix_exp
|
313
|
+
exp2 (ws ('++' / '--'))?
|
314
|
+
end
|
315
|
+
|
316
|
+
rule exp2
|
317
|
+
exp1 ws '->' ws ident ws '(' ws opt_arg_list ws ')' /
|
318
|
+
exp1 ws '<-' ws string_exp /
|
319
|
+
exp1 ((ws '[' ws list_exp ws ']') / (ws '[' ws (list_exp ws)? '..' ws (list_exp ws)? ']'))*
|
320
|
+
end
|
321
|
+
|
322
|
+
rule exp1
|
323
|
+
# This works (for now) with function_call up front, but not when it was lower down...
|
324
|
+
# There's some kind of bad stuff going on with precedence that's causing parse failures.
|
325
|
+
# That's weird, since I assume it should try all combinations/precedences before giving up...
|
326
|
+
function_call ws '(' ws opt_arg_list ws ')' /
|
327
|
+
'catch' ws '(' list_exp ws ')' /
|
328
|
+
'new' (WS 'object')? ws string_exp (ws '(' ws opt_arg_list ws ')')? /
|
329
|
+
'nil' /
|
330
|
+
'(' ws '{' ws opt_arg_list_comma ws '}' ws ')' /
|
331
|
+
'(' ws '[' ws opt_assoc_list_comma ws ']' ws ')' /
|
332
|
+
'::' ws ident /
|
333
|
+
decimal /
|
334
|
+
octal /
|
335
|
+
hexadecimal /
|
336
|
+
simple_char /
|
337
|
+
complex_char /
|
338
|
+
float /
|
339
|
+
string /
|
340
|
+
ident /
|
341
|
+
'(' ws list_exp ws ')'
|
342
|
+
end
|
343
|
+
|
344
|
+
rule arg_list
|
345
|
+
exp ws ',' ws arg_list /
|
346
|
+
exp
|
347
|
+
end
|
348
|
+
|
349
|
+
rule opt_arg_list
|
350
|
+
arg_list ws '...' /
|
351
|
+
arg_list?
|
352
|
+
end
|
353
|
+
|
354
|
+
rule opt_arg_list_comma
|
355
|
+
arg_list ws ',' /
|
356
|
+
arg_list?
|
357
|
+
end
|
358
|
+
|
359
|
+
rule assoc_list
|
360
|
+
assoc_pair ws ',' ws assoc_list /
|
361
|
+
assoc_pair
|
362
|
+
end
|
363
|
+
|
364
|
+
rule assoc_pair
|
365
|
+
exp ws ':' ws exp
|
366
|
+
end
|
367
|
+
|
368
|
+
rule opt_assoc_list_comma
|
369
|
+
assoc_list ws ',' /
|
370
|
+
assoc_list?
|
371
|
+
end
|
372
|
+
|
373
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
#class StringLiteral < Treetop::Runtime::SyntaxNode
|
2
|
+
# def some_name
|
3
|
+
# # This is a pretty crude way of handling character escaping, etc.
|
4
|
+
# return eval self.text_value
|
5
|
+
# end
|
6
|
+
#end
|
7
|
+
|
8
|
+
class DataDecl < Treetop::Runtime::SyntaxNode
|
9
|
+
end
|
10
|
+
|
11
|
+
class FuncDecl < Treetop::Runtime::SyntaxNode
|
12
|
+
end
|
13
|
+
|
14
|
+
class Inherit < Treetop::Runtime::SyntaxNode
|
15
|
+
end
|
16
|
+
|
17
|
+
class Identifier < Treetop::Runtime::SyntaxNode
|
18
|
+
end
|
19
|
+
|
20
|
+
class DecimalLiteral < Treetop::Runtime::SyntaxNode
|
21
|
+
end
|
22
|
+
|
23
|
+
class OctalLiteral < Treetop::Runtime::SyntaxNode
|
24
|
+
end
|
25
|
+
|
26
|
+
class HexadecimalLiteral < Treetop::Runtime::SyntaxNode
|
27
|
+
end
|
28
|
+
|
29
|
+
class FloatLiteral < Treetop::Runtime::SyntaxNode
|
30
|
+
end
|
31
|
+
|
32
|
+
class StringLiteral < Treetop::Runtime::SyntaxNode
|
33
|
+
end
|
34
|
+
|
35
|
+
class CharLiteral < Treetop::Runtime::SyntaxNode
|
36
|
+
end
|
data/lib/dgd-tools/manifest.rb
CHANGED
@@ -22,7 +22,7 @@ module DGD::Manifest
|
|
22
22
|
puts "Running command: #{cmd.inspect}..."
|
23
23
|
system(cmd, out: $stdout, err: :out)
|
24
24
|
unless $?.success?
|
25
|
-
raise "Error running command: #{cmd.inspect}!"
|
25
|
+
raise "Error running command in #{Dir.pwd}: #{cmd.inspect}!"
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
@@ -64,19 +64,20 @@ module DGD::Manifest
|
|
64
64
|
raise "Already have a dgd.manifest file!" unless @no_manifest_file
|
65
65
|
|
66
66
|
@no_manifest_file = false
|
67
|
-
@manifest_file ||= AppFile.new(self, path)
|
67
|
+
@manifest_file ||= AppFile.new(self, path, shared_dir: shared_dir)
|
68
68
|
end
|
69
69
|
|
70
70
|
protected
|
71
71
|
|
72
72
|
# This includes files to assemble... But also subdirectories and commands. This format is
|
73
73
|
# unstable and ugly, and should not be exposed to outside parties who might later depend on it.
|
74
|
-
def assembly_operations(location)
|
74
|
+
def assembly_operations(location, verbose:)
|
75
75
|
operations = []
|
76
76
|
|
77
77
|
raise("No manifest file!") if @no_manifest_file
|
78
78
|
|
79
|
-
|
79
|
+
# For each spec, put its dependencies before itself in order
|
80
|
+
@manifest_file.ordered_specs.each do |spec|
|
80
81
|
spec_git_repo = spec.source
|
81
82
|
spec_git_repo.use_details(spec.source_details) # This sets things like checked-out branch
|
82
83
|
|
@@ -125,26 +126,38 @@ module DGD::Manifest
|
|
125
126
|
"#{File.expand_path(location)}/#{GENERATED_ROOT}"
|
126
127
|
end
|
127
128
|
|
128
|
-
def assemble_app(location)
|
129
|
+
def assemble_app(location, verbose:)
|
129
130
|
Dir[File.join(dgd_root(location), "*")].each { |dir| FileUtils.rm_rf dir }
|
131
|
+
Dir[File.join(dgd_root(location), "state", "*")].each { |dir| FileUtils.rm_rf dir }
|
132
|
+
Dir[File.join(dgd_root(location), ".repos", "*")].each { |dir| FileUtils.rm_f dir }
|
130
133
|
|
131
|
-
write_app_files(location)
|
134
|
+
write_app_files(location, verbose: verbose)
|
132
135
|
end
|
133
136
|
|
134
|
-
def update_app(location)
|
135
|
-
write_app_files(location
|
137
|
+
def update_app(location, verbose:)
|
138
|
+
write_app_files(location, verbose: verbose)
|
136
139
|
end
|
137
140
|
|
138
141
|
protected
|
139
142
|
|
140
|
-
def write_app_files(location)
|
143
|
+
def write_app_files(location, verbose:)
|
141
144
|
Dir.chdir(location) do
|
142
145
|
write_config_file("#{location}/dgd.config")
|
143
146
|
FileUtils.mkdir_p("#{location}/state") # Statedir for statedumps, editor files, etc.
|
147
|
+
repos_dir = "#{location}/.repos"
|
148
|
+
FileUtils.mkdir_p(repos_dir) # Links to repos in manifest
|
144
149
|
|
145
|
-
|
150
|
+
@manifest_file.ordered_specs.each do |spec|
|
151
|
+
FileUtils.ln_s(spec.source.local_dir, File.join(".repos", spec.name))
|
152
|
+
end
|
153
|
+
|
154
|
+
assembly_operations(location, verbose: verbose).each do |sd_hash|
|
146
155
|
to_path = "#{dgd_root(location)}/#{sd_hash[:to]}"
|
147
156
|
|
157
|
+
if verbose
|
158
|
+
puts " Copy #{sd_hash[:from]} -> #{sd_hash[:to]}, files #{sd_hash[:non_dirs].join(", ")}"
|
159
|
+
end
|
160
|
+
|
148
161
|
# Make appropriate dirs, including empty ones
|
149
162
|
sd_hash[:dirs].each do |dir|
|
150
163
|
FileUtils.mkdir_p dir.sub(sd_hash[:from], to_path)
|
@@ -154,8 +167,13 @@ module DGD::Manifest
|
|
154
167
|
sd_hash[:non_dirs].each do |from_file|
|
155
168
|
to_file = from_file.sub(sd_hash[:from], "#{dgd_root(location)}/#{sd_hash[:to]}")
|
156
169
|
to_dir = File.dirname(to_file)
|
157
|
-
|
158
|
-
|
170
|
+
begin
|
171
|
+
FileUtils.mkdir_p to_dir
|
172
|
+
FileUtils.cp from_file, to_file
|
173
|
+
rescue
|
174
|
+
puts "Error when copying: #{from_file} -> #{to_file} in #{sd_hash.inspect}"
|
175
|
+
raise
|
176
|
+
end
|
159
177
|
end
|
160
178
|
end
|
161
179
|
end
|
@@ -163,8 +181,8 @@ module DGD::Manifest
|
|
163
181
|
|
164
182
|
public
|
165
183
|
|
166
|
-
def precheck(location)
|
167
|
-
all_files = assembly_operations(location).flat_map { |sd| sd[:non_dirs] }
|
184
|
+
def precheck(location, verbose:)
|
185
|
+
all_files = assembly_operations(location, verbose: verbose).flat_map { |sd| sd[:non_dirs] }
|
168
186
|
|
169
187
|
if all_files.size != all_files.uniq.size
|
170
188
|
repeated = all_files.uniq.select { |f| all_files.count(f) > 1 }
|
@@ -188,7 +206,7 @@ module DGD::Manifest
|
|
188
206
|
def initialize(repo, git_url)
|
189
207
|
@git_url = git_url
|
190
208
|
@repo = repo
|
191
|
-
local_path = git_url.tr("/\\", "_")
|
209
|
+
local_path = git_url.tr("/\\ ", "_")
|
192
210
|
@local_dir = "#{@repo.shared_dir}/git/#{local_path}"
|
193
211
|
|
194
212
|
if File.directory?(@local_dir)
|
@@ -217,15 +235,18 @@ module DGD::Manifest
|
|
217
235
|
end
|
218
236
|
end
|
219
237
|
|
238
|
+
# This class parses the DGD manifest
|
220
239
|
class AppFile
|
221
240
|
attr_reader :path
|
222
241
|
attr_reader :repo
|
223
242
|
attr_reader :specs
|
224
243
|
attr_reader :dgd_config
|
244
|
+
attr_reader :shared_dir
|
225
245
|
|
226
|
-
def initialize(repo, path)
|
246
|
+
def initialize(repo, path, shared_dir:)
|
227
247
|
@path = path
|
228
248
|
@repo = repo
|
249
|
+
@shared_dir = shared_dir
|
229
250
|
raise("No such dgd.manifest file as #{path.inspect}!") unless File.exist?(path)
|
230
251
|
contents = AppFile.parse_manifest_file(path)
|
231
252
|
|
@@ -279,6 +300,10 @@ module DGD::Manifest
|
|
279
300
|
|
280
301
|
@dgd_config = DGDRuntimeConfig.new (contents["config"] || {})
|
281
302
|
|
303
|
+
if contents["app_root"]
|
304
|
+
raise "App_root must now be inside config block!"
|
305
|
+
end
|
306
|
+
|
282
307
|
if contents["unbundled_goods"]
|
283
308
|
raise "Unbundled_goods must be an array!" unless contents["unbundled_goods"].is_a?(Array)
|
284
309
|
|
@@ -290,7 +315,10 @@ module DGD::Manifest
|
|
290
315
|
|
291
316
|
@specs += contents["goods"].map do |goods_url|
|
292
317
|
begin
|
293
|
-
|
318
|
+
text_contents = URI.open(goods_url).read
|
319
|
+
local_path = shared_dir + "/goods/" + goods_url.tr("/\\ ", "_")
|
320
|
+
File.open(local_path, "wb") { |f| f.write(text_contents) }
|
321
|
+
json_contents = JSON.parse text_contents
|
294
322
|
rescue
|
295
323
|
STDERR.puts "Error reading or parsing by URL: #{goods_url.inspect}"
|
296
324
|
raise
|
@@ -325,21 +353,42 @@ module DGD::Manifest
|
|
325
353
|
# For now, permit a single string as a dependency.
|
326
354
|
fields["dependencies"] = [ fields["dependencies"] ] if fields["dependencies"].is_a?(String)
|
327
355
|
|
356
|
+
goods_url = nil
|
328
357
|
fields["dependencies"].each do |dep|
|
329
358
|
if dep.is_a?(String)
|
330
|
-
|
359
|
+
goods_url = dep
|
331
360
|
elsif dep.is_a?(Hash)
|
332
361
|
raise "Currently only URL-based dependencies on Goods files are supported!" unless dep["url"]
|
333
|
-
|
362
|
+
goods_url = dep["url"]
|
334
363
|
else
|
335
364
|
raise "Unexpected dependency type #{dep.class} when parsing DGD Manifest specs, item: #{dep.inspect}"
|
336
365
|
end
|
366
|
+
|
367
|
+
text_contents = URI.open(goods_url).read
|
368
|
+
local_path = shared_dir + "/goods/" + goods_url.tr("/\\ ", "_")
|
369
|
+
File.open(local_path, "wb") { |f| f.write(text_contents) }
|
370
|
+
dep_fields = JSON.parse text_contents
|
371
|
+
|
372
|
+
dependencies.push unbundled_json_to_spec(dep_fields)
|
337
373
|
end
|
338
374
|
end
|
339
375
|
|
340
376
|
spec = GoodsSpec.new(@repo, name: fields["name"], source: source, source_details: source_details, paths: fields["paths"], dependencies: dependencies)
|
341
377
|
return spec
|
342
378
|
end
|
379
|
+
|
380
|
+
def ordered_specs
|
381
|
+
@specs.flat_map do |s|
|
382
|
+
deps = [s]
|
383
|
+
deps_to_add = s.dependencies
|
384
|
+
while(deps_to_add.size > 0)
|
385
|
+
next_deps = deps_to_add.flat_map { |dep| dep.dependencies }
|
386
|
+
deps = deps_to_add + deps
|
387
|
+
deps_to_add = next_deps
|
388
|
+
end
|
389
|
+
deps
|
390
|
+
end
|
391
|
+
end
|
343
392
|
end
|
344
393
|
|
345
394
|
class GoodsSpec
|
@@ -388,6 +437,13 @@ module DGD::Manifest
|
|
388
437
|
.root
|
389
438
|
dgd.config
|
390
439
|
state/*
|
440
|
+
wafer
|
441
|
+
websocket-to-tcp-tunnel
|
442
|
+
dgd
|
443
|
+
log/*
|
444
|
+
skotos.database
|
445
|
+
skotos.database.old
|
446
|
+
.repos/**
|
391
447
|
FILE_CONTENTS
|
392
448
|
end
|
393
449
|
|
@@ -400,7 +456,7 @@ module DGD::Manifest
|
|
400
456
|
"app_root": "app",
|
401
457
|
"goods": [
|
402
458
|
"# This is an example goods file - substitute your own.",
|
403
|
-
"https://raw.githubusercontent.com/
|
459
|
+
"https://raw.githubusercontent.com/ChatTheatre/dgd-tools/main/goods/skotos_httpd.goods"
|
404
460
|
],
|
405
461
|
"unbundled_goods": [
|
406
462
|
{
|
@@ -521,15 +577,17 @@ FILE_CONTENTS
|
|
521
577
|
|
522
578
|
def config_to_ports(data)
|
523
579
|
if data.is_a?(Hash)
|
524
|
-
|
525
|
-
return data
|
580
|
+
return data.map { |ip, port| [ip, Integer(port) ] }
|
526
581
|
elsif data.is_a?(Array)
|
527
|
-
|
528
|
-
|
529
|
-
|
582
|
+
if data[0].is_a?(Array)
|
583
|
+
ports = data.map { |ip, port| [ip, Integer(port) ] }
|
584
|
+
return ports
|
585
|
+
end
|
586
|
+
|
587
|
+
ports = data.map { |p| [ "*", Integer(p) ] }
|
530
588
|
return ports
|
531
589
|
elsif data.is_a?(Integer)
|
532
|
-
return
|
590
|
+
return [ [ "*", data ] ]
|
533
591
|
else
|
534
592
|
raise "dgd-manifest: not sure how to get port data from a #{data.class.name} -- #{data.inspect}!"
|
535
593
|
end
|
@@ -46,11 +46,13 @@ class SkotOS::XMLObject
|
|
46
46
|
of1.close
|
47
47
|
of2.close
|
48
48
|
|
49
|
-
diff_opts = [ "
|
50
|
-
diff_opts += [ "
|
49
|
+
diff_opts = [ "c" ]
|
50
|
+
diff_opts += [ "b", "B" ] if self.ignore_whitespace
|
51
51
|
|
52
52
|
# Diff 'fails' if there's a difference between the two files.
|
53
|
-
|
53
|
+
cmd = "diff -#{diff_opts.join("")} #{of1.path} #{of2.path}"
|
54
|
+
#puts "Diff command: #{cmd}"
|
55
|
+
diff = system_call(cmd, fail_ok: true)
|
54
56
|
diff.sub!(of1.path, o1_name)
|
55
57
|
diff.sub!(of2.path, o2_name)
|
56
58
|
ensure
|
@@ -115,11 +117,16 @@ class SkotOS::XMLObject
|
|
115
117
|
end
|
116
118
|
|
117
119
|
rev = noko_single_node(doc.root, "Core:Property", attrs: { "property" => "revisions" })
|
118
|
-
rev
|
120
|
+
noko_remove(rev) if rev
|
119
121
|
|
120
122
|
list = noko_single_node(doc.root, "Core:Property", attrs: { "property" => "#list#" })
|
121
123
|
list.remove if list
|
122
124
|
|
125
|
+
properties = noko_with_name_and_attrs(doc.root, "Core:Property")
|
126
|
+
properties.each do |prop_node|
|
127
|
+
prop_node.remove if prop_node.attribute("property").value.start_with?("sys:sync")
|
128
|
+
end
|
129
|
+
|
123
130
|
if self.merry_only
|
124
131
|
# Kill off all the non-Merry nodes
|
125
132
|
noko_remove_non_merry_nodes(doc.root)
|
@@ -128,7 +135,7 @@ class SkotOS::XMLObject
|
|
128
135
|
if self.ignore_types
|
129
136
|
self.ignore_types.each do |ignored_type|
|
130
137
|
skipped = noko_with_name_and_attrs(doc.root, ignored_type)
|
131
|
-
skipped.each { |n| n
|
138
|
+
skipped.each { |n| noko_remove(n) }
|
132
139
|
end
|
133
140
|
end
|
134
141
|
|
@@ -144,6 +151,12 @@ class SkotOS::XMLObject
|
|
144
151
|
end
|
145
152
|
end
|
146
153
|
|
154
|
+
def self.noko_remove(node)
|
155
|
+
nn = node.next
|
156
|
+
nn.remove if nn.is_a?(Nokogiri::XML::Text)
|
157
|
+
node.remove
|
158
|
+
end
|
159
|
+
|
147
160
|
def self.noko_single_node(node, name, attrs: {})
|
148
161
|
choices = noko_with_name_and_attrs(node, name, attrs)
|
149
162
|
if choices.size < 1
|
data/lib/dgd-tools/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dgd-tools
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.12
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Noah Gibbs
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-05-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: 3.0.1
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: treetop
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
41
55
|
description: dgd-tools supplies DGD Manifest and eventually perhaps other tools. DGD
|
42
56
|
Manifest is an experimental DGD library and packaging system.
|
43
57
|
email:
|
@@ -69,6 +83,9 @@ files:
|
|
69
83
|
- exe/skotos-xml-diff
|
70
84
|
- goods/chattheatre_kernellib.goods
|
71
85
|
- goods/skotos_httpd.goods
|
86
|
+
- lib/dgd-tools/dgd-doc.rb
|
87
|
+
- lib/dgd-tools/dgd_grammar.tt
|
88
|
+
- lib/dgd-tools/dgd_grammar_support.rb
|
72
89
|
- lib/dgd-tools/manifest.rb
|
73
90
|
- lib/dgd-tools/skotos_xml_obj.rb
|
74
91
|
- lib/dgd-tools/version.rb
|