How to split multiple terminals in a single window - html

I've a single screen terminal as shown in screenshot single screen terminal,
I want to split the terminal screen in multiple part as shown in screenshot Muti screen terminal view.
Note: I've also created single terminal using(javascript, html , css and ruby on rails) but how can do to split single terminal into multiple terminals in a single window.
used javascript-
var Terminal = Terminal || {};
var Command = Command || {};
// Note: The file system has been prefixed as of Google Chrome 12:
window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
/**
* Terminal Events
*/to split single terminal into multiple terminals in a single window
var command_list = []
Terminal.Events = function(inputElement, OutputElement) {
// Set Root Pointer
window.requestFileSystem(window.TEMPORARY, 1024*1024, function(fs) {Terminal.Filesystem.pwd = fs.root}, Terminal.FilesystemErrorHandler);
// Sets
vato split single terminal into multiple terminals in a single windowr input = document.getElementById(inputElement);
var body = document.getElementsByTagName('body');
var count = 0;
// Input Keypress
input.onkeydown = function(event) {
// up down arrow
if (event.which == 38 || event.keyCode == 38){
if (count < command_list.length){
count += 1
}
if (command_list) {
var l = command_list.length - count
console.log(l)
command_list[l] != undefined ? $('#cmdline').val(command_list[l]) : $('#cmdline').val("")
}
// for up arrow
} else if(event.which == 40 || event.keyCode == 40) {
if (count > 0){
count -= 1
}
if (command_list) {
var l = command_list.length - count
console.log(l)
command_list[l] != undefined ? $('#cmdline').val(command_list[l]) : $('#cmdline').val("")
}
}
I want to split single terminal into multiple terminals in a single window.

Related

xpath in apps script?

I made a formula to extract some Wikipedia data in Google Seets which works fine. Here is the formula:
=regexreplace(join("",flatten(IMPORTXML(D2,".//p[preceding-sibling::h2[1][contains(., 'Geography')]]"))),"\[[^\]]+\]","")&char(10)&char(10)&iferror(regexreplace(join("",flatten(IMPORTXML(D2,".//p[preceding-sibling::h2[1][contains(., 'Education')]]"))),"\[[^\]]+\]",""))
Where D2 is a URL like https://en.wikipedia.org/wiki/Abbeville,_Alabama
This extracts some Geography and Education data from the Wikipedia page. Trouble is that importxml only runs a few times before it dies due to quota.
So I thought maybe better to use Apps Script where there are much higher limits on fetching and parsing. I could not see a good way however of using Xpath in Apps Script. Older posts on the web discuss using a deprecated service called Xml but it seems to no longer work. There is a Service called XmlService which looks like it may do the job but you can't just plug in an Xpath. It looks like a lot of sweating to get to the result. Any solutions out there where you can just plug in Xpath?
Here is an alternative solution I actually do in a case like this.
I have used XmlService but only for parsing the content, not for using Xpath. This makes use of the element tags and so far pretty consistent on my tests. Although, it might need tweaks when certain tags are in the result and you might have to include them into the exclusion condition.
Tested the code below in both links:
https://en.wikipedia.org/wiki/Abbeville,_Alabama#Geography
https://en.wikipedia.org/wiki/Montgomery,_Alabama#Education
My test shows that the formula above used did not return the proper output from the 2nd link while the code does. (Maybe because it was too long)
Code:
function getGeoAndEdu(path) {
var data = UrlFetchApp.fetch(path).getContentText();
// wikipedia is divided into sections, if output is cut, increase the number
var regex = /.{1,100000}/g;
var results = [];
// flag to determine if matches should be added
var foundFlag = false;
do {
m = regex.exec(data);
if (foundFlag) {
// if another header is found during generation of data, stop appending the matches
if (matchTag(m[0], "<h2>"))
foundFlag = false;
// exclude tables, sub-headers and divs containing image description
else if(matchTag(m[0], "<div") || matchTag(m[0], "<h3") ||
matchTag(m[0], "<td") || matchTag(m[0], "<th"))
continue;
else
results.push(m[0]);
}
// start capturing if either IDs are found
if (m != null && (matchTag(m[0], "id=\"Geography\"") ||
matchTag(m[0], "id=\"Education\""))) {
foundFlag = true;
}
} while (m);
var output = results.map(function (str) {
// clean tags for XmlService
str = str.replace(/<[^>]*>/g, '').trim();
decode = XmlService.parse('<d>' + str + '</d>')
// convert html entity codes (e.g.  ) to text
return decode.getRootElement().getText();
// filter blank results due to cleaning and empty sections
// separate data and remove citations before returning output
}).filter(result => result.trim().length > 1).join("\n").replace(/\[\d+\]/g, '');
return output;
}
// check if tag is found in string
function matchTag(string, tag) {
var regex = RegExp(tag);
return string.match(regex) && string.match(regex)[0] == tag;
}
Output:
Difference:
Formula ending output
Script ending output
Education ending in wikipedia
Note:
You still have quota when using UrlFetchApp but should be better than IMPORTXML's limit depending on the type of your account.
Reference:
Apps Script Quotas
Sorry I got very busy this week so I didn't reply. I took a look at your answer which seems to work fine, but it was quite code heavy. I wanted something I would understand so I coded my own solution. not that mine is any simpler. It's just my own code so it's easier for me to follow:
function getTextBetweenTags(html, paramatersInFirstTag, paramatersInLastTag) { //finds text values between 2 tags and removes internal tags to leave plain text.
//eg getTextBetweenTags(html,[['class="mw-headline"'],['id="Geography"']],[['class="wikitable mw-collapsible mw-made-collapsible"']])
// **Note: you may want to replace &#number; with ascII number
var openingTagPos = null;
var closingTagPos = null;
var previousChar = '';
var readingTag = false;
var newTag = '';
var tagEnd = false;
var regexFirstTagParams = [];
var regexLastTagParams = [];
//prepare regexes to test for parameters in opening and closing tags. put regexes in arrays so each condition can be tested separately
for (var i in paramatersInFirstTag) {
regexFirstTagParams.push(new RegExp(escapeRegex(paramatersInFirstTag[i][0])))
}
for (var i in paramatersInLastTag) {
regexLastTagParams.push(new RegExp(escapeRegex(paramatersInLastTag[i][0])))
}
var startTagIndex = null;
var endTagIndex = null;
var matches = 0;
for (var i = 0; i < html.length - 1; i++) {
var nextChar = html.substr(i, 1);
if (nextChar == '<' && previousChar != '\\') {
readingTag = true;
}
if (nextChar == '>' && previousChar != '\\') { //if end of tag found, check tag matches start or end tag
readingTag = false;
newTag += nextChar;
//test for firstTag
if (startTagIndex == null) {
var alltestsPass = true;
for (var j in regexFirstTagParams) {
if (!regexFirstTagParams[j].test(newTag)) alltestsPass = false;
}
if (alltestsPass) {
startTagIndex = i + 1;
//console.log('Start Tag',startTagIndex)
matches++;
}
}
//test for lastTag
else if (startTagIndex != null) {
var alltestsPass = true;
for (var j in regexLastTagParams) {
if (!regexLastTagParams[j].test(newTag)) alltestsPass = false;
}
if (alltestsPass) {
endTagIndex = i + 1;
matches++;
}
}
if(startTagIndex && endTagIndex) break;
newTag = '';
}
if (readingTag) newTag += nextChar;
previousChar = nextChar;
}
if (matches < 2) return 'No matches';
else return html.substring(startTagIndex, endTagIndex).replace(/<[^>]+>/g, '');
}
function escapeRegex(string) {
if (string == null) return string;
return string.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
}
My function requires an array of attributes for the start tag and an array of attributes for the end tag. It gets any text in between and removes any tags found inbetween. One issue I also noticed was there were often special characters (eg  ) so they need to be replaced. I did that outside the scope of the function above.
The function could be easily improved to check the tag type (eg h2), but it wasn't necessary for the wikipedia case.
Here is a function where I called the above function. the html variable is just the result of UrlFetchApp.fetch('some wikipedia city url').getContextText();
function getWikiTexts(html) {
var geography = getTextBetweenTags(html, [['class="mw-headline"'], ['id="Geography']], [['class="mw-headline"']]);
var economy = getTextBetweenTags(html, 'span', [['class="mw-headline"'], ['id="Economy']], 'span', [['class="mw-headline"']])
var education = getTextBetweenTags(html, 'span', [['class="mw-headline"'], ['id="Education']], 'span', [['class="mw-headline"']])
var returnString = '';
if (geography != 'No matches' && !/Wikipedia/.test(geography)) returnString += geography + '\n';
if (economy != 'No matches' && !/Wikipedia/.test(economy)) returnString += economy + '\n';
if (education != 'No matches' && !/Wikipedia/.test(education)) returnString += education + '\n';
return returnString
}
Thanks for posting your answer.

How to prevent error throwing in Google Apps Script?

Please see the code herein under:
function binanceOrderBook() {
try {
muteHttpExceptions = true;
var workSpreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var mySheet = workSpreadsheet.getSheetByName('Order Books');
if(mySheet == 'Sheet'){
mySheet.activate();
} else {
mySheet = workSpreadsheet.insertSheet('Order Books', 1).activate();
}
var ui = SpreadsheetApp.getUi();
var string = 'https://api.binance.com/api/v3/depth?';
var symbolResponse = ui.prompt('Pair Name', 'Please enter the pair symbol.\n\nExamples: BTCUSDT or ETHBTC:', ui.ButtonSet.OK_CANCEL);
var symbolButton = symbolResponse.getSelectedButton();
if(symbolButton == ui.Button.CANCEL){return}
var mySymbol = symbolResponse.getResponseText();
mySymbol = mySymbol.toUpperCase();
string = string + "symbol=" + mySymbol;
var limitResponse = ui.prompt('Limit:', 'Please enter Limit (Period Quantity).\nValid limits are:5, 10, 20, 50, 100, 500, 1000. \n Default limit is 100.\n You can leave it blank and simply click OK.', ui.ButtonSet.OK_CANCEL);
if(limitResponse.getSelectedButton() == ui.Button.CANCEL){return}
var myLimit = Number(limitResponse.getResponseText());
if(myLimit != 5 && myLimit != 10 && myLimit != 20 && myLimit != 50 && myLimit != 100 && myLimit != 500 && myLimit != 1000){myLimit = 100;}
string = string + "&limit=" + myLimit;
var myDate = new Date().toUTCString();
var jsonOrderBookData = JSON.parse(UrlFetchApp.fetch('https://api.binance.com/api/v3/depth?symbol=' + mySymbol + '&limit=' + myLimit));
reporter(jsonOrderBookData);
} catch (e){
exceptionHandler(e)
}
}
The problem I have is to run UrlFetchApp.fetch again when it encounters an error. I need to run it several times to get the result. So, I need to prevent the script from stopping when an error (code -1003) occurs, but how can I do that?
EDIT: There is a function windows.onerror in javascript which can be set to prevent the program from stopping. Is it useable in GAS? if yes, how? if No, is there a similar solution for GAS?
You could call binanceOrderBook() from within your catch statement. E.g.
...
} catch (e){
binanceOrderBook()
exceptionHandler(e)
}
Of course you probably should have some condition that exits the function if a certain error occurs, or if you know that the function needs to run no more than x number of times you could check that it has run less than x times before executing. For example,
const maxValue = 10 // whatever the max number of executions should be
function binanceOrderBook(executions) {
if (executions >= maxValue) return;
try {
...
} catch(e) {
binanceOrderBook((executions || 0) + 1));
exceptionHandler(e); // note that I am including this here because it's in your original example, but as it is written now, exception handler won't be called until binanceOrderBook executes without an error.
}
}
[Edit] To answer your second question, there is no equivalent to window.onerror that I know of in GAS. However, window.onerror is a global event handler and so would affect errors thrown by any functions defined in your project. To address a concern with a single function call like this, you are better off using a try catch statement as you have.

