CodeMirror is not updated source on change - rascal

I am creating a salix webapp and I am trying to use codeMirror as per the salix examples.
I am unable to execute the codeMirror example in the salix.demo.basic, even though I can easily execute all the other examples in basic, so I'm wondering if anything has changed since these were written.
The code I am using:
module salix::demo::basic::CodeMirror
import salix::HTML;
import salix::App;
import salix::lib::CodeMirror;
import IO;
alias Model = tuple[list[Msg] changes, str src];
SalixApp[str] cmApp(str id = "root") = makeApp(id, init, view, update, parser=parseMsg);
App[str] cmWebApp()
= webApp(
cmApp(),
|project://projectName/src/salix/demo/basic/index.html|,
|project://projectName/src|
);
Model init()
= <[], "function hello() {\n console.log(\'Hello world\');\n}">;
data Msg
= myChange(int, int, int, int, str, str)
;
Model update(Msg msg, Model model) {
switch (msg) {
case m:myChange(int _, int _, int _, int _, str _, str _):{
println("Update called");
model.changes += [m];
}
}
return model;
}
void view(Model model) {
div(() {
h2("Code Mirror demo");
div(() {
codeMirror("cm", style(("height": "auto")), onChange(myChange),
mode("javascript"), lineNumbers(true), \value(model.src));
});
for (Msg m <- model.changes) {
text(m);
text("; ");
}
});
}
In my app I have managed to display the codeMirror example as so:
codeMirror("cm", onChange(cmChange), style(("height": "50%")),
lineNumbers(true), \value(model.projectViewInfo.src), lineWrapping(true), class("cm-s-3024-night"));
but the change message is never sent (cmChange) and the source is never updated. So it is partially working for me.
This example can also be found in the salix library
https://github.com/usethesource/salix/tree/master/src/salix/demo/basic

Related

Reading a file in dart and split the string has different results in console that in vscode

I'm new in dart, I'm trying to read information from a txt file and use the data to create objects from a class (in this case about pokemon), but when I run my program in the terminal it doesn't prints the correct information, and when I run the program in vscode (whit the dart extension, the "run" button) it prints in the debug console the correct information. What is the problem?
When I run the program in vscode I get in my print method (printP) this (which is what I want)
vscode:
Print method:
1+: Bulbasaur GRASS | POISON
but when I run the program in the terminal I get this.
Terminal:
Print method:
| POISONsaur
Here is the dart code.
main.dart
import 'dart:io';
import 'pokemon.dart';
void main() {
var file = new File("/home/ariel/Documents/script/pokemon.txt");
String str = file.readAsStringSync();
var pokes = str.split("[");
pokes = pokes.sublist(1, pokes.length);
getPokemon(pokes[0]).printP();
}
Pokemon getPokemon(String str) {
Pokemon p = new Pokemon();
print("string: " + str);
var aux = str.split("\n");
print(aux.length);
for (var i in aux) {
print("line: " + i);
}
p.number = int.parse(aux[0].split("]")[0]);
p.name = aux[1].split("=")[1];
p.type1 = aux[3].split("=")[1];
p.type2 = aux[4].split("=")[1];
return p;
}
pokemon.dart
class Pokemon {
String _name, _type1, _type2;
int _number;
Pokemon() {
this._name = "";
this._number = 0;
this._type1 = "";
this._type2 = "";
}
void printP() {
print("Print method:");
print("${this._number}+: ${this._name} ${this._type1} | ${this._type2}");
}
void set number(int n) {
this._number = n;
}
void set name(String nm) {
this._name = nm;
}
void set type1(String t) {
this._type1 = t;
}
void set type2(String t) {
this._type2 = t;
}
}
And here is the txt file
pokemon.txt
[1]
Name=Bulbasaur
InternalName=BULBASAUR
Type1=GRASS
Type2=POISON
BaseStats=45,49,49,45,65,65
GenderRate=FemaleOneEighth
GrowthRate=Parabolic
BaseEXP=64
EffortPoints=0,0,0,0,1,0
Rareness=45
Happiness=70
Abilities=OVERGROW
HiddenAbility=CHLOROPHYLL
Moves=1,TACKLE,3,GROWL,7,LEECHSEED,9,VINEWHIP,13,POISONPOWDER,13,SLEEPPOWDER,15,TAKEDOWN,19,RAZORLEAF,21,SWEETSCENT,25,GROWTH,27,DOUBLEEDGE,31,WORRYSEED,33,SYNTHESIS,37,SEEDBOMB
EggMoves=AMNESIA,CHARM,CURSE,ENDURE,GIGADRAIN,GRASSWHISTLE,INGRAIN,LEAFSTORM,MAGICALLEAF,NATUREPOWER,PETALDANCE,POWERWHIP,SKULLBASH,SLUDGE
Compatibility=Monster,Grass
StepsToHatch=5355
Height=0.7
Weight=6.9
Color=Green
Habitat=Grassland
Kind=Seed
Pokedex=Almacena energía en el bulbo de su espalda para alimentarse durante épocas de escasez de recursos o para atacar liberándola de golpe.
BattlerPlayerY=0
BattlerEnemyY=25
BattlerAltitude=0
Evolutions=IVYSAUR,Level,16
Your code are dependent on the newline format of your txt file. I will recommend you are using the LineSplitter class from dart:convert to split your lines.
The problem is that Windows newlines contains both '\n' and '\r' but you are only removing the '\n' part. '\r' are essential meaning the terminal should set the cursor back to the beginning of the line.
You can read this like a typewriter where you first move the head back and set move the paper to the next line. And can read a lot more about is topic here: https://en.wikipedia.org/wiki/Newline
The purpose of the LineSplitter class is to abstract all of this logic and get some behavior which will work on all platforms.
So import dart:convert and change this line:
var aux = str.split("\n");
Into:
var aux = LineSplitter.split(str).toList();

