Trying to get environment variables from a Widget widget.system() - macos

I'm attempting to write some Dashcode to but can't seem to get the environment variables when I run the /env command. The environment doesn't appear to be sourced because it always returns "Undefined". Below is my code and I'm open for any suggestions (I need more than just LANG, LANG is just the example).
var textFieldToChange = document.getElementById("LangField");
var newFieldText = widget.system("/usr/bin/env | grep LANG").outputString;
textFieldToChange.value = newFieldText;
Is there an easy way to source my environment and cache it in Dashcode or do I need to attempt to write something that will cache the entire environment somehow?
Thanks for any ideas!

Have you allowed Command Line Access? Go to Widget Attributes (in the left hand menu) , then extensions and check Allow Command Line Access else the widget is prevented from talking to the system. Not sure if this is what is causing the problem though.

I know this thread is quite aged, but anyway, the question is still up to date :-)
Just having started with Dashcode and widgets myself, I did a quick hack on this:
function doGetEnv(event)
{
if (window.widget)
{
var out = widget.system("/bin/bash -c set", null).outputString;
document.getElementById("content").innerText = out;
}
}
For my experimental widget, I did use a scroll area and a button. The doGetEnv(event) is fired upon onclick, set via inspector. The Id "content" is the standard naming of the content within the scroll area.
The out var containes a string with '\n' charaters, to transform it into an array use split().
function doGetEnv(event)
{
if (window.widget)
{
var out = widget.system("/bin/bash -c set", null).outputString;
out = out.split("\n");
document.getElementById("content").innerText = out[0];
}
}
The first entry is "BASH..." in my case.
If you search for a particular item, use STRING's match method (see also http://www.w3schools.com/jsref/jsref_match.asp) along with the following pages on regular expressions:
http://www.w3schools.com/jsref/jsref_obj_regexp.asp
http://www.w3schools.com/js/js_obj_regexp.asp
To cache the environment, you can use:
var envCache = "";
function cacheENV()
{
envCache = widget.system("/bin/bash -c set", null).outputString;
envCache = envCache.split("\n");
}
This will leave an array in envCache. Alternative:
function cacheENV()
{
var envCache = widget.system("/bin/bash -c set", null).outputString;
envCache = envCache.split("\n");
return envCache;
}

Related

Kendo UI template syntax in TabStrip

I have a kendo template that contains a tabstrip. In this tabstrip I have item that use the kendo template syntax like so:
items.Add().Text("Block Attributes").LoadContentFrom("BlockAttributes", "Properties", new { blockRef = "#=BlockRef#" });
In this case the block ref gets output as expected. However when using the .Action() method like so:
items.Add().Action("Details", "Properties", new { fiscalYear = Model.FiscalYear, blockRef = "#=BlockRef#" }).Text("Details");
the propertyId uses the literal string that is typed so it will try to navigate using "#=BlockRef#" as a parameter which results in an error.
Why does it work ok for the former but not the latter? How do I get this to work?
A solution I have found, although probably ill-advised is to do the following:
items.Add().Text("Details").Url(Url.Action("Detail", "Properties", new { fiscalYear = Model.FiscalYear, blockRef = -1 }).ToString().Replace("-1", "#=BlockRef#"))
It seems there is no way to get Kendo templates to work directly with Url.Action(), the html has to first be generated and then parameters have to be individually replaced. I used -1 as BlockRef is expecting an int and there is no possible way for -1 to appear naturally in the system.

tmux titles-string not executing shell command

