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'));
}
Related
I am writing a Flutter application using the BLOC pattern. I'm currently trying to search a database and return a list of results on the screen.
The first search will complete fine. The issue is when I hit the back button and try to do a second search. The first search results aren't cleared out. Instead they remain on the screen and the new search results are placed below them.
In a nutshell here's what I'm doing.(I'm using the RxDart library)
1.) Defining input and output streams:
PublishSubject<SearchRowModel> _searchFetcher =
PublishSubject<BibSearchRowModel>();
BehaviorSubject<Map<int, SearchRowModel>> _searchOutput =
BehaviorSubject<Map<int, SearchRowModel>>();
2.) Piping the streams together in the class constructor.
_searchFetcher.stream.transform(_resultsTransformer()).pipe(_searchOutput);
3.) Adding the results to the fetcher stream
results.searchRows.forEach((SearchRowModel row) {
_searchFetcher.sink.add(row);
});
4.) Using a ScanStreamTransformer to create a map of the results.
_resultsTransformer() {
return ScanStreamTransformer(
(Map<int, SearchRowModel> cache, SearchRowModel row, index) {
cache[index] = row;
return cache;
},
<int, SearchRowModel>{},
);
}
From my debugging, I've found that the code in step 4 appears to be the issue. That cache (or the Accumulator) isn't getting reset between searches. It just keeps adding additional results to the map.
I've yet to find a way of resetting the map in the accumulator / cache that works. I even tried completely destroying the streams and recreating them, but the original search data in the SearchstreamTransformer accumulator still persisted.
Is it even possible to have a slide presentation delete a slide base off of a date. For example have the slide expire after a certain date. The purpose is for digital signage. I was just hoping to write a script that deleted a slide.
Please let me know if my question is not clear.
first post #not a programmer...yet
I think you want to do a cron. Cron is time-based job scheduler, to run periodically at fixed times, dates, or intervals.
One sample would be using a time-driven trigger to run a function (delete slide).
The code snippet that I used would be in Apps Script to run using a time driven trigger and code to delete a page in a slide.
function checkslide(){
var origin = Slides.Presentations.get(originSlideID).slides;
Logger.log(origin[1])
var slide = SlidesApp.openById(targetSlideID).getSlides();
//remove all slide other than first page
slide.splice(targetSlideID - 1, 1);
for (var i in slide) {
slide[i].remove();
}
//remove a specify depending on condition where j is the slide to be removed
for (i = 0; i < slide.length; i++) {
if(i == j){
slide[i].remove();
}
}
}
References:
https://developers.google.com/slides/samples/writing#delete_a_page_or_page_element
https://developers.google.com/apps-script/guides/triggers/installable
I'm trying to take a set of names with check boxes next to them and make a system so that you can check some of the names (mark them as "True") and click a button. It would then increment +1 the value next to the names of the people marked true.
Here is a link to a sample sheet:
https://docs.google.com/spreadsheets/d/1gf-BrXXR0cAYCn7bMkvvK65R290NXbP9D6aA68c06C8/edit?usp=sharing
If column A, row 2 (Tim's row) is marked true, I want to increment the value in column C, row 2 by one, so Tim would have a running total of tardies next to his name.
I hope this is do-able. Thanks!
(Now I know what you're trying to get)
In order to increment a value via the press of a button, as far as I know you have to use scripts (Tools -> Script Editor). Here's something I threw together:
// editCell takes the cell to edit and it's new value
function editCell(cellName, value) {
SpreadsheetApp.getActiveSheet().getRange(cellName).setValue(value);
}
// getCell takes the cell's value and returns it
function getCell(cellName) {
return SpreadsheetApp.getActiveSheet().getRange(cellName).getValue();
}
// plusOne adds one to the field supplied. It's linked to the button in the sheet
function plusOne() {
editCell("C2",getCell("C2")+1);
}
In order to make it work, you may need to change the targeted Cell (currently C2). You'll also need to create a drawing (Insert -> Drawing) which will act as the button you'll be able to press. Once inserted, click on the three dots on it and click on Link Script. Type in plusOne. When executing it the first time, it'll ask you to authenticate the use of scripts.
That should do the trick. I hope you have some understanding of Java Script though (to modify the code to your needs optimally).
Edit - Expandable version
So, to make every number behind a ticked field increase by one, you can use this version of the code:
// Adds one to every field within "AddArea" that has a tick in front of it. It's linked to the button in the sheet.
function plusOne() {
var ss = SpreadsheetApp.getActiveSheet();
var range = ss.getRange("AddArea");
var values = range.getValues();
var newValues = [];
for (var i = 0; i < range.getNumRows(); ++i) {
var row = values[i];
if(row[0]) {
newValues.push([true, row[1]+1]);
}
else {
newValues.push([false, row[1]]);
}
}
range.setValues(newValues);
}
You need to define a custom named area, named "AddArea" (Data -> Labeled Areas [or similar]), link the script to a button and allow the script to be run. This was hard but very fun to figure out.
Example Sheet for reference (updated)
Can be achieved with just, for example for C2:
=A2+C2
but you would need to turn on iterative calculation (File > Spreadsheet settings... > Calculation [Max. 1 is adequate]) and I would not really recommend that over a trigger with Google Apps Script.
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.
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.