Is there a way to trim a TM_FILENAME beyond using TM_FILENAME_BASE? - visual-studio-code

I am trying to create a snippet for a redux container file that takes an import of some react file of the same base name. TM_FILENAME_BASE works great for removing the .js from the file name but in this case, my component file's extension is fun-thing.component.js and the container will follow suit with an extension that is fun-thing.container.js.
The Regex I am using to select everything before the first period is ^([^.]+)
"Redux Container": {
"prefix": "rc",
"body": [
"// #flow",
"import { connect } from 'react-redux';",
"import { ${TM_FILENAME/^([^.]+)/${1:/pascalcase}/}Component } from './${TM_FILENAME/^([^.]+)/$1/}.component';",
"",
"const mapStateToProps = (state) => ({});",
"",
"const mapDispatchToProps = {};",
"",
"export const ${TM_FILENAME/^([^.]+)/${1:/pascalcase}/} = connect(",
" mapStateToProps,",
" mapDispatchToProps",
")(${TM_FILENAME/^([^.]+)/${1:/pascalcase}/}Component);"
],
"description": "Creates a normal container for a normal component"
}
expected
// #flow
import { connect } from 'react-redux';
import { FunThingComponent } from './fun-thing.component';
...
actual
// #flow
import { connect } from 'react-redux';
import { FunThing.container.jsComponent } from './FunThing.container.js.component';
...
As you can see, it is not omitting the file extensions.

Both of these work:
"import { ${TM_FILENAME/^([^.]+).*/${1:/pascalcase}/}Component } from './${TM_FILENAME/^([^.]+).*/$1/}.component';",
"import { ${TM_FILENAME/(.*?)\\..+/${1:/pascalcase}/}Component } from './${TM_FILENAME/(.*?)\\..+/$1/}.component';"
With the vscode snippet transforms if you want to exclude part of the variable as you want, removing the .component.js from the filename, then that part of the variable must be accounted for in the regex - hence (.*?)\\..+.
Otherwise that "unseen" part of the variable just passes through.
So your regex ^([^.]+) was accurately capturing the part of the filename before the first . but then the rest of the variable was "passing through" unmodified.
You can see this more clearly with this example:
"import { ${TM_FILENAME//${1:/pascalcase}/}Component }
that yields:
import { fun-thing.component.jsComponent }
so the entire filename is passed through although none of it is captured.
${someVariable/everything To Be Transformed/what To Do To the previous/}
if it isn't in the "everything to be transformed" part nothing happens to it.

Related

How to apply multiple transforms to snippet variable