I have the following lines in my ~/.tmux.conf
set-option -g set-titles on
set-option -g set-titles-string "#(whoami)##H: $PWD \"#S\" (#W)#F [#I:#P]"
This has worked in the past but after upgrading to 2.0 shell commands are no longer executed. I now see in my title:
#(whoami)#myhostname.local: /Users/lander [..rest..]
According to the man page, this should work:
status-left string
Display string (by default the session name) to the left of the status
bar. string will be passed through strftime(3) and formats (see
FORMATS) will be expanded. It may also contain any of the following
special character sequences:
Character pair Replaced with
#(shell-command) First line of the command's output
#[attributes] Colour or attribute change
## A literal `#'
Well done for reading the code, it's simple really: set-titles-string switched to using formats which don't expand #(). Patching this is easy, and no, it's not good enough to reinstate status_print() to tmux.h, instead, job expansion should be a separate function and used from status_replace() and format_expand(). No idea when this will get done.
Thanks for playing.
The code that performed the task your are mentioning is no longer present in version 2.0. That's the short answer to the question above. Either the documentation hasn't been updated to reflect this, or this was done accidentally and is a bug.
What follows is exactly why I think this is the case. I'm at the end of my lunch break, so I can't create a patch for this right now. If no one else gets around to fixing this from here, I will take a stab at it this weekend.
I checkout out the git repository and took a look at code changes from version 1.9a -> 2.0.
The function that actually does this replacement is status_replace() in status.c. This still seems to work, as the command processing works in the status lines, which still call this function.
In version 1.9a, this was also called from server_client_set_title() in server-client.c, around line 770. It looks like this:
void
server_client_set_title(struct client *c)
{
struct session *s = c->session;
const char *template;
char *title;
template = options_get_string(&s->options, "set-titles-string");
title = status_replace(c, NULL, NULL, NULL, template, time(NULL), 1);
if (c->title == NULL || strcmp(title, c->title) != 0) {
free(c->title);
c->title = xstrdup(title);
tty_set_title(&c->tty, c->title);
}
free(title);
}
In version 2.0, this call has been replaced with (now down around line 947):
void
server_client_set_title(struct client *c)
{
struct session *s = c->session;
const char *template;
char *title;
struct format_tree *ft;
template = options_get_string(&s->options, "set-titles-string");
ft = format_create();
format_defaults(ft, c, NULL, NULL, NULL);
title = format_expand_time(ft, template, time(NULL));
if (c->title == NULL || strcmp(title, c->title) != 0) {
free(c->title);
c->title = xstrdup(title);
tty_set_title(&c->tty, c->title);
}
free(title);
format_free(ft);
}
It looks like calls to format_expand_time() and status_replace() might be mutually exclusive. That is the part that might take a bit of effort to fix -- getting the old function call back in there without breaking whatever new functionality they've just added.

Need assistance with unfamiliar syntax, error - e is undefined - Google Apps Script(GAS)

I'm using a script exactly like the one on the tutorial here, https://developers.google.com/apps-script/reference/ui/file-upload
However, despite using the syntax I keep getting e is undefined in the statement:
var fileBlob = e.parameter.dsrFile;
I think that means my function doPost(e) is probably wrong somehow. Here is my entire script below.
// Create Menu to Locate .CSV
function doGet(e) {
var app = UiApp.createApplication().setTitle("Upload CSV");
var formContent = app.createVerticalPanel();
formContent.add(app.createFileUpload().setName("dsrFile"));
formContent.add(app.createSubmitButton("Start Upload"));
var form = app.createFormPanel();
form.add(formContent);
app.add(form);
return app;
}
// Upload .CSV file
function doPost(e)
{
// data returned is a blob for FileUpload widget
var fileBlob = e.parameter.dsrFile;
var doc = DocsList.createFile(fileBlob);
}
e is undefined because you are not passing anything to doPost. You have to pass the needed object to doPost. Check where you call the function and what parameters do you pass to it if any. Even if you pass a parameter to that function, it holds undefined value. Make sure that you are passing the correct objects to your functions.
Your script should work perfectly. e is defined by Google Apps Script, not need to pass anything in particular is contains the fields of your form, in particular in this case the file you uploaded.
I would suspect you may be falling foul to the dev url vs publish url syndrome, where you are executing an old scrip rather that the code you are currently working on.
Be sure you script end with 'dev' and not 'exec'
https://script.google.com/a/macros/appsscripttesting.com/s/AKfyck...EY7qzA7m6hFCnyKqg/dev
Let me know if you are still getting the error after running it from the /dev url

Format Output of Placeholder

