String interpolation in coffeescript - coffeescript

My question is similar to the one posted here. Essentially I would like to read a config file.json looking like this:
{
"message": "Error in #{baseName} at #{directory}"
}
I would like to interpolate the message string using variables provided as a map / an object. Unlike in the question above, the string to be formatted is not known at compile time.
Is it possible to run a string interpolation using built-in methods in coffeescript or would I have to use mustaches or similar techniques?

You could pretty easily wire up a very basic template engine using CoffeeScript template literals.
You would have to define your JSON as a CS file that exports:
module.exports = (context)->
[
some: "#{context.dynamic.content}"
,
some: 'other static content'
]
Then, you would simply call the function with the values you want:
render = require './data'
myContext =
dynamic: content: 'some dynamic content'
dynamicData = render(myContext)
At this point dynamicData looks like this:
[
some: 'some dynamic content'
,
some: 'other static content'
]

As per the comment by #deceze - no. The coffeescript will be compiled and executed as JS which doesn't have this string interpolation syntax. And even then, you would have to use eval(), which isn't good practice.
I would suggest the JS library spintf for on the fly string interpolation. You may be familiar with the syntax from other languages

Related

VSCode Extension: Get outline of function for custom outliner

I'm trying to create a custom outliner for VSCode (currently only for python), but I don't find measures to get the information I needed.
I like to get information in this manner this:
Array:
[0]
label: "foo"
type: "Function"
parameters: [...]
Range: [...]
innerDefinitions: [0]
[1]
label: "myclass"
type: "Class"
base_class: ""
Range: [...]
innerDefinitions:
[0]:
[...]
[1]:
[...]
Currently I try to get outline information via vscode.commands.executeCommand( 'vscode.XXX'
What I've tried:
Here is what commands I've tried and what result I received.
vscode.executeImplementationProvider
half usable: range of functionname. Other information is missing
vscode.executeHoverProvider
half usable: string of function head (including def keyword)
vscode.executeDefinitionProvider
half usable: range of complete function. Individual information must be "parsed out"
vscode.executeTypeDefinitionProvider
Never provided any result
vscode.executeDeclarationProvider
Never provided any result
vscode.executeDocumentSymbolProvider
Goes in a good direction. However
(1) Does only work on the whole document (not single function)
(2) Does only return first-level entities (i.e. class methods are not included in result)
Is there any API call I've overseen?
I wonder how the built-in outliner works, as it contains all-level information.
You need to use vscode.commands.executeCommand<vscode.Location[]>("vscode.executeDocumentSymbolProvider", uri, position)
This will give you the full outline of one file. There is no way to receive a partial outline.
Note: innerDefinitions are called children here.
Regarding the detail of the outline:
How detailed (and correct) an outline is going to be, depends on the implementation of the provider. Also, provider's information is no necessarily consistent among languages. This is very important to keep in mind!
At the moment (2021/03), the standard SymbolProvider for...
... Python will have a child for each parameter and local variable of a function. They will not be distinguishable
... C++ will contain no children for parameters. But it will have the parameter types in its name. (e.g. name of void foo(string p) will be foo(string): void.
As you can see, both act differently with their own quirks.
You could create and register a DocumentSymbolProvider yourself, that would return a level of detail you need (see VSCode Providers)
Also see: https://stackoverflow.com/a/66486297/6702598

CloudFormation syntax for ParameterOverrides

I'm getting stuck on overriding multiple parameters within a CloudFormation that is passing them to CodePipeline.
I can successful override a single parameter like this:
ParameterOverrides: "{ \"StageName\": \"stage\" }"
But when I try this:
ParameterOverrides: '{ "StageName": "prod", "EnvValue", "prod" }'
I have also tried these combinations:
ParameterOverrides: "{\"StageName\": \"prod\", \"EnvValue\", \"prod\"}"
Codepipeline throws an error of: ParameterOverrides property is not valid
I have looked at this help article a half a dozen times and it seems I'm following the format to the T.
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/continuous-delivery-codepipeline-parameter-override-functions.html
What am I missing? Does anyone have this working in a CloudFormation template?
When dealing with embedded JSON in your YAML, the folded (>) or literal (|) block style, rather than a quoted string, will increase clarity. So something like:
ParameterOverrides: >
{
"StageName": "prod",
"EnvValue": "prod"
}
This will let you see the actual JSON without quite as much noise from the backslash escapes in the way. This can be seen in the "Example Create Stack B Stage" section of the page you linked to (it uses the literal block style with |). The difference between | and > can be seen on the YAML Multiline site.
I found out what the problem was, fat fingered.
I put this:
ParameterOverrides: "{\"StageName\": \"prod\", \"EnvValue\", \"prod\"}"
and it should have been this:
ParameterOverrides: "{\"StageName\": \"prod\", \"EnvValue\": \"prod\"}"
NOTICE: the missing colon on after the second key.

Programmatically return a list of all functions

I want to programmatically get a list of available functions in the current MATLAB namespace, as well the available functions in a package. How can this be done?
We can use package metadata for this:
pkgs = meta.package.getAllPackages();
% Or if the specific package name is known:
mp = meta.package.fromName('matlab')
The cell array returned in the 1st case, pkgs, contains objects such as this:
package with properties:
Name: 'Sldv'
Description: ''
DetailedDescription: ''
ClassList: [29×1 meta.class]
FunctionList: [8×1 meta.method]
PackageList: [9×1 meta.package]
ContainingPackage: [0×0 meta.package]
So all that's left to do is iterate through the packages and sub-packages tand collect their FunctionList entries.
I'm not sure how to get the functions that belong to the "default" namespace, other than by parsing the function list doc page, for example using the Python API and BeautifulSoup:
fl = arrayfun(#(x)string(x{1}.string.char), py.bs4.BeautifulSoup( ...
fileread(fullfile(docroot,'matlab','functionlist-alpha.html')), ...
'html.parser').find_all("code")).';
Further to Dev-iL's answer, parsing the function list documentation web page is pretty easy because of the useful "function" class that the web devs have (currently) used to tag each function name with! Each function looks like this within the HTML:
<code class="function">accumarray</code>
So we can use urlread to grab the source, and regular expressions to strip out the inner text of each "function" class item:
str = urlread('https://mathworks.com/help/matlab/functionlist-alpha.html');
funcs = regexp( str, '(?<="function">)[0-9A-Za-z.]+', 'match' );
Note: "alpha" in the URL is for "alphabetical" rather than to denote early testing!
funcs is a cell array with all the function names on that page.
The page used above is for the most recent MATLAB version. For a specific version, use the historic documentation pages structured like so:
https://mathworks.com/help/releases/R2017b/matlab/functionlist.html

Can I use rowmode: 'array' in combination with named parameters?

Is it possible to have rowMode: 'array' and named parameters at the same time? Right now, with the code below, I'm getting syntax error at or near "$"
db.query({
text: `
select task_nr, commitment
from surveys
where email = $<email> and id = $<id>
order by task_nr
`,
values: {email: email, id: id},
rowMode: 'array',
})
No, it is not possible, because rowMode is strictly part of the Parameterized Query, which by definition forwards query formatting to the driver->server where such thing as Named Parameters does not exist.
Unfortunately, if you really need to use rowMode, you can only use the basic $1, $2... variable formatting as supported by the server.
Strictly speaking, rowMode is not that valuable, it is fairly easy to reformat the data, and then just use pg-promise default formatting with all its nice formatting features.

escape HTML by default in Template Toolkit

Can I somehow configure Template Toolkit so that:
[% foo %]
does what you would now need to say:
[% foo | html %]
that is, escape HTML in foo? And do something else, like:
[% foo | noHtml %]
if I don't want to escape?
Came across your question when trying to answer the same question for myself.
http://search.cpan.org/~mithaldu/Template-AutoFilter/ seems to do what we want, but it does require installing another module. I'm going to give it a try anyway.
I guess you could create your own stash by extending Template::Stash so that it would by default escape variables.
That said I think it is not a good idea. Better to stick with default behaviour and refrain from custom modifications as they are certainly confusing.
I spent some time on this problem recently. Here is the outline of my solution.
I created a new class called HtmlSafe which contains strings that can be safely written to WWW client without a security vulnerability. The idea was that the functions that generate HTML tags return HtmlSafe objects, and variables out of the box are not HtmlSafe. Whatever creates a HtmlSafe also has vouched for the safety for the string in question. Concatenating a non-HTML-safe string with HTML-safe string causes the non-HTML-safe string to be escaped through CGI::escapeHTML, and then joined with the HTML-safe string. Concatenating another instance of HtmlSafe to HtmlSafe just joins the strings in question without escaping. I ended up using an overload so I could redefine the . operator for HtmlSafe class.
Armed with this thing, I gave a $template->process() function an $output variable that was actually a sub that invoked a concatenation with HtmlSafe, like this:
my $output = HtmlSafe->new("");
$template->process($vars, sub { $output .= $_[0]; });
return $output->unwrap(); # remove HtmlSafe and return underlying string
We are almost ready with the HtmlSafe TT2. The big changed I had to actually do was to change the textblock() function in Template::Directive, which is used by the Template::Parser to generate HtmlSafe instances of whatever text block it tried to emit. These appear to correspond with the TEXT nodes of the parsed template, so just doing
package MyDirective;
use base "Template::Directive";
sub textblock { my $self = shift; return "$Template::Directive::OUTPUT HtmlSafe->new(" . $self->text(#_) . ")"; }
which I gave to parser like so:
my $parser = Template::Parser->new({
FACTORY => "MyDirective",
});
In addition to this, I defined a "none" filter for TT2 which simply wraps whatever is defined as HtmlSafe, so you can output raw HTML if you have to. This avoids escaping things. The default "html" filter is no-op, because anything concatenated to HtmlSafe gets escaped now anyway.