Dart:io stdin raw character codes - dart

I've created a Dart console app and need to process keycodes like Arrow keys and function keys from stdin? The samples I've seen are typically String based :
Stream readLine() => stdin.transform(UTF8.decoder).transform(new LineSplitter());
readLine().listen(processLine);
I modified the above sample hoping to get the raw ints like this:
Stream readInts() => stdin;
readInts().listen(processInts);
void processInts(List<int> kbinput) {
for (int i=0;i<kbinput.length;i++){
print ("kbinput:${kbinput[i]}");
}
}
It seems stdin provides only printable characters and not all ascii keycodes. If it is not possible from stdin, can I create & load a stream within my native extension with the keycodes? How can my console app get to the ascii keycodes of any keypress? Thanks for your help!

One way would be
import 'dart:io' as io;
import 'dart:convert' show UTF8;
void main() {
io.stdin.echoMode = false;
var input;
while(input != 32) { // leave program with [Space][Enter]
input = io.stdin.readByteSync();
if(input != 10) print(input); // ignore [Enter]
}
io.stdin.echoMode = true;
}
but it only returns a value after Enter is pressed.
For one key press it returns from one up to three bytes.
It seems it's not easy to get a keystroke from console without pressing Enter
see Capture characters from standard input without waiting for enter to be pressed for more details.
You could create a native extension that implements the suggested solution in the linked question.

Related

How to setup pager in dart console

It is popular to show output per page at one time when content is huge in many console applications: git log/diff, more/less; but how do I do in a dart programming application?
I find a setup_pager method in git diff source code, but could not figure it out, do I have to do some linux programming? or start an other process to pass output to less command? Thanks!
If it's something simple like the more command then use the console package to get the no of rows for the terminal.
Enter a for loop from 1 to the row count - 1
Print a row of text on each iteration.
Then prompt the user to hit the space key.
When they do, restart the for loop.
Rinse and repeat.
If you want to scroll up then again the console package is you friend.
Similar process but when you prompt the user ask which direction.
If the direction is up then clear the screen and print the prior page of text.
The tricky bit is reading backwards through the file.
Have a look at the File class and the seek method. It will let you move backward in the file but you will have to find the line brakes yourself.
A very crude implementation:
#! /usr/bin/env dcli
// ignore: prefer_relative_imports
import 'dart:math';
import 'package:dcli/dcli.dart';
/// dcli script generated by:
/// dcli create %scriptname%
///
/// See
/// https://pub.dev/packages/dcli#-installing-tab-
///
/// For details on installing dcli.
///
void main(List<String> args) {
// -1 to allow for the 'Hit enter to continue' message
var rows = Terminal().rows - 1;
final lines = read('/var/log/syslog').toList();
rows = min(lines.length, rows);
var shown = 0;
while (shown < lines.length) {
for (var row = 0; row < rows; row++) {
print(lines[shown]);
shown++;
}
ask('Hit enter to continue', required: false);
}
print(orange('Done'));
}

Swift 4 OutputStream produces more output than input