I am creating a dynamic list of placeholders, some of the values held in these place holders are decimal numbers that are supposed to represent money.
What I'm wondering is if there is a way I can format them to display as such?
Something like [[+MoneyField:formatmoney]]
I see http://rtfm.modx.com/revolution/2.x/making-sites-with-modx/customizing-content/input-and-output-filters-(output-modifiers) but I do not see a way to do this here.
You most definitely can, under the header "Creating a Custom Output Modifier" on the link you posted it's described how you can place a snippet name as a output modifier. This snippet will recieve the [[+MoneyField]] value in a variable called $input.
So you'd have to create this custom snippet which could be as simple as
return '$'.number_format($input);
Another version of doing this is calling the snippet directly instead of as an output modifier like so:
[[your_custom_money_format_snippet ? input=`[[+MoneyField]]`]]
I'm not sure if theres any difference between the two in this case. Obviously you can pass any value into the number format snippet when calling it as a snippet instead of an output modifier. And i'm sure theres a microsecond of performance difference in the two but i'm afraid i don't know which one would win. ;)
Update:
Actually found the exact example you want to implement on this link;
http://rtfm.modx.com/revolution/2.x/making-sites-with-modx/customizing-content/input-and-output-filters-%28output-modifiers%29/custom-output-filter-examples
Snippet:
<?php
$number = floatval($input);
$optionsXpld = #explode('&', $options);
$optionsArray = array();
foreach ($optionsXpld as $xpld) {
$params = #explode('=', $xpld);
array_walk($params, create_function('&$v', '$v = trim($v);'));
if (isset($params[1])) {
$optionsArray[$params[0]] = $params[1];
} else {
$optionsArray[$params[0]] = '';
}
}
$decimals = isset($optionsArray['decimals']) ? $optionsArray['decimals'] : null;
$dec_point = isset($optionsArray['dec_point']) ? $optionsArray['dec_point'] : null;
$thousands_sep = isset($optionsArray['thousands_sep']) ? $optionsArray['thousands_sep'] : null;
$output = number_format($number, $decimals, $dec_point, $thousands_sep);
return $output;
Used as output modifier:
[[+price:numberformat=`&decimals=2&dec_point=,&thousands_sep=.`]]

How to debug Google Apps Script (aka where does Logger.log log to?)

