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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2b3639fa674b53796ffe654f0e7e0deb9506868eece4550b99b4f28b98940e97
4
- data.tar.gz: b0f115747b8f790ba079a9789d18e5bbe024de6e9b1c6cc1c476d21066a1b48a
3
+ metadata.gz: ed7c35c57fad646f3083312c2c4a0d3b2ed1dcc9fa0d7f95f4b2c89d49ddadba
4
+ data.tar.gz: 8124dbf072f51dfd84ba1bde82fe60e3521d20b7eb53ef8dc413b8d31f78a57b
5
5
  SHA512:
6
- metadata.gz: c739260975e503e32a44bfeaf4775d6693e606f35a247f6d432008d0b9e813ac7b29208d1db641dee46be7aec8bbb86e92c1f8fe7e9c7b1c2aadb2ce93e4fb8e
7
- data.tar.gz: 50cc3537969a52ca379857a8936b900212e18567bdc10c1cb1152cffb7901f88db53b75a04126b8848e0edb3151d74a4514cc3fe02d7c1ae1f0ece0cbbe7d6f3
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.7)
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 called WOE, which is [documented in SkotOS-Doc](https://ChatTheatre.github.io/SkotOS-Doc). The skotos-xml-diff utility will diff between WOE objects or directories of WOE 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
- It's possible to add it to a Ruby's application's Gemfile. Ordinarily you wouldn't.
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
- If you update files in your root and want to update files under the generated root directory, use "dgd-manifest update".
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
@@ -26,4 +26,5 @@ Gem::Specification.new do |spec|
26
26
 
27
27
  spec.add_runtime_dependency "nokogiri", "~>1.10.5"
28
28
  spec.add_runtime_dependency "optimist", "~>3.0.1"
29
+ spec.add_runtime_dependency "treetop"
29
30
  end
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
- if ARGV.size == 0
6
- ARGV.push "install"
7
- end
6
+ SUB_COMMANDS = %w(new test install update server)
8
7
 
9
- if ARGV == ["--version"]
10
- puts "dgd-tools version #{DGD::VERSION}"
11
- exit
12
- end
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
- if ARGV.size == 1 && ["-h", "--help"].include?(ARGV[0])
15
- puts <<HELP_INFO
16
- dgd-manifest commands:
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
- new [project_name]: create a new DGD-manifest project
19
- test: make sure the dgd.manifest file is well-formed and usable
20
- install: compile the DGD application to a config file and a root directory
21
- HELP_INFO
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
- case ARGV[0]
26
- when "new"
27
- unless ARGV.size == 2
28
- puts "Usage: dgd-manifest new [project name]"
29
- raise "Must supply exactly one argument to dgd-manifest new!"
30
- end
31
- appdir = DGD::Manifest::AppDirectory.new(File.expand_path ARGV[1])
32
- appdir.name = ARGV[1]
33
- appdir.create!
34
- when "test"
35
- unless File.exist?("dgd.manifest")
36
- raise "I don't see a dgd.manifest file in this directory!"
37
- end
38
- puts "Running dgd.manifest installer..."
39
- repo = DGD::Manifest::Repo.new
40
- repo.manifest_file("dgd.manifest")
41
- repo.precheck(".")
42
- puts "Verified Manifest packages: this looks likely correct."
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)
52
- repo.assemble_app(current_dir)
53
- puts "Assembled DGD application into #{current_dir}"
54
- when "update"
55
- unless File.exist?("dgd.manifest")
56
- raise "I don't see a dgd.manifest file in this directory!"
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
@@ -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
- @manifest_file.specs.each do |spec|
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) # TODO: maybe check files dates? Some way to do update-only
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
- assembly_operations(location).each do |sd_hash|
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
- FileUtils.mkdir_p to_dir
158
- FileUtils.cp from_file, to_file
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
- json_contents = JSON.parse(URI.open(goods_url).read)
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
- dependencies.push "url" => dep
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
- dependencies.push dep
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/noahgibbs/dgd-tools/main/goods/skotos_httpd.goods"
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
- # TODO: verify that keys are IP addr strings and values are legal port numbers
525
- return data
580
+ return data.map { |ip, port| [ip, Integer(port) ] }
526
581
  elsif data.is_a?(Array)
527
- # TODO: verify that data is an array of legal integer port numbers
528
- ports = {}
529
- data.each { |p| ports["*"] = p }
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 { "*": data }
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 = [ "-c" ]
50
- diff_opts += [ "-w", "-B" ] if self.ignore_whitespace
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
- diff = system_call("diff #{diff_opts.join(" ")} #{of1.path} #{of2.path}", fail_ok: true)
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.remove if 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.remove }
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
@@ -1,3 +1,3 @@
1
1
  module DGD
2
- VERSION = "0.1.7"
2
+ VERSION = "0.1.12"
3
3
  end
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.7
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-03-03 00:00:00.000000000 Z
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