I have been attempting to use streams in swift to interface with a java socket server (I don't believe the java server is my problem) but when I attempt to write with an OutputStream my string includes a bunch of extra garbage that was not in my original string
The code currently looks like this:
var maxWriteLength = 4096
func sendMessage(msg: String) {
let encodedDataArray = [UInt8](msg.utf8)
outputStream.write(encodedDataArray, maxLength: maxWriteLength)
}
However when I give it an input of "hi" it returns an ouput of:
Echo: hi���8B��,rؾ�؇��allowCloudBackup؇��allowAppInstallation؇��safariForceFraudWarning�&��q���ޙTh�C��=wthread��&��q����������������8$��N��8$���0'}��#�
Echo: �'��q����������p�g�iYh�C���iYh�C��
Echo: D�#D�8״
Echo: pV���؇��requireAlphanumeric؇��allowCellularHDUploadsInternational-Key_2��
and much much more
I have seen other posts suggesting that you should use encodedDataArray.count instead of a maxWriteLength however when I have used this the OutputStream will not write anything.
Thanks in advance.
For future people who struggle with this it was indeed the way the server was handling messages (I went back to check it). The problem was that I was using Scanner.nextLine() and had no \n inside of the swift portion of my code. If you are using an array make sure that you add + "\n" to your string before it is made into an array otherwise the bytes for \n will not be written. The final code looked like this:
func sendMessage(msg: String) {
var finalMsg = msg + "\n"
let encodedDataArray = [UInt8](finalMsg.utf8)
outputStream.write(encodedDataArray, maxLength: encodedDataArray.count)
}

how to print a receipt in java label

enter image description herei want to print all the Double variables in a java label. but when i execute the program only Qty1 print in the label.so that i used escape sequences but the also dont work. Could anyone tell me how to fix this.What i really expect to do is something like in the attachment.
Code
JButton receipt = new JButton("Receipt");
receipt.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Double Qty1= Double.parseDouble(textField.getText());
Double Qty2=Double.parseDouble(textField_2.getText());
Double Qty3=Double.parseDouble(textField_3.getText());
lblRecipt.setText("\t\nHotel \n\nManagement System"+Qty1);
// lblRecipt.setText("Hotel Management System"+Qty1);
You can use swing's html formatting feature as explained in https://docs.oracle.com/javase/tutorial/uiswing/components/html.html.
To specify that a component's text has HTML formatting, just put the tag at the beginning of the text, then use any valid HTML in the remainder.
This is what swing example offers:
Your code might look like:
lblRecipt.setText("<html>\t<br>Hotel<br><br>Management System"+Qty1+"</html>");

How to remove non-ascii char from MQ messages with ESQL

CONCLUSION:
For some reason the flow wouldn't let me convert the incoming message to a BLOB by changing the Message Domain property of the Input Node so I added a Reset Content Descriptor node before the Compute Node with the code from the accepted answer. On the line that parses the XML and creates the XMLNSC Child for the message I was getting a 'CHARACTER:Invalid wire format received' error so I took that line out and added another Reset Content Descriptor node after the Compute Node instead. Now it parses and replaces the Unicode characters with spaces. So now it doesn't crash.
Here is the code for the added Compute Node:
CREATE FUNCTION Main() RETURNS BOOLEAN
BEGIN
DECLARE NonPrintable BLOB X'0001020304050607080B0C0E0F101112131415161718191A1B1C1D1E1F7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF1F2F3F4F5F6F7F8F9FAFBFCFDFEFF';
DECLARE Printable BLOB X'20202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020';
DECLARE Fixed BLOB TRANSLATE(InputRoot.BLOB.BLOB, NonPrintable, Printable);
SET OutputRoot = InputRoot;
SET OutputRoot.BLOB.BLOB = Fixed;
RETURN TRUE;
END;
UPDATE:
The message is being parsed as XML using XMLNSC. Thought that would cause a problem, but it does not appear to be.
Now I'm using PHP. I've created a node to plug into the legacy flow. Here's the relevant code:
class fixIncompetence {
function evaluate ($output_assembly,$input_assembly) {
$output_assembly->MRM = $input_assembly->MRM;
$output_assembly->MQMD = $input_assembly->MQMD;
$tmp = htmlentities($input_assembly->MRM->VALUE_TO_FIX, ENT_HTML5|ENT_SUBSTITUTE,'UTF-8');
if (!empty($tmp)) {
$output_assembly->MRM->VALUE_TO_FIX = $tmp;
}
// Ensure there are no null MRM fields. MessageBroker is strict.
foreach ($output_assembly->MRM as $key => $val) {
if (empty($val)) {
$output_assembly->MRM->$key = '';
}
}
}
}
Right now I'm getting a vague error about read only messages, but before that it wasn't working either.
Original Question:
For some reason I am unable to impress upon the senders of our MQ
messages that smart quotes, endashes, emdashes, and such crash our XML
parser.
I managed to make a working solution with SQL queries, but it wasted
too many resources. Here's the last thing I tried, but it didn't work
either:
CREATE FUNCTION CLEAN(IN STR CHAR) RETURNS CHAR BEGIN
SET STR = REPLACE('–',STR,'–');
SET STR = REPLACE('—',STR,'—');
SET STR = REPLACE('·',STR,'·');
SET STR = REPLACE('“',STR,'“');
SET STR = REPLACE('”',STR,'”');
SET STR = REPLACE('‘',STR,'&lsqo;');
SET STR = REPLACE('’',STR,'’');
SET STR = REPLACE('•',STR,'•');
SET STR = REPLACE('°',STR,'°');
RETURN STR;
END;
As you can see I'm not very good at this. I have tried reading about
various ESQL string functions without much success.
So in ESQL you can use the TRANSLATE function.
The following is a snippet I use to clean up a BLOB containing non-ASCII low hex values so that it then be cast into a usable character string.
You should be able to modify it to change your undesired characters into something more benign. Basically each hex value in NonPrintable gets translated into its positional equivalent in Printable, in this case always a full-stop i.e. x'2E' in ASCII. You'll need to make your BLOB's long enough to cover the desired range of hex values.
DECLARE NonPrintable BLOB X'000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F';
DECLARE Printable BLOB X'2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E';
SET WorkBlob = TRANSLATE(WorkBlob, NonPrintable, Printable);
BTW if messages with invalid characters only come in every now and then I'd probably specify BLOB on the input node and then use something similar to the following to invoke the XMLNSC parser.
CREATE LASTCHILD OF OutputRoot DOMAIN 'XMLNSC'
PARSE(InputRoot.BLOB.BLOB CCSID InputRoot.Properties.CodedCharSetId ENCODING InputRoot.Properties.Encoding);
With the exception terminal wired up you can then correct the BLOB's of any messages containing parser breaking invalid characters before attempting to reparse.
Finally my best wishes as I've had a number of battles over the years with being forced to correct invalid message content in the "Integration Layer" after all that's what it's meant to do.

readByteSync - is this behavior correct?

stdin.readByteSync has recently been added to Dart.
Using stdin.readByteSync for data entry, I am attempting to allow a default value and if an entry is made by the operator, to clear the default value. If no entry is made and just enter is pressed, then the default is used.
What appears to be happening however is that no terminal output is sent to the terminal until a newline character is entered. Therefore when I do a print() or a stdout.write(), it is delayed until newline is entered.
Therefore, when operator enters first character to override default, the default is not cleared. IE. The default is "abc", data entered is "xx", however "xxc" is showing on screen after entry of "xx". The "problem" appears to be that no "writes" to the terminal are sent until newline is entered.
While I can find an alternative way of doing this, I would like to know if this is the way readByteSync should or must work. If so, I’ll find an alternative way of doing what I want.
// Example program //
import 'dart:io';
void main () {
int iInput;
List<int> lCharCodes = [];
print(""); print("");
String sDefault = "abc";
stdout.write ("Enter data : $sDefault\b\b\b");
while (iInput != 10) { // wait for newline
iInput = stdin.readByteSync();
if (iInput == 8 && lCharCodes.length > 0) { // bs
lCharCodes.removeLast();
} else if (iInput > 31) { // ascii printable char
lCharCodes.add(iInput);
if (lCharCodes.length == 1)
stdout.write (" \b\b\b\b chars cleared"); // clear line
print ("\nlCharCodes length = ${lCharCodes.length}");
}
}
print ("\nData entered = ${new String.fromCharCodes(lCharCodes).trim()}");
}
Results on Command screen are :
c:\Users\Brian\dart-dev1\test\bin>dart testsync001.dart
Enter data : xxc
chars cleared
lCharCodes length = 1
lCharCodes length = 2
Data entered = xx
c:\Users\Brian\dart-dev1\test\bin>
I recently added stdin.readByteSync and readLineSync, to easier create small scrips reading the stdin. However, two things are still missing, for this to be feature-complete.
1) Line mode vs Raw mode. This is basically what you are asking for, a way to get a char as soon as it's printed.
2) Echo on/off. This mode is useful for e.g. typing in passwords, so you can disable the default echo of the characters.
I hope to be able to implement and land these features rather soon.
You can star this bug to track the development of it!
This is common behavior for consoles. Try to flush the output with stdout.flush().
Edit: my mistake. I looked at a very old revision (dartlang-test). The current API does not provide any means to flush stdout. Feel free to file a bug.

Resources