How to get all pages of a Google site with many pages

I have a Google site and I use Google Apps Script to get all the pages of the site and export their data to JSON format.
I use the getAllDescendants function with a code similar to this:
function getAllSitePages(site) {
var result = [], i = 0;
while(true) {
var pages = site.getAllDescendants({start: i});
if(!pages || pages.length == 0) break;
result = result.concat(pages);
i += pages.length;
};
return result;
}
But this only gets me the first 891 (?!) pages. If my sites has around 1000 pages, is there a way to get all of them with the Sites Service?
For now, I was able to bypass the problem by using the getChildren function instead (as I currently don't have any page (including root), that has more than 800 direct children):
function getAllSitePages(root, result) {
result = result || []
var start = 0;
while (true) {
var pages = root.getChildren({ start });
if (!pages || pages.length == 0) break;
result.push(...pages);
pages.forEach(page => getAllSitePages(page, result));
start += pages.length;
};
return result;
}

Navigating Windows Phone 8 Pivot

While working on Windows Phone 8 app, we need to restrict user on navigating pivot.
For example, only first two items are available until user make his selection on second item, then third is unlocked, and so on.
I've tried several approaches, and all of them stumble on one thing - setting pivot.SelectedIndex (or pivot.SelectedItem) inside event handler does not changing visual representation of pivot.
What is missing in my approach?
Here is sample code, from one of variants I've tried...
private void ReservationPivot_UnloadingPivotItem(object sender, PivotItemEventArgs e)
{
if (previousSelectedIndex != ((Pivot)sender).Items.IndexOf(e.Item) && !pivotRedirect)
previousSelectedIndex = ((Pivot)sender).Items.IndexOf(e.Item);
else if (previousSelectedIndex == ((Pivot)sender).Items.IndexOf(e.Item))
return;
object tmp;
PhoneApplicationService.Current.State.TryGetValue("PickupAddress", out tmp);
if (e.Item == ((Pivot)sender).Items[1] && tmp == null && !pivotRedirect)
{
MessageBox.Show("Please, select pickup point!");
pivotRedirect = true;
((Pivot)sender).SelectedIndex = previousSelectedIndex;
((Pivot)sender).SelectedItem = ((Pivot)sender).Items[1];
return;
}
PhoneApplicationService.Current.State.TryGetValue("DropOffAddress", out tmp);
if (e.Item == ((Pivot)sender).Items[2] && tmp == null && !pivotRedirect)
{
MessageBox.Show("Please, select dropoff point!");
pivotRedirect = true;
((Pivot)sender).SelectedIndex = previousSelectedIndex;
((Pivot)sender).SelectedItem = ((Pivot)sender).Items[2];
return;
}
if (pivotRedirect)
{
if (((Pivot)sender).SelectedIndex != previousSelectedIndex)
{
pivotRedirect = false;
((Pivot)sender).SelectedIndex = previousSelectedIndex;
}
}
}
Dont have access to visual now but did you try set visible of third pivot item to collapsed and change it to visible when user will select dropooff point ?

A* algorithm works OK, but not perfectly. What's wrong?

This is my grid of nodes:
I'm moving an object around on it using the A* pathfinding algorithm. It generally works OK, but it sometimes acts wrongly:
When moving from 3 to 1, it correctly goes via 2. When going from 1 to 3 however, it goes via 4.
When moving between 3 and 5, it goes via 4 in either direction instead of the shorter way via 6
What can be wrong? Here's my code (AS3):
public static function getPath(from:Point, to:Point, grid:NodeGrid):PointLine {
// get target node
var target:NodeGridNode = grid.getClosestNodeObj(to.x, to.y);
var backtrace:Map = new Map();
var openList:LinkedSet = new LinkedSet();
var closedList:LinkedSet = new LinkedSet();
// begin with first node
openList.add(grid.getClosestNodeObj(from.x, from.y));
// start A*
var curNode:NodeGridNode;
while (openList.size != 0) {
// pick a new current node
if (openList.size == 1) {
curNode = NodeGridNode(openList.first);
}
else {
// find cheapest node in open list
var minScore:Number = Number.MAX_VALUE;
var minNext:NodeGridNode;
openList.iterate(function(next:NodeGridNode, i:int):int {
var score:Number = curNode.distanceTo(next) + next.distanceTo(target);
if (score < minScore) {
minScore = score;
minNext = next;
return LinkedSet.BREAK;
}
return 0;
});
curNode = minNext;
}
// have not reached
if (curNode == target) break;
else {
// move to closed
openList.remove(curNode);
closedList.add(curNode);
// put connected nodes on open list
for each (var adjNode:NodeGridNode in curNode.connects) {
if (!openList.contains(adjNode) && !closedList.contains(adjNode)) {
openList.add(adjNode);
backtrace.put(adjNode, curNode);
}
}
}
}
// make path
var pathPoints:Vector.<Point> = new Vector.<Point>();
pathPoints.push(to);
while(curNode != null) {
pathPoints.unshift(curNode.location);
curNode = backtrace.read(curNode);
}
pathPoints.unshift(from);
return new PointLine(pathPoints);
}
NodeGridNode::distanceTo()
public function distanceTo(o:NodeGridNode):Number {
var dx:Number = location.x - o.location.x;
var dy:Number = location.y - o.location.y;
return Math.sqrt(dx*dx + dy*dy);
}
The problem I see here is the line
if (!openList.contains(adjNode) && !closedList.contains(adjNode))
It may be the case that an adjNode may be easier(shorter) to reach through the current node although it was reached from another node previously which means it is in the openList.
Found the bug:
openList.iterate(function(next:NodeGridNode, i:int):int {
var score:Number = curNode.distanceTo(next) + next.distanceTo(target);
if (score < minScore) {
minScore = score;
minNext = next;
return LinkedSet.BREAK;
}
return 0;
});
The return LinkedSet.BREAK (which acts like a break statement in a regular loop) should not be there. It causes the first node in the open list to be selected always, instead of the cheapest one.