Recover single asset history

I'm trying to recover the history of a single asset. The model is defined like the following
namespace org.example.basic
asset SampleAsset identified by assetId {
o String assetId
--> SampleParticipant owner
o String value
}
participant SampleParticipant identified by participantId {
o String participantId
o String firstName
o String lastName
}
transaction GetAssetHistory {
o String assetId
}
event SampleEvent {
--> SampleAsset asset
o String oldValue
o String newValue
}
I generate a single participant and a new asset referencing to the previous participant. And I proceed to update the asset value variable value. But reading about asset update I found the following:
async function getAssetHistory(tx) {
//How can I get a single asset history using the tx.assetId value??
let historian = await businessNetworkConnection.getHistorian();
let historianRecords = historian.getAll();
console.log(prettyoutput(historianRecords));
}
When I deploy the bna and I call the function I get the following:
img
In other functions i use the RuntimeApi but I dont know if businessNetworkConnection is a Runtime API call.
Any idea of how can a get a single asset history?
Any example on internet?
***************** UPDATE
I change the way to recover a particula asset history. Doing the following:
In js file
/**
* Sample read-only transaction
* #param {org.example.trading.MyPartHistory} tx
* #returns {org.example.trading.Trader[]} All trxns
* #transaction
*/
async function participantHistory(tx) {
console.log('1');
const partId = tx.tradeid;
console.log('2');
const nativeSupport = tx.nativeSupport;
// const partRegistry = await getParticipantRegistry('org.example.trading.Trader')
console.log('3');
const nativeKey = getNativeAPI().createCompositeKey('Asset:org.example.trading.Trader', [partId]);
console.log('4');
const iterator = await getNativeAPI().getHistoryForKey(nativeKey);
let results = [];
let res = {done : false};
while (!res.done) {
res = await iterator.next();
if (res && res.value && res.value.value) {
let val = res.value.value.toString('utf8');
if (val.length > 0) {
console.log("#debug val is " + val );
results.push(JSON.parse(val));
}
}
if (res && res.done) {
try {
iterator.close();
}
catch (err) {
}
}
}
var newArray = [];
for (const item of results) {
newArray.push(getSerializer().fromJSON(item));
}
console.log("#debug the results to be returned are as follows: ");
return newArray; // returns something to my NodeJS client (called via REST API)
}
In model file
#commit(false)
#returns(Trader[])
transaction MyPartHistory {
o String tradeId
}
I create a single asset an di update then with other values. But whe I call the MyPartHistory i get the following message:
Error: Native API not available in web runtime
use of the native api is only available when you are running your business network in a real fabric environment. You can't use it in the online playground environment. You will have to setup a real fabric environment and then run playground locally connecting to that fabric in order to test your business network.

async Future StreamSubscription Error