I'm in a file called event-list.tsx, and I'm trying to create a snippet that writes the following code:
const EventList: FC = () => {
return <div>
</div>;
};
export default EventList;
Thus far, in typescriptreact.json I've written the following snippet setting, which results in awkward-looking code (it puts out const event-list rather than const EventList
"react arrow func component": {
"prefix": "rafce",
"body": [
"const ${TM_FILENAME_BASE}: FC = () => {",
" return <div>",
" ",
" </div>;",
"};",
"",
"export default ${TM_FILENAME_BASE};",
""
]
},
I know how to remove the hyphen from the snippet:
${TM_FILENAME_BASE/-//}
I also figured out how to capitalize the first character:
${TM_FILENAME_BASE/(^.)/${1:/upcase}/}
But I can't figure out how to apply all three of the changes I want. I know the regular expression needed to capitalize every character that comes after a hyphen (a positive lookbehind), but I don't know how to apply it here. There is nothing in the documentation chapter implying the possibility to chain multiple transforms onto each other.
Try the following global regex
${TM_FILENAME_BASE/(.)([^-]*)-?/${1:/upcase}${2}/g}
Find a part before a - and Upcase the first letter, repeat for the whole string
"${TM_FILENAME_BASE/(\\w+)-?/${1:/capitalize}/g}",
(\\w+)-? : You only need one capture group if you use /capitalize.
The hyphens are removed by virtue of matching them (-?) but not including them in the output.
The g flag is necessary to keep matching every (\\w+)-? instance and perform a transform for each.
And since you are reusing an earlier transform you can simplify the whole thing like this:
"react arrow func component": {
"prefix": "rafce",
"body": [
"const ${1:${TM_FILENAME_BASE/(\\w*)-?/${1:/capitalize}/g}}: FC = () => {",
" return <div>",
" ",
" </div>;",
"};",
"",
"export default $1;",
""
]
},
Note that
${1:${TM_FILENAME_BASE/(\\w*)-?/${1:/capitalize}/g}}
stores the result of that transform in variable $1 - which can simply be used later (or earlier) by itself to output the same result!

Keep $ for Powershell variable in VS code snippet

I’m able to save my code snippets with tabbed spacing in VS code for Powershell, but it keeps ignoring my variables by not displaying the $ for my variables when I call the snippet. It will just paste in the name and omit the $.
How do you get VS code to paste in the $ when you select your code snippet?
Here is the VS Code JSON file I'm using for my "template" snippet
{
// Place your snippets for powershell here. Each snippet is defined under a snippet name and has a prefix, body and
// description. The prefix is what is used to trigger the snippet and the body will be expanded and inserted. Possible variables are:
// $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders. Placeholders with the
// same ids are connected.
// Example:
// "Print to console": {
// "prefix": "log",
// "body": [
// "console.log('$1');",
// "$2"
// ],
// "description": "Log output to console"
// }
"Template": {
"prefix": "template",
"body": [
"<#",
".SYNOPSIS",
"\t<Overview of script>",
"",
".SYNTAX",
"\t<Cmdlet-Name> -Parameter <value>",
"",
".DESCRIPTION",
"\t<Brief description of script>",
"",
".PARAMETER <Parameter_Name>",
"\t<Brief description of parameter input required. Repeat this attribute if required>",
"",
".INPUTS",
"\t<Inputs if any, otherwise state None>",
"",
".OUTPUTS",
"\t<Outputs if any, otherwise state None - example: Log file stored in C:\file.log>",
"",
".EXAMPLE",
"\t<Example goes here. Repeat this attribute for more than one example>",
"",
".REMARKS",
"\tVersion: 1.0",
"#>",
"",
"#---------------------------------------------------------[Variables]------------------------------------------------------------",
"",
"$var1 = <stuff>",
"$var2 = <stuff>",
"",
"#---------------------------------------------------------[Import Modules]--------------------------------------------------------",
"",
"Import-Module <name>",
"",
"#-----------------------------------------------------------[Functions]------------------------------------------------------------",
"",
"Function <FunctionName> {",
"\t[CmdletBindinging()]",
"\tparam(",
"\t\t[Parameter()]",
"\t\t[string]$MyOptionalParameter,",
"",
"\t\t[Parameter(Mandatory)]",
"\t\t[int]$MyMandatoryParameter",
"\t)",
"",
"\tTry{",
"\t\t<code goes here>",
"\t}",
"",
"\tCatch {",
"\t\tWrite-Host $Error.Exception",
"\t\t$Error.Exception | Out-File Out-File $env:TEMP\file.log",
"\t\tBreak",
"\t}",
"",
"\tFinally {",
"\t\t$time = Get-Date",
"\t\tcompleted at $time | Out-File $env:TEMP\file.log",
"\t}",
"}",
"",
"#-----------------------------------------------------------[Execution]------------------------------------------------------------",
"",
"<FunctionName>",
],
"description": "test"
}
}
When I call this snippet to paste the template into a new .ps1 file, it omits the all the $. How do you get those to stay?
Use \\$ inside a Visual Studio Code snippet body to embed a literal $.
For instance, to embed PowerShell variable $HOME, use \\$HOME.
Note: From the snippet parser's perspective, a single \ is required for escaping, but since snippets are defined as JavaScript strings, which themselves use \ as an escape character, \\ is need in order to pass a single \ through to the snippet parser.
See the docs.
As an aside:
Using $$ accidentally, somewhat works, but its purpose is not to escape, and it results in different behavior:
The location of a $$-prefixed identifier becomes a tab-stop, because Visual Studio Code interprets the sequence as follows:
The first $ becomes a literal[1], but the second $ and the identifier that follows is interpreted as a Visual Studio Code variable reference; if a built-in variable by that name doesn't exist, it is used as placeholder text.
[1] Any $ not followed by a valid Visual Studio Code placeholder name or variable reference is treated literally.

How to resolve "unresolved import" in Rust when using VS Code?

I'm fairly new to rust and have been following the official book that they provide on their site. During chapter 2 they tell you to import a "Rand" cargo which I did. However, when I try to run my code directly through VS Code I get an error saying "unresolved import rand". When I run it through command prompt, everything works fine. I've already tried every solution suggested here: https://github.com/rust-lang/rls-vscode/issues/513 and nothing seemed to have worked. Extensions that I'm using:
Better TOML
Cargo
Code Runner
Rust (rls)
Rust Assist
vsc-rustfmt
vscode-rust-syntax
Has anyone else ran into a similar problem or a know a solution? Thank you!
Edit: My Cargo.TOML looks like this:
[package]
name = "guessing_game"
version = "0.1.0"
authors = ["Name <MyNameHere#gmail.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
rand = "0.6.0"
Edit 2: my main.rs file looks like this:
use rand::Rng;
use std::io;
use std::cmp::Ordering;
fn main()
{
println!("Guess the number!");
let secret_number = rand::thread_rng().gen_range(1, 101);
loop
{
println!("Please input your guess!");
let mut guess = String::new();
io::stdin().read_line(&mut guess).expect("Failed to read line!");
let guess: u32 = match guess.trim().parse()
{
Ok(num) => num,
Err(_) => continue,
};
println!("Your guess {}", guess);
match guess.cmp(&secret_number)
{
Ordering::Less => println!("Too small!"),
Ordering::Greater => println!("Too big!"),
Ordering::Equal =>
{
println!("You win!");
break;
}
}
}
}
Got a fix!
In VSC, select Extensions, select the Code Runner extension, click the little gear symbol and select Extension Settings. It's the Code-runner: Executor Map setting that needs to be changed. Click the 'Edit in settings.json' link.
Add the following to the file:
"code-runner.executorMap": {
"rust": "cargo run # $fileName"
}
If you already have content in the settings.json file then remember to add a comma to the line above and put your edit inside the outermost curly braces, e.g.
{
"breadcrumbs.enabled": true,
"code-runner.clearPreviousOutput": true,
"code-runner.executorMap": {
"rust": "cargo run # $fileName"
}
}
This tells Code Runner to use the 'cargo run' command, instead of 'rustc'
This fix came from this question on stackoverflow.

Dependency not resolved correctly when Product (CodeGenerator) used in Rule ([asd] -> [cpp])

when using a Rule inside a Module with a Dependency to a Product, a FileTagger breaks the resolution of dependencies in qbs.
We have a CodeGenerator in our project which is build by the project itself.
This CodeGenerator generates C++-Classes from *.asd-Files.
A Product called "Core" uses that CodeGenerator to generate Classes from Core.asd Files.
I am not sure if this is a bug in qbs, but since qbs 1.8 this part of our project does not work anymore.
I created a small test project that illustrates that problem:
RuleUsesProduct.qbs
import qbs
Project {
minimumQbsVersion: "1.8.0"
references: [
"Core/Core.qbs",
"CodeGenerator/CodeGenerator.qbs"
]
qbsSearchPaths: "QBS"
}
Core.qbs
import qbs
CppApplication {
Depends { name: "Qt.core" }
cpp.cxxLanguageVersion: "c++11"
cpp.defines: [
]
consoleApplication: true
files: [
"main.cpp",
"core.asd"
]
Depends{ name:"CodeGenerator"}
Depends{ name:"CodeGeneration"}
Group { // Properties for the produced executable
fileTagsFilter: product.type
qbs.install: true
}
}
Db2cppModule.qbs
This is indirectly included via the qbsSearchPath from RuleUsesProductTest.qbs
import qbs 1.0
import qbs.Environment
import qbs.FileInfo
import qbs.TextFile
import qbs.Process
import qbs.File
Module {
FileTagger {
patterns: ["*.asd"]
fileTags: ["asd"]
}
Rule {
id: dbRule
inputs: ["asd"]
inputsFromDependencies: ["application"]
multiplex: true
outputFileTags: ["cpp", "hpp"]
outputArtifacts: {
// dummy code that should call the CodeGenerator.exe with some parameters...
var process = new Process();
console.warn("# " + inputs["application"][0].filePath)
var cmdExp = "" + inputs["application"][0].filePath;
process.exec(cmdExp, [], false);
return []
}
prepare: {
console.warn("*" + inputs["application"][0].filePath)
var cmdExp = "" + inputs["application"][0].filePath;
var cmd = new Command(cmdExp, []);
return cmd
}
}
}
CodeGenerator.qbs
import qbs
CppApplication {
Depends { name: "Qt.core" }
cpp.cxxLanguageVersion: "c++11"
cpp.defines: [
]
consoleApplication: true
files: [
"codegenerator.cpp"
]
Group { // Properties for the produced executable
fileTagsFilter: product.type
qbs.install: true
}
}
Any help is much appreciated!
Qbs knows two types of rules: Multiplex and non-multiplex ones. Details can be found here: https://doc.qt.io/qbs/rule-item.html.
The important point for you is that non-multiplex rules invoke their prepare script once for every input. This means that in your example, the prepare script runs twice: Once for the asd input and once for the application input. The respective other inputs are not visible. This does not fit your use case, because you want to see both inputs at the same time. Therefore, you need to make your rule a multiplex rule:
multiplex: true
In the prepare script, you need to create one command for every input of type asd (unless your generator can take several inputs at once).
Rule of thumb (no pun intended): If your rule declares more than one input tag, it probably should be a multiplex rule.

more than one defaction in the body?

All, can I run more than one defaction in the body of the rule? or can I only run one?
You can define as many actions in the pre block of a rule as you want. You can have as many actions in the action block of a rule as you want (just enclose the action block in curly braces). For example,
rule first_rule {
select when pageview ".*" setting ()
pre {
notify_one = defaction() { notify("notify_one", "First defaction"); };
notify_two = defaction() { notify("notify_two", "Second defaction"); };
}
{
notify_one();
notify_two();
}
}
So I think the answer to your question is yes.
Your question is a little confusing, but I'll give it a run.
Running actions defined with defaction is just like running system defined actions.
If you want to run more then one action in a rule, you need to wrap them in {} like so:
rule foo {
select when pageview ".*"
{
notify("cheese", "brie");
notify("apple", "golden delicious");
}
}
I seem to recall that a defaction has an implicit, optional 'pre' section, followed by the action(s). To include multiple actions you do need {} as Sam says.
act1 = defaction() {
{
notify("Defaction Demo", "<ul id='demo_id'></ul>");
append("#demo-id", "<li>cheese: brie</li>");
append("#demo-id", "<li>apple: golden delicious</li>");
}
};
That works out to defaction() { { ... } }; but the extra curly braces are required if you want more than one action in a defaction.
See also http://docs.kynetx.com/docs/Defaction