Skip to content

Commit 91a1404

Browse files
committed
rfw2txt without format output
1 parent 8a3a7d7 commit 91a1404

File tree

8 files changed

+226
-13
lines changed

8 files changed

+226
-13
lines changed

packages/rfw2txt/CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
## 1.0.0
1+
## 0.0.1
22

33
- Initial version.

packages/rfw2txt/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
A sample command-line application providing basic argument parsing with an entrypoint in `bin/`.
1+
# rfw2txt

packages/rfw2txt/bin/rfw2txt.dart

Lines changed: 114 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ void main(List<String> arguments) {
6767
printUsage(argParser);
6868
return;
6969
}
70-
70+
7171
// check if file exists
7272
String rfwPath = results.arguments[0];
7373
File rfwFile = File(rfwPath);
@@ -81,11 +81,123 @@ void main(List<String> arguments) {
8181
}
8282
File outputFile = File(outputPath);
8383
outputFile.writeAsStringSync(
84-
decodeLibraryBlob(rfwFile.readAsBytesSync()).toString());
84+
decodeLibraryBlob(rfwFile.readAsBytesSync()).visit(ParseTxtVisitor()));
8585
} on FormatException catch (e) {
8686
// Print usage information if an invalid argument was provided.
8787
print(e.message);
8888
print('');
8989
printUsage(argParser);
9090
}
9191
}
92+
93+
extension on RemoteWidgetLibrary {
94+
String visit(ParseTxtVisitor visitor) => visitor.visit(this);
95+
}
96+
97+
class ParseTxtVisitor {
98+
String visit(RemoteWidgetLibrary library) {
99+
StringBuffer buffer = StringBuffer();
100+
// write imports
101+
buffer.writeln(library.imports.map(_visitImport).join('\n'));
102+
103+
buffer.writeln();
104+
// write widget declarations
105+
for (var element in library.widgets) {
106+
buffer.writeln(_visitWidgetDeclaration(element));
107+
}
108+
return buffer.toString();
109+
}
110+
111+
// visit import
112+
String _visitImport(Import import) => 'import ${import.name};';
113+
114+
// visit widget declaration
115+
String _visitWidgetDeclaration(WidgetDeclaration widget) {
116+
StringBuffer buffer = StringBuffer();
117+
buffer.write('widget ${widget.name}');
118+
119+
if (widget.initialState != null) {
120+
buffer.write(_visitDynamicMap(widget.initialState!));
121+
}
122+
123+
buffer.write(' = ');
124+
buffer.write(_visitObject(widget.root));
125+
buffer.write(';');
126+
return buffer.toString();
127+
}
128+
129+
// visit DynamicMap
130+
String _visitDynamicMap(DynamicMap map, {bool withoutCurlyBraces = false}) {
131+
StringBuffer buffer = StringBuffer();
132+
133+
DynamicMap newMap = map.map((key, value) {
134+
if (value is int && key == 'color') {
135+
return MapEntry(key, int2Color(value));
136+
}
137+
return MapEntry(key, _visitObject(value, dynamicMapKey: key));
138+
});
139+
140+
if (withoutCurlyBraces) {
141+
buffer
142+
.write(newMap.entries.map((e) => '${e.key}: ${e.value}').join(', '));
143+
} else {
144+
buffer.write(newMap);
145+
}
146+
return buffer.toString();
147+
}
148+
149+
// visit DynamicList
150+
String _visitDynamicList(DynamicList list) =>
151+
list.map((e) => _visitObject(e)).toList().toString();
152+
153+
// visit BlobNode
154+
String _visitBlobNode(BlobNode node) {
155+
StringBuffer buffer = StringBuffer();
156+
if (node is ConstructorCall) {
157+
// ConstructorCall ignore arguments' curly braces
158+
buffer.write('${node.name}(');
159+
buffer.write(_visitDynamicMap(node.arguments, withoutCurlyBraces: true));
160+
buffer.write(')');
161+
} else if (node is Switch) {
162+
buffer.write('switch ');
163+
buffer.write(_visitObject(node.input));
164+
buffer.write(' ');
165+
node.outputs.forEach((key, value) {});
166+
// TODO: Can key be another type?
167+
buffer.write(node.outputs.map((key, value) => MapEntry(
168+
key == null ? 'default' : '$key',
169+
_visitObject(value, dynamicMapKey: '$key'))));
170+
} else if (node is EventHandler) {
171+
buffer.write('event "${node.eventName}" ');
172+
buffer.write(_visitDynamicMap(node.eventArguments));
173+
} else {
174+
buffer.write(node.toString());
175+
}
176+
return buffer.toString();
177+
}
178+
179+
// BlobNode, DynamicMap, DynamicList, int, double, bool, String, null
180+
String _visitObject(Object? object, {String? dynamicMapKey}) {
181+
if (object is BlobNode) {
182+
return _visitBlobNode(object);
183+
} else if (object is DynamicMap) {
184+
return _visitDynamicMap(object);
185+
} else if (object is DynamicList) {
186+
if (object.every((element) => element is int) &&
187+
dynamicMapKey == 'colors') {
188+
return object.map((e) => int2Color(e as int)).toList().toString();
189+
}
190+
return _visitDynamicList(object);
191+
}
192+
if (object is String) {
193+
return '"$object"';
194+
} else {
195+
//int, double, bool, null
196+
return '$object';
197+
}
198+
}
199+
200+
String int2Color(int value) {
201+
return '0x${value.toRadixString(16).toUpperCase().toUpperCase()}';
202+
}
203+
}