Could someone please explain what's wrong with the following code. I'm making two calls to the function fInputData. The first works ok, the second results in an error :
"unhandled exception"
"Bad state: Stream already has subscriber"
I need to write a test console program that inputs multiple parameters.
import "dart:async" as async;
import "dart:io";
void main() {
fInputData ("Enter Nr of Iterations : ")
.then((String sResult){
int iIters;
try {
iIters = int.parse(sResult);
if (iIters < 0) throw new Exception("Invalid");
} catch (oError) {
print ("Invalid entry");
exit(1);
}
print ("In Main : Iterations selected = ${iIters}");
fInputData("Continue Processing? (Y/N) : ") // this call bombs
.then((String sInput){
if (sInput != "y" && sInput != "Y")
exit(1);
fProcessData(iIters);
print ("Main Completed");
});
});
}
async.Future<String> fInputData(String sPrompt) {
async.Completer<String> oCompleter = new async.Completer();
stdout.write(sPrompt);
async.Stream<String> oStream = stdin.transform(new StringDecoder());
async.StreamSubscription oSub;
oSub = oStream.listen((String sInput) {
oCompleter.complete(sInput);
oSub.cancel();
});
return oCompleter.future;
}
void fProcessData(int iIters) {
print ("In fProcessData");
print ("iIters = ${iIters}");
for (int iPos = 1; iPos <= iIters; iPos++ ) {
if (iPos%100 == 0) print ("Processed = ${iPos}");
}
print ("In fProcessData - completed ${iIters}");
}
Some background reading:
Streams comes in two flavours: single or multiple (also known as
broadcast) subscriber. By default, our stream is a single-subscriber
stream. This means that if you try to listen to the stream more than
once, you will get an exception, and using any of the callback
functions or future properties counts as listening.
You can convert the single-subscriber stream into a broadcast stream
by using the asBroadcastStream() method.
So you've got two options - either re-use a single subscription object. i.e. call listen once, and keep the subscription object alive.
Or use a broadcast stream - note there are a number of differences between broadcast streams and single-subscriber streams, you'll need to read about those and make sure they suit your use-case.
Here's an example of reusing a subscriber to ask multiple questions:
import 'dart:async';
import 'dart:io';
main() {
var console = new Console();
var loop;
loop = () => ask(console).then((_) => loop());
loop();
}
Future ask(Console console) {
print('1 + 1 = ...');
return console.readLine().then((line) {
print(line.trim() == '2' ? 'Yup!' : 'Nope :(');
});
}
class Console {
StreamSubscription<String> _subs;
Console() {
var input = stdin
.transform(new StringDecoder())
.transform(new LineTransformer());
_subs = input.listen(null);
}
Future<String> readLine() {
var completer = new Completer<String>();
_subs.onData(completer.complete);
return completer.future;
}
}

JS-Interop : Attempting to use salesforce proxy

