StringTemplate4 if conditional with length - stringtemplate

I need to generate the following kinds of code with StringTemplate4:
methodFoo0(Connection conn);
methodFoo1(Connection conn, int arg1);
methodFoo2(Connection conn, int arg1, int arg2);
etc.
The "Connection conn" part is always present so I am only passing the method name and the rest of the arguments to my ST template. My template looks as follows:
<methodName>(Connection conn, <args; separator=", ">);
This works but produces an extra comma when there are no arguments at all (except conn):
methodFoo0(Connection conn,);
To eliminate the extra comma I tried using the if conditional and the length ST4 function but I couldn't get it to work although I tried various combos like the following:
<methodName>(Connection conn <if (length(fieldsInFind) \> 0)>,<else><endif><fieldsInFind; separator=", ">)
... and others which they all failed with some parsing-related error (mismatched input).
In the end, I gave up and resorted to passing a comma parameter to the template which is either "," or the empty string "" based on pre-rendering logic.

You could check the presence of the second parameter using <if (fieldsInFind)> and only pass this to the template if its size is greater than 0.

The extra comma is not produced by the separator but it is the one you already typed after Connection conn,.
You do the following:
<methodName>(Connection conn<if(args)>,<args; separator=", "><endif>)
Notice the comma after the conn is only placed if there are in fact more arguments.

Related

How to pass variable in SQL from Powershell script? [duplicate]