packages/rfw2txt/pubspec.lock

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -233,10 +233,9 @@ packages:
233233
rfw:
234234
dependency: "direct main"
235235
description:
236-
name: rfw
237-
sha256: ae96afb1c345f53239c5ab3222cff94896df511ca4a53b2fcec5c64678cbb2ff
238-
url: "https://pub.dev"
239-
source: hosted
236+
path: "../../../rfw-1.0.24"
237+
relative: true
238+
source: path
240239
version: "1.0.24"
241240
shelf:
242241
dependency: transitive

packages/rfw2txt/pubspec.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ executables:
1313
dependencies:
1414
args: ^2.4.2
1515
path: ^1.9.0
16-
rfw: ^1.0.24
16+
rfw:
17+
path: ../../../rfw-1.0.24
1718

1819
dev_dependencies:
1920
lints: ^3.0.0

packages/rfw2txt/test/match.rfwtxt

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import core.widgets;
2+
import core.material;
3+
4+
widget Counter = Container(
5+
color: 0xFF66AACC,
6+
child: Center(
7+
child: Button(
8+
child: Padding(
9+
padding: [ 20.0 ],
10+
child: Text(text: data.counter, style: {
11+
fontSize: 56.0,
12+
color: 0xFF000000,
13+
}),
14+
),
15+
onPressed: event "increment" { },
16+
),
17+
),
18+
);
19+
20+
widget Button { down: false } = GestureDetector(
21+
onTap: args.onPressed,
22+
onTapDown: set state.down = true,
23+
onTapUp: set state.down = false,
24+
onTapCancel: set state.down = false,
25+
child: Container(
26+
duration: 50,
27+
margin: switch state.down {
28+
false: [ 0.0, 0.0, 2.0, 2.0 ],
29+
true: [ 2.0, 2.0, 0.0, 0.0 ],
30+
},
31+
padding: [ 12.0, 8.0 ],
32+
decoration: {
33+
type: "shape",
34+
shape: {
35+
type: "stadium",
36+
side: { width: 1.0 },
37+
},
38+
gradient: {
39+
type: "linear",
40+
begin: { x: -0.5, y: -0.25 },
41+
end: { x: 0.0, y: 0.5 },
42+
colors: [ 0xFFFFFF99, 0xFFEEDD00 ],
43+
stops: [ 0.0, 1.0 ],
44+
tileMode: "mirror",
45+
},
46+
shadows: switch state.down {
47+
false: [ { blurRadius: 4.0, spreadRadius: 0.5, offset: { x: 1.0, y: 1.0, } } ],
48+
default: [],
49+
},
50+
},
51+
child: DefaultTextStyle(
52+
style: {
53+
color: 0xFF000000,
54+
fontSize: 32.0,
55+
},
56+
child: args.child,
57+
),
58+
),
59+
);
Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,50 @@
1-
import 'package:test/expect.dart';
2-
import 'package:test/scaffolding.dart';
1+
@TestOn('vm')
2+
import 'dart:convert';
3+
import 'dart:io';
4+
5+
import 'package:rfw/formats.dart';
6+
import 'package:test/test.dart';
7+
import 'package:collection/collection.dart';
38

49
void main() {
5-
test('rfw2txt', () {
6-
expect(1, 2);
10+
test('rfw2txt without output path', () async {
11+
Process process = await Process.start(
12+
'dart', ['run', 'bin/rfw2txt.dart', "test/test.rfw"]);
13+
await process.stdout.transform(utf8.decoder).forEach(print);
14+
await process.stderr.transform(utf8.decoder).forEach(print);
15+
File matchFile = File('test/test.rfw');
16+
File outputTxtFile = File('test.rfwtxt');
17+
File outputFile = File('output.rfw');
18+
outputFile.writeAsBytesSync(
19+
encodeLibraryBlob(parseLibraryFile(outputTxtFile.readAsStringSync())));
20+
// use rfw encoder to convert output test.rfwtxt to test.rfw, then check the file is equal to test/test.rfw
21+
expect(outputFile.existsSync(), true);
22+
expect(
23+
ListEquality()
24+
.equals(matchFile.readAsBytesSync(), matchFile.readAsBytesSync()),
25+
true);
26+
27+
outputFile.delete();
28+
outputTxtFile.delete();
29+
});
30+
31+
test('rfw2txt with output path', () async {
32+
Process process = await Process.start('dart',
33+
['run', 'bin/rfw2txt.dart', "test/test.rfw", "-o", "test.rfwtxt"]);
34+
await process.stdout.transform(utf8.decoder).forEach(print);
35+
await process.stderr.transform(utf8.decoder).forEach(print);
36+
File matchFile = File('test/test.rfw');
37+
File outputTxtFile = File('test.rfwtxt');
38+
File outputFile = File('output.rfw');
39+
outputFile.writeAsBytesSync(
40+
encodeLibraryBlob(parseLibraryFile(outputTxtFile.readAsStringSync())));
41+
expect(outputFile.existsSync(), true);
42+
expect(
43+
ListEquality()
44+
.equals(matchFile.readAsBytesSync(), matchFile.readAsBytesSync()),
45+
true);
46+
47+
outputFile.delete();
48+
outputTxtFile.delete();
749
});
850
}

packages/rfw2txt/test/test.rfw

1.68 KB
Binary file not shown.

0 commit comments

Comments
 (0)