I'm trying to use Salesforce's sforce library to place an Ajax call to salesforce. Here is the example javascript that is working:
function setupPage() {
var state = { //state that you need when the callback is called
output : document.getElementById("output"),
startTime : new Date().getTime()};
var callback = {
//call layoutResult if the request is successful
onSuccess: layoutResults,
//call queryFailed if the api request fails
onFailure: queryFailed,
source: state};
sforce.connection.query(
"Select Id, Name, Industry From Account order by Industry",
callback);
}
function queryFailed(error, source) {
// not shown function code
}
function layoutResults(queryResult, source) {
// not shown function code
}
Here's my dart implementation:
import 'dart:html';
import 'package:js/js.dart' as js;
import 'dart:json';
void main() {
js.scoped(() {
var sforce = js.context.sforce;
var callbackSuccess = new js.Callback.once(success);
var callbackFailed = new js.Callback.once(failure);
var sfdc = new js.Proxy(sforce.connection.query("Select Id, Name, Industry From Account order by Industry"),
js.map({"onSuccess" : callbackSuccess, "onFailure" : callbackFailed}));
});
}
void success(queryResult) {
print("queryResult is: " + queryResult);
}
void failure(error) {
print("error is: " + error);
}
The Ajax call is being placed, as I see the POST request being made and returning data. However, I always seem to get this error (and I've tried countless different combinations):
Uncaught TypeError: object is not a function (program):370
construct (program):370
ReceivePortSync.dispatchCall darttest:178
$$._JsSendPortSync.callSync$1 minidartjs:4929
$.Proxy_Proxy$withArgList minidartjs:8194
$.Proxy_Proxy minidartjs:8183
$$.main_anon.call$0 minidartjs:6057
$.scoped minidartjs:8136
$.main minidartjs:8066
$$._IsolateContext.eval$1 minidartjs:276
$.startRootIsolate minidartjs:6533
(anonymous function)
Any help would be greatly appreciated, as I'm not sure where to turn at this point.
You get this error because you try to create a js.Proxy (sfdc) with the result of sforce.connection.query(...) . When you use new js.Proxy(f), f must be a js.Proxy of a js function. Here you get an object and that's why you get the error.
Here's the code that should work.
import 'dart:html';
import 'package:js/js.dart' as js;
import 'dart:json';
void main() {
js.scoped(() {
var sforce = js.context.sforce;
var callbackSuccess = new js.Callback.once(success);
var callbackFailed = new js.Callback.once(failure);
sforce.connection.query("Select Id, Name, Industry From Account order by Industry",
js.map({"onSuccess" : callbackSuccess, "onFailure" : callbackFailed}));
});
}
void success(queryResult, source) {
print("queryResult is: " + queryResult);
}
void failure(error, source) {
print("error is: " + error);
}

Writing a list of strings to a file

From the API page, I gather there's no function for what I'm trying to do. I want to read text from a file storing it as a list of strings, manipulate the text, and save the file. The first part is easy using the function:
abstract List<String> readAsLinesSync([Encoding encoding = Encoding.UTF_8])
However, there is no function that let's me write the contents of the list directly to the file e.g.
abstract void writeAsLinesSync(List<String> contents, [Encoding encoding = Encoding.UTF_8, FileMode mode = FileMode.WRITE])
Instead, I've been using:
abstract void writeAsStringSync(String contents, [Encoding encoding = Encoding.UTF_8, FileMode mode = FileMode.WRITE])
by reducing the list to a single string. I'm sure I could also use a for loop and feed to a stream line by line. I was wondering two things:
Is there a way to just hand the file a list of strings for writing?
Why is there a readAsLinesSync but no writeAsLinesSync? Is this an oversight or a design decision?
Thanks
I just made my own export class that handles writes to a file or for sending the data to a websocket.
Usage:
exportToWeb(mapOrList, 'local', 8080);
exportToFile(mapOrList, 'local/data/data.txt');
Class:
//Save data to a file.
void exportToFile(var data, String filename) =>
new _Export(data).toFile(filename);
//Send data to a websocket.
void exportToWeb(var data, String host, int port) =>
new _Export(data).toWeb(host, port);
class _Export {
HashMap mapData;
List listData;
bool isMap = false;
bool isComplex = false;
_Export(var data) {
// Check is input is List of Map data structure.
if (data.runtimeType == HashMap) {
isMap = true;
mapData = data;
} else if (data.runtimeType == List) {
listData = data;
if (data.every((element) => element is Complex)) {
isComplex = true;
}
} else {
throw new ArgumentError("input data is not valid.");
}
}
// Save to a file using an IOSink. Handles Map, List and List<Complex>.
void toFile(String filename) {
List<String> tokens = filename.split(new RegExp(r'\.(?=[^.]+$)'));
if (tokens.length == 1) tokens.add('txt');
if (isMap) {
mapData.forEach((k, v) {
File fileHandle = new File('${tokens[0]}_k$k.${tokens[1]}');
IOSink dataFile = fileHandle.openWrite();
for (var i = 0; i < mapData[k].length; i++) {
dataFile.write('${mapData[k][i].real}\t'
'${mapData[k][i].imag}\n');
}
dataFile.close();
});
} else {
File fileHandle = new File('${tokens[0]}_data.${tokens[1]}');
IOSink dataFile = fileHandle.openWrite();
if (isComplex) {
for (var i = 0; i < listData.length; i++) {
listData[i] = listData[i].cround2;
dataFile.write("${listData[i].real}\t${listData[i].imag}\n");
}
} else {
for (var i = 0; i < listData.length; i++) {
dataFile.write('${listData[i]}\n');
}
}
dataFile.close();
}
}
// Set up a websocket to send data to a client.
void toWeb(String host, int port) {
//connect with ws://localhost:8080/ws
//for echo - http://www.websocket.org/echo.html
if (host == 'local') host = '127.0.0.1';
HttpServer.bind(host, port).then((server) {
server.transform(new WebSocketTransformer()).listen((WebSocket webSocket) {
webSocket.listen((message) {
var msg = json.parse(message);
print("Received the following message: \n"
"${msg["request"]}\n${msg["date"]}");
if (isMap) {
webSocket.send(json.stringify(mapData));
} else {
if (isComplex) {
List real = new List(listData.length);
List imag = new List(listData.length);
for (var i = 0; i < listData.length; i++) {
listData[i] = listData[i].cround2;
real[i] = listData[i].real;
imag[i] = listData[i].imag;
}
webSocket.send(json.stringify({"real": real, "imag": imag}));
} else {
webSocket.send(json.stringify({"real": listData, "imag": null}));
}
}
},
onDone: () {
print('Connection closed by client: Status - ${webSocket.closeCode}'
' : Reason - ${webSocket.closeReason}');
server.close();
});
});
});
}
}
I asked Mads Agers about this. He works on the io module. He said that he decided not to add writeAsLines because he didn't find it useful. For one it is trivial to write the for loop and the other thing is that you have to parameterize it which the kind of line separator that you want to use. He said he can add it if there is a strong feeling that it would be valuable. He didn't immediately see a lot of value in it.

Resources