In Google Sheets, you can add some scripting functionality. I'm adding something for the onEdit event, but I can't tell if it's working. As far as I can tell, you can't debug a live event from Google Sheets, so you have to do it from the debugger, which is pointless since the event argument passed to my onEdit() function will always be undefined if I run it from the Script Editor.
So, I was trying to use the Logger.log method to log some data whenever the onEdit function gets called, but this too seems like it only works when run from the Script Editor. When I run it from the Script Editor, I can view the logs by going to View->Logs...
I was hoping I'd be able to see the logs from when the event actually gets executed, but I can't figure it out.
How do I debug this stuff?
UPDATE:
As written in this answer,
Stackdriver Logging is the preferred method of logging now.
Use console.log() to log to Stackdriver.
Logger.log will either send you an email (eventually) of errors that have happened in your scripts, or, if you are running things from the Script Editor, you can view the log from the last run function by going to View->Logs (still in script editor). Again, that will only show you anything that was logged from the last function you ran from inside Script Editor.
The script I was trying to get working had to do with spreadsheets - I made a spreadsheet todo-checklist type thing that sorted items by priorities and such.
The only triggers I installed for that script were the onOpen and onEdit triggers. Debugging the onEdit trigger was the hardest one to figure out, because I kept thinking that if I set a breakpoint in my onEdit function, opened the spreadsheet, edited a cell, that my breakpoint would be triggered. This is not the case.
To simulate having edited a cell, I did end up having to do something in the actual spreadsheet though. All I did was make sure the cell that I wanted it to treat as "edited" was selected, then in Script Editor, I would go to Run->onEdit. Then my breakpoint would be hit.
However, I did have to stop using the event argument that gets passed into the onEdit function - you can't simulate that by doing Run->onEdit. Any info I needed from the spreadsheet, like which cell was selected, etc, I had to figure out manually.
Anyways, long answer, but I figured it out eventually.
EDIT:
If you want to see the todo checklist I made, you can check it out here
(yes, I know anybody can edit it - that's the point of sharing it!)
I was hoping it'd let you see the script as well. Since you can't see it there, here it is:
function onOpen() {
setCheckboxes();
};
function setCheckboxes() {
var checklist = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("checklist");
var checklist_data_range = checklist.getDataRange();
var checklist_num_rows = checklist_data_range.getNumRows();
Logger.log("checklist num rows: " + checklist_num_rows);
var coredata = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("core_data");
var coredata_data_range = coredata.getDataRange();
for(var i = 0 ; i < checklist_num_rows-1; i++) {
var split = checklist_data_range.getCell(i+2, 3).getValue().split(" || ");
var item_id = split[split.length - 1];
if(item_id != "") {
item_id = parseInt(item_id);
Logger.log("setting value at ("+(i+2)+",2) to " + coredata_data_range.getCell(item_id+1, 3).getValue());
checklist_data_range.getCell(i+2,2).setValue(coredata_data_range.getCell(item_id+1, 3).getValue());
}
}
}
function onEdit() {
Logger.log("TESTING TESTING ON EDIT");
var active_sheet = SpreadsheetApp.getActiveSheet();
if(active_sheet.getName() == "checklist") {
var active_range = SpreadsheetApp.getActiveSheet().getActiveRange();
Logger.log("active_range: " + active_range);
Logger.log("active range col: " + active_range.getColumn() + "active range row: " + active_range.getRow());
Logger.log("active_range.value: " + active_range.getCell(1, 1).getValue());
Logger.log("active_range. colidx: " + active_range.getColumnIndex());
if(active_range.getCell(1,1).getValue() == "?" || active_range.getCell(1,1).getValue() == "?") {
Logger.log("made it!");
var next_cell = active_sheet.getRange(active_range.getRow(), active_range.getColumn()+1, 1, 1).getCell(1,1);
var val = next_cell.getValue();
Logger.log("val: " + val);
var splits = val.split(" || ");
var item_id = splits[splits.length-1];
Logger.log("item_id: " + item_id);
var core_data = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("core_data");
var sheet_data_range = core_data.getDataRange();
var num_rows = sheet_data_range.getNumRows();
var sheet_values = sheet_data_range.getValues();
Logger.log("num_rows: " + num_rows);
for(var i = 0; i < num_rows; i++) {
Logger.log("sheet_values[" + (i) + "][" + (8) + "] = " + sheet_values[i][8]);
if(sheet_values[i][8] == item_id) {
Logger.log("found it! tyring to set it...");
sheet_data_range.getCell(i+1, 2+1).setValue(active_range.getCell(1,1).getValue());
}
}
}
}
setCheckboxes();
};
As far as I can tell, you can't debug a live event from google docs, so you have to do it from the debugger, which is pointless since the event argument passed to my onEdit() function will always be undefined if I run it from the Script Editor.
True - so define the event argument yourself for debugging. See How can I test a trigger function in GAS?
I was trying to use the Logger.log method to log some data whenever the onEdit function gets called, but this too seems like it only works when run from the Script Editor. When I run it from the Script Editor, I can view the logs by going to View->Logs...
True again, but there is help. Peter Hermann's BetterLog library will redirect all logs to a spreadsheet, enabling logging even from code that is not attached to an instance of the editor / debugger.
If you're coding in a spreadsheet-contained script, for example, you can add just this one line to the top of your script file, and all logs will go to a "Logs" sheet in the spreadsheet. No other code necessary, just use Logger.log() as you usually would:
Logger = BetterLog.useSpreadsheet();
2017 Update:
Stackdriver Logging is now available for Google Apps Script. From the menu bar in the script editor, goto:
View > Stackdriver Logging to view or stream the logs.
console.log() will write DEBUG level messages
Example onEdit() logging:
function onEdit (e) {
var debug_e = {
authMode: e.authMode,
range: e.range.getA1Notation(),
source: e.source.getId(),
user: e.user,
value: e.value,
oldValue: e. oldValue
}
console.log({message: 'onEdit() Event Object', eventObject: debug_e});
}
Then check the logs in the Stackdriver UI labeled onEdit() Event Object to see the output
I've gone through these posts and somehow ended up finding a simple answer, which I'm posting here for those how want short and sweet solutions:
Use console.log("Hello World") in your script.
Go to https://script.google.com/home/my and select your add-on.
Click on the ellipsis menu on Project Details, select Executions.
Click on the header of the latest execution and read the log.
A little hacky, but I created an array called "console", and anytime I wanted to output to console I pushed to the array. Then whenever I wanted to see the actual output, I just returned console instead of whatever I was returning before.
//return 'console' //uncomment to output console
return "actual output";
}
If you have the script editor open you will see the logs under View->Logs. If your script has an onedit trigger, make a change to the spreadsheet which should trigger the function with the script editor opened in a second tab. Then go to the script editor tab and open the log. You will see whatever your function passes to the logger.
Basically as long as the script editor is open, the event will write to the log and show it for you. It will not show if someone else is in the file elsewhere.
I am having the same problem, I found the below on the web somewhere....
Event handlers in Docs are a little tricky though. Because docs can handle multiple simultaneous edits by multiple users, the event handlers are handled server-side. The major issue with this structure is that when an event trigger script fails, it fails on the server. If you want to see the debug info you'll need to setup an explicit trigger under the triggers menu that emails you the debug info when the event fails or else it will fail silently.
It's far from elegant, but while debugging, I often log to the Logger, and then use getLog() to fetch its contents. Then, I either:
save the results to a variable (which can be inspected in the Google Scripts debugger—this works around cases where I can't set a breakpoint in some code, but I can set one in code that gets executed later)
write it to some temporary DOM element
display it in an alert
Essentially, it just becomes a JavaScript output issue.
It grossly lacks the functionality of modern console.log() implementations, but the Logger does still help debug Google Scripts.
Just as a notice. I made a test function for my spreadsheet. I use the variable google throws in the onEdit(e) function (I called it e). Then I made a test function like this:
function test(){
var testRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(GetItemInfoSheetName).getRange(2,7)
var testObject = {
range:testRange,
value:"someValue"
}
onEdit(testObject)
SpreadsheetApp.getActiveSpreadsheet().getSheetByName(GetItemInfoSheetName).getRange(2,6).setValue(Logger.getLog())
}
Calling this test function makes all the code run as you had an event in the spreadsheet. I just put in the possision of the cell i edited whitch gave me an unexpected result, setting value as the value i put into the cell.
OBS! for more variables googles gives to the function go here: https://developers.google.com/apps-script/guides/triggers/events#google_sheets_events
Currently you are confined to the container bound nature of using scripts within docs. If you create a new script inside outside of docs then you will be able to export information to a google spreadsheet and use it like a logging tool.
For example in your first code block
function setCheckboxes() {
// Add your spreadsheet data
var errorSheet = SpreadsheetApp.openById('EnterSpreadSheetIDHere').getSheetByName('EnterSheetNameHere');
var cell = errorSheet.getRange('A1').offset(errorSheet.getLastRow(),0);
// existing code
var checklist = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("checklist");
var checklist_data_range = checklist.getDataRange();
var checklist_num_rows = checklist_data_range.getNumRows();
// existing logger
Logger.log("checklist num rows: " + checklist_num_rows);
//We can pass the information to the sheet using cell.setValue()
cell.setValue(new Date() + "Checklist num rows: " + checklist_num_rows);
When I'm working with GAS I have two monitors ( you can use two windows ) set up with one containing the GAS environment and the other containing the SS so I can write information to and log.
The dev console will log errors thrown by the app script, so you can just throw an error to get it logged as a normal console.log. It will stop execution, but it might still be useful for step by step debugging.
throw Error('hello world!');
will show up in the console similarly to console.log('hello world')
For Apps Script projects that are tied to a single Sheet (or doc) — in 2022 — there is no View menu like other answers suggest. Instead you need to look in the Executions menu on the left sidebar to see the executions of your onSelectionChange function (or any other function), from there you can click REFRESH until your console.log messages appear.
just debug your spreadsheet code like this:
...
throw whatAmI;
...
shows like this:

Resources