I have a string that I want to insert dynamically a variable. Ex;
$tag = '{"number" = "5", "application" = "test","color" = "blue", "class" = "Java"}'
I want to accomplish:
$mynumber= 2
$tag = '{"number" = "$($mynumber)", "application" = "test","color" = "blue", "class" = "Java"}'
What I want is to have the variable inserted on the string, But it is not going through. I guess the '' sets all as a string. Any recomendations on how should I approach this?
thanks!
powershell test and trial and error. Also Google.
The reason your current attempt doesn't work is that single-quoted (') string literals in PowerShell are verbatim strings - no attempt will be made at expanding subexpression pipelines or variable expressions.
If you want an expandable string literal without having to escape all the double-quotes (") contained in the string itself, use a here-string:
$mynumber = 2
$tag = #"
{"number" = "$($mynumber)", "application" = "test","color" = "blue", "class" = "Java"}
"#
To add to Mathias' helpful answer:
Mistakenly expecting string interpolation inside '...' strings (as opposed to inside "...") has come up many times before, and questions such as yours are often closed as a duplicate of this post.
However, your question is worth answering separately, because:
Your use case introduces a follow-up problem, namely that embedded " characters cannot be used as-is inside "...".
More generally, the linked post is in the context of argument-passing, where additional rules apply.
Note: Some links below are to the relevant sections of the conceptual about_Quoting_Rules help topic.
In PowerShell:
only "..." strings (double-quoted, called expandable strings) perform string interpolation, i.e. expansion of variable values (e.g. "... $var" and subexpressions (e.g., "... $($var.Prop)")
not '...' strings (single-quoted, called verbatim strings), whose values are used verbatim (literally).
With "...", if the string value itself contains " chars.:
either escape them as `" or ""
E.g., with `"; note that while use of $(...), the subexpression operator never hurts (e.g. $($mynumber)), it isn't necessary with stand-alone variable references such as $mynumber:
$mynumber= 2
$tag = "{`"number`" = `"$mynumber`", `"application`" = `"test`",`"color`" = `"blue`", `"class`" = `"Java`"}"
Similarly, if you want to selectively suppress string interpolation, escape $ as `$
# Note the ` before the first $mynumber.
# -> '$mynumber = 2'
$mynumber = 2; "`$mynumber` = $mynumber"
See the conceptual about_Special_Characters help topic for info on escaping and escape sequences.
If you need to embed ' inside '...', use '', or use a (single-quoted) here-string (see next).
or use a double-quoted here-string instead (#"<newline>...<newline>"#):
See Mathias' answer, but generally note the strict, multiline syntax of here-strings:
Nothing (except whitespace) must follow the opening delimiter on the same line (#" / #')
The closing delimiter ("# / '#) must be at the very start of the line - not even whitespace may come before it.
Related answers:
Overview of PowerShell's expandable strings
Overview of all forms of string literals in PowerShell
When passing strings as command arguments, they are situationally implicitly treated like expandable strings (i.e. as if they were "..."-enclosed); e.g.
Write-Output $HOME\projects - see this answer.
Alternatives to string interpolation:
Situationally, other approaches to constructing a string dynamically can be useful:
Use a (verbatim) template string with placeholders, with -f, the format operator:
$mynumber= 2
# {0} is the placeholder for the first RHS operand ({1} for the 2nd, ...)
'"number" = "{0}", ...' -f $mynumber # -> "number" = "2", ...
Use simple string concatenation with the + operator:
$mynumber= 2
'"number" = "' + $mynumber + '", ...' # -> "number" = "2", ...

How to show an unknown list of variables and their values, if possible

As mentioned before in some questions with "Progress-4GL" and "OpenEdge" tags, I'm working with AppBuilder and Procedure editor. As a result, the debugging possibilities are extremely limited: for knowing the value of a variable, I need to do show them on screen, something like this:
MESSAGE "temp1=[" temp1 "], temp2=[" temp2 "]" VIEW-AS ALERT-BOX.
I can also put that information in a logfile, but that's not the main point here.
I would like to write a procedure, which can handle this, something like:
PROCEDURE SHOW_VARIABLES_AND_VALUES (INPUT I1, INPUT I2, ...):
1. <put parameter names and values together inside one string> => """I1="" I1"
2. <do this for all input parameters (the number is unknown)> => """I1="" I1, ""I2="" I2, ..."
3. <how to use this (MESSAGE VIEW-AS ALERT-BOX, LOG, ...) there I'll know what to do>
Does anybody know how to handle the fist two points (put variable name and value together and handle an unknown number of input parameters)?
Thanks in advance
You can use SUBSTITUTE function.
MESSAGE SUBSTITUTE ("temp1=&1 ~ntemp2=&2 ~n temp3=&3",
temp1,
temp2,
temp3) VIEW-AS ALERT-BOX.
Unfortunately there is no dynamic access to variables or parameters. So there's no way to automatically add all input parameters to a message string. Also there is no anytype parameter type in the ABL - for user defined functions or procedures. So you'd have to use the STRING() function a lot to convert your input parameters to string as the best fit parameter for everything.
The built in SUBSTITUTE function on the other hand can handle anytype of arguments. So temp1, temp2 and temp3 can actually be variables or parameters of any datatype.
As mentioned in one of my comments on one of your earlier questions: Give the OpenEdge debugger a chance. The debugger outside of Progress Developer studio looks historic. But it does it's job.
Meanwhile I've decided to use following system (as my request seems to be impossible):
MESSAGE "temp1=[" temp1 "]~n" ~
"temp2=[" temp2 "]~n" ~
"temp3=[" temp3 "]~n" ~
"temp4=[" temp4 "]" ~
VIEW-AS ALERT-BOX.
In order to make it easy to work with, I've found out the following keyboard "shortcut" for the tilde character: ALT+0126.
As indicated by Stefan, this is far better (no tilde and no shortcut needed):
MESSAGE "temp1=[" temp1 "]" SKIP
"temp2=[" temp2 "]" SKIP
"temp3=[" temp3 "]" SKIP
"temp4=[" temp4 "]" SKIP
VIEW-AS ALERT-BOX.

Printing Unnecessary escape character [duplicate]

I tried many ways to get a single backslash from an executed (I don't mean an input from html).
I can get special characters as tab, new line and many others then escape them to \\t or \\n or \\(someother character) but I cannot get a single backslash when a non-special character is next to it.
I don't want something like:
str = "\apple"; // I want this, to return:
console.log(str); // \apple
and if I try to get character at 0 then I get a instead of \.
(See ES2015 update at the end of the answer.)
You've tagged your question both string and regex.
In JavaScript, the backslash has special meaning both in string literals and in regular expressions. If you want an actual backslash in the string or regex, you have to write two: \\.
The following string starts with one backslash, the first one you see in the literal is an escape character starting an escape sequence. The \\ escape sequence tells the parser to put a single backslash in the string:
var str = "\\I have one backslash";
The following regular expression will match a single backslash (not two); again, the first one you see in the literal is an escape character starting an escape sequence. The \\ escape sequence tells the parser to put a single backslash character in the regular expression pattern:
var rex = /\\/;
If you're using a string to create a regular expression (rather than using a regular expression literal as I did above), note that you're dealing with two levels: The string level, and the regular expression level. So to create a regular expression using a string that matches a single backslash, you end up using four:
// Matches *one* backslash
var rex = new RegExp("\\\\");
That's because first, you're writing a string literal, but you want to actually put backslashes in the resulting string, so you do that with \\ for each one backslash you want. But your regex also requires two \\ for every one real backslash you want, and so it needs to see two backslashes in the string. Hence, a total of four. This is one of the reasons I avoid using new RegExp(string) whenver I can; I get confused easily. :-)
ES2015 and ES2018 update
Fast-forward to 2015, and as Dolphin_Wood points out the new ES2015 standard gives us template literals, tag functions, and the String.raw function:
// Yes, this unlikely-looking syntax is actually valid ES2015
let str = String.raw`\apple`;
str ends up having the characters \, a, p, p, l, and e in it. Just be careful there are no ${ in your template literal, since ${ starts a substitution in a template literal. E.g.:
let foo = "bar";
let str = String.raw`\apple${foo}`;
...ends up being \applebar.
Try String.raw method:
str = String.raw`\apple` // "\apple"
Reference here: String.raw()
\ is an escape character, when followed by a non-special character it doesn't become a literal \. Instead, you have to double it \\.
console.log("\apple"); //-> "apple"
console.log("\\apple"); //-> "\apple"
There is no way to get the original, raw string definition or create a literal string without escape characters.
please try the below one it works for me and I'm getting the output with backslash
String sss="dfsdf\\dfds";
System.out.println(sss);

Limitting character input to specific characters

I'm making a fully working add and subtract program as a nice little easy project. One thing I would love to know is if there is a way to restrict input to certain characters (such as 1 and 0 for the binary inputs and A and B for the add or subtract inputs). I could always replace all characters that aren't these with empty strings to get rid of them, but doing something like this is quite tedious.
Here is some simple code to filter out the specified characters from a user's input:
local filter = "10abAB"
local input = io.read()
input = input:gsub("[^" .. filter .. "]", "")
The filter variable is just set to whatever characters you want to be allowed in the user's input. As an example, if you want to allow c, add c: local filter = "10abcABC".
Although I assume that you get input from io.read(), it is possible that you get it from somewhere else, so you can just replace io.read() with whatever you need there.
The third line of code in my example is what actually filters out the text. It uses string:gsub to do this, meaning that it could also be written like this:
input = string.gsub(input, "[^" .. filter .. "]", "").
The benefit of writing it like this is that it's clear that input is meant to be a string.
The gsub pattern is [^10abAB], which means that any characters that aren't part of that pattern will be filtered out, due to the ^ before them and the replacement pattern, which is the empty string that is the last argument in the method call.
Bonus super-short one-liner that you probably shouldn't use:
local input = io.read():gsub("[^10abAB]", "")

Comma, ')',or valid expression continuation expected

I need my VB.net to write a file containing the following line
objWriter.WriteLine ("TEXTA " (FILEA) " TEXTB")
Unfortunatly the variable (FILEA) is causing problems i now get the error
Comma, ')', or valid expression continuation expected.
Could someone explain this please?
You're not concatenating (joining) the strings proerly...
objWriter.WriteLine ("TEXTA " & FILEA & " TEXTB")
A better style to get into the habit of using is:
objWriter.WriteLine (string.format("TEXTA {0} TEXTB", FILEA))
The FILEA variable replaces the {0} placeholder in the format string. Depending on what the writer you're using is, you may have a formatted overload so you could just do:
objWriter.WriteLine ("TEXTA {0} TEXTB", FILEA)
And since you asked for an explanation;
The compiler is asking you what exactly you want it to do - you've given it 3 variables (String, variable, String) and haven't told it that you want to join them together - It's saying that after the first string "TEXTA", there should either be the closing bracket (to end the method call), a comma (to pass another parameter to the method) OR a "valid continuation expression" - ie something that tells it what to do with the next bit. in this case, you want a continuation expression, specifically an ampersand to signify "concatenate with the next 'thing'".
Presumably you're looking for string concatenation? Try this:
objWriter.WriteLine("TEXTA" & FILEA & "TEXTB");
Note that FILEA isn't exactly a conventional variable name... which leads me to suspect there may be something else you're trying to achieve. Could you give more details?