Skip to content

Instantly share code, notes, and snippets.

@Wetbikeboy2500
Last active May 19, 2021 07:17
Show Gist options
  • Select an option

  • Save Wetbikeboy2500/548e579e2ff222d669b24c1e99ef3dfb to your computer and use it in GitHub Desktop.

Select an option

Save Wetbikeboy2500/548e579e2ff222d669b24c1e99ef3dfb to your computer and use it in GitHub Desktop.
Allow asynchronous external functions by callback for Hetu-Script 0.0.6
import 'dart:async';
import 'dart:io';
//http: ^0.13.0
import 'package:http/http.dart' as http;
//html: ^0.15.0
import 'package:html/parser.dart' as parser show parse;
//path: ^1.8.0
import 'package:path/path.dart' as p;
//hetu_script: ^0.0.6
import 'package:hetu_script/hetu_script.dart';
void main(List<String> arguments) async {
//Directory for where your .ht scripts are
String workingDirectory = Directory('bin').path;
//make a full path to script we want to run
String path = p.join(workingDirectory, 'test.ht');
HTAstInterpreter hetu = HTAstInterpreter(importHandler: DefaultImportHandler(workingDirectory: Directory('bin').path));
await hetu.init(
externalFunctions: {
'querySelector': (List<dynamic> positionalArgs, Map<String, dynamic> namedArgs) {
var doc = positionalArgs[0];
return doc.querySelector(positionalArgs[1] as String);
},
'getText': (List<dynamic> positionalArgs, Map<String, dynamic> namedArgs) {
var elm = positionalArgs[0];
return elm.text;
},
'fetchHtml': (List<dynamic> positionalArgs, Map<String, dynamic> namedArgs) {
return http.get(Uri.parse(positionalArgs[0]));
},
'parseBody': (List<dynamic> positionalArgs, Map<String, dynamic> namedArgs) {
return parser.parse(positionalArgs[0].body);
}
},
);
await hetu.eval(File(path).readAsStringSync());
//We want to setup a recursive function that will keep resolving futures until we get the final result
//Add "late" before declaring eval to make this null-safe
Future Function(String, List<dynamic>) eval;
eval = (name, args) async {
var response = hetu.invoke(
name,
positionalArgs: args,
);
if (response is Map) {
//require a map with a target and data
if (response.containsKey('target') && response.containsKey('data')) {
List next_data = [];
if (response['data'] is List) {
//iterates and awaits for anything passed by the list
for (var data in response['data']) {
next_data.add(await data);
}
} else {
next_data.add(await response['data']);
}
return await eval(response['target'], next_data);
}
}
return response;
};
//Entry call to the script
var info = await eval('main', []);
print(info);
}
external fun querySelector
external fun getText
external fun parseBody
external fun fetchHtml: Future
fun main() {
//async call that will trigger another script
return {
"data": fetchHtml('https://duckduckgo.com/'),
"target": 'getGoogle',
}
//or (produces the same result but displays how multiple futures can be put in the data list)
return getGoogle(fetchHtml('https://duckduckgo.com/'))
}
fun getGoogle (request) {
return {
"data": [fetchHtml('https://www.google.com/'), request],
"target": 'getTitle',
}
}
fun getTitle (google, duckduckgo): String {
print('get title google')
var doc = parseBody(google)
var elm = querySelector(doc, 'title')
print(getText(elm))
print('get title duckduckgo')
var doc = parseBody(duckduckgo)
var elm = querySelector(doc, 'title')
print(getText(elm))
return 'success'
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment