Can I include conditional logic in VS Code snippets? - json

I would like to write a snippet in VS Code that writes a "switch" expression (in Javascript), but one where I can define the number of cases.
Currently there is a snippet that produces the outline of a switch expression with 1 case, and allows you to tab into the condition, case name, and the code contained within.
I want to be able to type "switch5" ("5" being any number) and a switch with 5 cases to be created, where I can tab through the relevant code within.
I know the snippets are written in a JSON file, can I include such conditional logic in this, or is it not possible?
Thanks!

The short answer is that you cannot do that kind of thing in a standard vscode snippet because it cannot dynamically evaluate any input outside of its designated variables with some limited workarounds like I'll mention next.
You might - I and others have written answers on SO about his - type your various case values first and then trigger a snippet tat would transform them into a switch statement. It is sort of doing it backwords but it might be possible.
There are extensions, however, that do allow you to evaluate javascript right in a snippet or setting and output the result. macro-commander is one such extension. I'll show another simpler extension doing what you want: HyperSnips.
In your javascript.hsnips:
snippet `switch(\d)` "add number of cases to a switch statement" A
``
let numCases = Number(m[1]) // 'm' is an array of regex capture groups
let caseString = ''
if (numCases) { // if not 'switch0'
let tabStopNum = 1
caseString = `switch (\${${tabStopNum++}:key}) {\n`
for (let index = 0; index < m[1]; index++) {
caseString += `\tcase \${${tabStopNum++}:value}:\n\t\t\$${tabStopNum++}\n`
caseString += '\t\tbreak;\n\n'
}
caseString += '\tdefault:\n'
caseString += '\t\tbreak;\n}\n'
}
rv = `${caseString}` // return value
``
endsnippet
The trickiest part was getting the unknown number of tabstops to work correctly. This is how I did it:
\${${tabStopNum++}:key}
which will resolve to ${n:defaultValue} where n gets incremented every time a tabstop is inserted. And :defaultValue is an optional default value to that tabstop. If you don't need a defaultValue just use \$${tabStopNum++} there.
See https://stackoverflow.com/a/62562886/836330 for more info on how to set up HyperSnips.

Related

While loop keeps repeating itself when it should break

My goal is to create a pre-written code - or function - that I can apply to multiple questions, where I only need to fill in the information shown on the lower half. The top half code must remain general, because I do not want to replace pieces of the code every time I use it, and would rather have it do so automatically, making it Reusable.
At the moment my code keeps repeating itself even when I type in the correct answers ('Fully', 'Partially', 'None')
def enter_preset_option():
global subj_desc
subj_desc = input(question)
i = 0
while i < len(options):
if str(subj_desc.lower()) == options[i]:
print("Great!")
break
else:
print("Invalid input. Please try again!")
i += 1
enter_preset_option()
question = "Is the property fully fenced or partially fenced? (Answer 'Fully', 'Partially' or 'None'): "
options = ['fully', 'partially', 'none']
attribute = "Fenced"
enter_preset_option()
fenced = subj_desc
print(fenced)

Value Calculation issue in Google web HTML App

I have created an HTML web app in google script this works like a calculator, This app works fine if I add the input in descending order however if I skip the order and update in put data numbers randomly in any column then I am not getting the output properly
Example:- update the numbers in box number 4 and 5 then update in box number 1 you will find the differences in total numbers
Please refer the attached sheet for detailed script
Project Name- Project Proposal Form
$("#rTpe1").keyup(function(e){
$("#rFor1").val(this.value * $("#PerHourRate1").val());
$("#rFor3").val( Number($("#rFor1").val()) +Number($("#rFor2").val()))
});
$("#rTpe2").keyup(function(e){
$("#rFor2").val(this.value * $("#PerHourRate2").val());
$("#rFor3").val( Number($("#rFor1").val()) + Number($("#rFor2").val()))
});
$("#rTpe12").keyup(function(e){
$("#rFor12").val(this.value * $("#PerHourRate3").val());
$("#rFor3").val( Number($("#rFor1").val()) + Number($("#rFor2").val())+ Number($("#rFor12").val()))
});
$("#rTpe13").keyup(function(e){
$("#rFor13").val(this.value * $("#PerHourRate4").val());
$("#rFor3").val( Number($("#rFor1").val()) + Number($("#rFor2").val())+ Number($("#rFor12").val())+ Number($("#rFor13").val()))
});
I could be wrong, but I think that's the main culprit:
If your work your way top to bottom, the output in '#rFor3' is not affected. For example, if you enter values in the first field ('#rTpe1'), this statement
Number($("#rFor2").val()))
will evaluate to '0' because '#rFor2' probably contains an empty string at this point and Number("") will get you a zero. Because all subsequent input fields reference the results of previous calculations ('rTpe2' references 'rFor1', 'rTpe12' references both 'rFor1' and 'rFor2', etc), the sum will come out as correct.
Now consider the reverse scenario. For simplicity, let's make all your rates equal to 1. If you enter the value of '5' into 'rTpe12', the value of 'rFor3' will be
Number("") + Number("") + Number(5*1) == 5; //the first two inputs will contain empty strings at this point
The output of '#rFor3' would be 5. If you go up a step and enter the value of '2' into 'rTpe2', the value of the 'rFor3' output will change to
Number("") + Number(2*1) == 2; the first input will contain an empty string.
The code is not easy to understand, so even if this solution doesn't work for you, consider caching your DOM elements to improve performance and make your code more readable. Currently, you are using jQuery selectors to search the DOM over and over again, which is a serious performance drag. You could also store your calculated value as a variable and simply add values to it instead of recalculating on each input. For example
$('document').ready(function(){
var total = 0;
var input1 = $('#input1');
var input2 = $('#input1');
var input3 = $('#input1');
var output = $('#output');
input1.keyup(function(e){
var value = Number(this.value);
sum += value;
output.val(sum);
});
});

Node-red - need a multi-input function for a number value

So I'm just getting to grips with node-red and I need to create a conditional global function.
I have two separate global.payloads set to a number value of either 0 or 1.
What I need to happen now is, if global.payload is equal to value 1 then follow this flow, if it is equal to value 0 then follow this one.
I'm just a little confused with the syntax for the function statement. Any help gratefully appreciated.
Since you haven't accepted the current answer, thought I'd give this a try.
I think this is what you need to handle inputs from two separate global contexts. I'm simulating them here with two separate inject nodes to demonstrate:
The checkconf inject node emits a 1 or a 0. Same for the meshstatus node. Substitute your real inputs for those inject nodes. The real work is done inside the function:
var c = context.get('c') || 0; // initialize variables
var m = context.get('m') || 0;
if (msg.topic == "checkconf") // update context based on topic of input
{
c = {payload: msg.payload};
context.set("c", c); // save last value in local context
}
if (msg.topic == 'meshstatus') // same here
{
m = {payload: msg.payload};
context.set('m', m); // save last value in local context
}
// now do the test to see if both inputs are triggered...
if (m.payload == 1) // check last value of meshstatus first
{
if (c.payload == 1) // now check last value of checkconf
return {topic:'value', payload: "YES"};
}
else
return {topic:'value', payload: "NO"};
Be sure to set the "topic" property of whatever you use as inputs so the if statements can discriminate between the two input. Good luck!
You can use the Switch node to do this, rather than a Function node.

Select statement selection through URL parameters

I'm attempting to alter the contents of certain parts of a HTML form through usage of the URL. For a text field, I'm aware that this will suffice,
http://<domain>?fieldname=ping&anotherfield=pong
On the form there are multiple select braces (drop down boxes); Is it possible to pick an int or string value through the url for this?
There seems to be little documentation on this (or even people trying to do the same)...
You haven't specified how you want to do this, but I'll assume that you want to use JavaScript:
To get a value from QueryString:
getQueryStringArgument = function(key) {
var hu = window.location.search.substring(1);
var gy = hu.split("&");
for (i = 0; i < gy.length; i++) {
var ft = gy[i].split("=");
if (ft[0] == key)
return ft[1];
}
}
To set the selected value of the select list:
document.getElementById("sel").value = getQueryStringArgument("id");
For a text field, I'm aware that this will suffice
No, it won't (at least, not in a generic way).
For a text field, the default value is specified by the value attribute. There might be a server side script that populates it based on query string data, but there doesn't have to be.
On the form there are multiple select braces (drop down boxes); Is it possible to pick an int or string value through the url for this?
Again, this requires an attribute to be set (selected on <option>), and that could (again) be set by a server side script based on the query string data.

LINQ-to-SQL oddity with multiple where clause arguments on the same field

My problem requires me to dynamically add where clauses to a IQueryable based on user input. The problem i'm having is that Linq-to-SQL doesn't seem to like having multiple where clauses on the same field, it actually duplicates the search arg value for the last item on all parameters. I verified this behavior through a SQL trace. Here is what I'm seeing.
WHERE ([t22].[OpenText] LIKE #p11) AND ([t22].[OpenText] LIKE #p12)
-- #p11: Input NVarChar (Size = 10; Prec = 0; Scale = 0) [%classify%] // Should be 2da57652-dcdf-4cc8-99db-436c15e5ef50
-- #p12: Input NVarChar (Size = 10; Prec = 0; Scale = 0) [%classify%]
My code uses a loop to dynamically add the where clauses as you can see below. My question is how do I work around this? This pretty much seems like a bug with the tool, no?
// add dyanmic where clauses based on user input.
MatchCollection searchTokens = Helper.ExtractTokensWithinBracePairs(filterText);
if (searchTokens.Count > 0)
{
foreach(Match searchToken in searchTokens)
query = query.Where((material => material.OpenText.Contains(searchToken.Value)));
}
else
{
query = query.Where((material => material.OpenText.Contains(filterText)));
}
Closing over the loop variable considered harmful! Change
foreach(Match searchToken in searchTokens) {
query = query.Where(
material => material.OpenText.Contains(searchToken.Value)
);
}
to
foreach(Match searchToken in searchTokens) {
Match token = searchToken;
query = query.Where(
material => material.OpenText.Contains(token.Value)
);
}
You are closing over the loop variable, which is considered harmful. To fix do this:
foreach(Match searchToken in searchTokens)
{
Match searchToken2 = searchToken;
// ^^^^^^^^^^^^ copy the value of the reference to a local variable.
query = query.Where(material => material.OpenText.Contains(searchToken2.Value));
// use the copy here ^^^^^^^^^^^^
}
The reason why your version doesn't work is that the query refers to the variable searchToken, not the value it had when the query was created. When the variable's value changes, all your queries see the new value.
I don't have enough rep to leave comments yet (or this would be a comment and not an answer) but the answers listed here worked for me.
However, I had to turn off compiler optimizations in order for it to work. If you do not turn off compiler optimizations (at least at the method level) then the compiler sees you setting a loop variable to a local variable and throws the local variable away.