How can I select a part of TM_DIRECTORY variable? - visual-studio-code

I want to select a part of the TM_DIRECTORY variable on VScode snippet. I mean I want to select Tests\Setup of the d:\Projects\Hakhsin\hakhsin\tests\Setup in code-snippet file. Look at this:
// On snippet file
"PHP Class": {
"scope": "",
"prefix": ["phpClass"],
"body": [
"<?php\n\nnamespace ${TM_DIRECTORY/(?<=(?:[\w:\\]hakhsin\\)).+(?=\\)//};\n\nclass ${TM_FILENAME_BASE} {\n\t$2\n}"
],
"description": "New PHP Class"
},
And I want to get this result:
namespace Tests\Setup;
class StorageFactory {
}
But I get this result:
<?php
namespace d:\Projects\Hakhsin\hakhsin\tests\Setup;
class StorageFactory {
}

It doesn't appear you can use variables inside of other variables in a snippet transform.
You can try this code which is more "dynamic" than yours but not perfect:
"${TM_DIRECTORY/([^\\\\]*\\\\){4}(.*)/${2:/capitalize}/}",
The {4} in that is if you have 4 segments in the directory structure before the part you want, like d:\Projects\Hakhsin\hakhsin\tests\Setup The segments are d:\, Projects\, Hakhsin\ and hakhsin\. If that number of segments is known and stable than the snippet I showed works well.
I doubt the number of those segments would vary within a project but might very well between projects - you would just have to change the {x} item for each project if so.

I solved it but it is not dynamic.
namespace ${TM_DIRECTORY/(.*hakhsin\\\\)(.*)/${2:/capitalize}/};
Is there a better way? anything like this:
namespace ${TM_DIRECTORY/(.*${WORKSPACE_NAME}\\\\)(.*)/${2:/capitalize}/};
This is the result:
<?php
namespace Tests\Setup;
class StorageFactory {
}

Related

VSCode - Make custom user snippets overwriting default suggestion

To match my company's coding standards, I'm making custom snippets like so:
// php.json
{
"If block": {
"prefix": ["if"],
"body": ["if ( ${1:condition} )", "{", "\t$0", "}"],
"description": "if block",
},
// ...
}
Then, when I type if + Tab, I have two suggestions:
I'm forced to press enter to actually select the first one, which is my custom made snippet ; the second being PHP's default snippet.
Is there a way to actually ignore PHP's default snippets in case I have the exact same prefix?

Variable does not expand in transformation

I am working on a VS code extension for a custom language. This contains a snippet that allows the user to create a function with parameters and start to set up some documentation inside the function. The way I am achieving this is to use variable transforms on the parameter variable (${2}) using some matching tricks to extract each individual parameter and data type. In this simpler example, each parameter name will be on its own line inside a block comment.
"function": {
"prefix": "func",
"body": [
"function ${1:functionName}(${2:params})",
"${2/([^,]+), *|([^,]+$)/\t${BLOCK_COMMENT_START} ${1}${2} ${BLOCK_COMMENT_END}\n/g}",
"end"
]
}, ...
The expected output is this:
function functionName(hello,world)
{ hello }
{ world }
end
The actual output is this:
function functionName(hello,world)
${BLOCK_COMMENT_START} hello ${BLOCK_COMMENT_END}
${BLOCK_COMMENT_START} world ${BLOCK_COMMENT_END}
end
The issue is that ${BLOCK_COMMENT_START} and _END do not expand inside the transform. I can easily get around this issue by hardcoding the curly braces in the snippet, but I would prefer to find a way where I do not have to do that.
"body": [
"function ${1:functionName}(${2:params})",
"${2/([^,]+), *|([^,]+$)/\t{ ${1}${2} }\n/g}",
"end"
]
Is there a way that I can have a variable expand in the transform?

Using TypeScript with Dojo - import/export issues

In the company I work for we are using Dojo framework and lately I have started pushing to use it with TypeScript.
I took a look around and found this great article on how this topic, you can find it here:
https://gregwiechec.com/2016/01/creating-dojo-widget-in-typescript/
The last 2 lines in this solution are:
var exp = _declare("alloy.editors.StringListTs", [_Widget, _TemplatedMixin, _WidgetsInTemplateMixin, _CssStateMixin, _ValueRequiredMixin], new StringList());
export = exp;
I followed the same pattern and it works great, except for 2 issues that I cant seem to have a good solid solution:
1. If you look at the solution, when calling dojo declare method, the class created needs to be instantiated (this is because dojo looks at properties and not prototype).
2. The more problematic issue, is the fact that I am exporting out the dojo declared object, and not the class it self. This is problematic when you try to import the class (typescript import), and even if I declare the variable exp as the class type, I get an error saying that there is no constructor to what i am trying to import.
I faced your same problem, and for me has been a transpiler issue.
TL;DR if you import something using the import * as WidgetName from '<path>' syntax and don't use WidgetName in the js (like you would do for a widget in a template), the transpiler won't import it. Use import '<path>' instead.
Long answer: It's my first time with TypeScript and, similarly you, I'm converting a dojo project to TypeScript. Hoping to help more people, I'll put few steps which helped me to import modules correctly.
Step 0 dojoConfig packages
Defining you own package on dojoConfig won't work, modules must be referenced using relative path.
To be clear, with this example:
dojoConfig = {
...
packages : [ { name : "myproject", location : "js/myproject" },
{ name : "dojo", location : dojoBase+"dojo" },
{ name : "dijit", location : dojoBase+"dijit" },
{ name : "dojox", location : dojoBase+"dojox" } ]
};
It's not possible to have widget importing each other with import * as WidgetName from 'myproject/WidgetName' approach, but rather you have to import * as WidgetName from './WidgetName' (notice the '.' vs 'myproject').
Step 1: importing dojo declaration (not mandatory, as far as I noticed)
I'm relying on node, I pulled dojo-typing using npm install dojo-typings --save-dev. In the files property I specified [ "src/js/**/*.ts", "src/js/**/*.js", "node_modules/dojo-typings/dojo/1.11/index.d.ts", "node_modules/dojo-typings/dojo/1.11/modules.d.ts", "node_modules/dojo-typings/dijit/1.11/index.d.ts", "node_modules/dojo-typings/dijit/1.11/modules.d.ts" ].
Step 2: using the correct options on the transpiler:
{
"target": "es5",
"allowJs": true,
"module": "amd",
"moduleResolution": "classic",
"noImplicitUseStrict" : true
},
noImplicitUseStrict solved the error dojo/parser::parse() error TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them. allowJs allowed me to mix TypeScript and native dojo together.
Step 3: returning using export
This is an example of a very minimal module which doesn't require/import anything, but only exports a log method (file would be 'toast.ts'):
const log = function(message) {
window['dojo'].publish("mainTopic",
[{
message: "<span style='font-size: 12px;'>" + message +"</span>",
type: 'info',
duration: 3000
}]
);
}
export { log }
For completeness, in pure Dojo you would have written something like (file would be 'toast.js'):
define([ ],
function(){
var log = function(message) {
dojo.publish("mainTopic",
[{
message: "<span style='font-size: 12px;'>" + message +"</span>",
type: 'info',
duration: 3000
}]
);
};
return { log : log };
});
Step 4: rewrite your widget and import it correctly
I use a Main widget which takes all the body, here the content of Main.ts:
/// <amd-dependency path="dojo/text!./Main.html" name="template" />
declare var template: string;
import * as _Widget from 'dijit/_Widget';
import * as _TemplatedMixin from 'dijit/_TemplatedMixin';
import * as _WidgetsInTemplateMixin from 'dijit/_WidgetsInTemplateMixin';
import * as dojoDeclare from 'dojo/_base/declare';
import './MyVanillaJavascriptWidget';
import './MyModule';
import 'dojox/widget/Toaster';
import toast = require('./utility/toast');
export default dojoDeclare("mm.Main", [ _Widget, _TemplatedMixin, _WidgetsInTemplateMixin ], {
templateString : template,
});
There are different types of imports:
the first is the one I struggled the most, for the template
import * as ... is a sequence of dojo objects I use in the class
import '<path>' is used for widget I declared in the template using data-dojo-type
import name = require('<path>') is another way to require modules
For completeness, this would be the original Main.js file:
define([ "dijit/_Widget", "dijit/_TemplatedMixin", "dijit/_WidgetsInTemplateMixin",
"dojo/_base/declare", "dojo/text!./Main.html",
"dojox/widget/Toaster", "./MyVanillaJavascriptWidget", "./MyModule"
],
function( _Widget, _TemplatedMixin, _WidgetsInTemplateMixin, declare, mainTemplate, toast) {
return declare("mm.Main", [ _Widget, _TemplatedMixin, _WidgetsInTemplateMixin ], {
templateString : mainTemplate,
});
});
Conclusion: The missing constructor most probably comes from the way you import a module, checking the transpiled code helped me to understand where the issue was. To succeed with the import, a bit of accuracy is needed here and there (all the steps above should give an overview).
I'm still in the process of converting my project (other issues may come out), but I hope this helps also other poor souls trying to use TypeScript with Dojo!

jqGrid adding a class to column by function

There's similar question here, but using cellatrr for whole column is quite overloaded. I know there's classes attribute, but it can be only set by static text. I would like to use a function instead like:
$("#jqgrid").jqGrid({
...
colModel:
[
{
name:'a',
index:'a',
classes: function() {
return (a < b ? "ui-state-error" : "ui-state-highlight");
}
]
});
Any ideas? Of course without modding jqGrid core :)
'title'=>'Name',
'name'=>'name',
'classes'=>'your class'
may be you can useful. check below link
http://guriddo.net/documentation/php/_2v70w5p2k.htm

Silverstripe - assign Template to Controller manually

at the moment I´m working with a custom Silverstripe Controller with a Director rule:
---
Name: myroutes
After: framework/routes#coreroutes
---
Director:
rules:
'category/$Action/$Slug': 'Category_Controller'
The Controller looks like that:
class Category_Controller extends Page_Controller {
public function show($arguments) {
echo "Slug: " . $arguments->param("Slug");
}
}
When I open in the browser the URL http://mysite.com/category/show/mobile
then the output look fine like this: "Slug: mobile".
I just wonder how I can use a Category.ss Template from the Folder "themes/templates/Layout" to render the Output. Then of course the container html (with header/footer) from Page.ss should be included as well. Just as usual when you have a custom Page Controller/Class and a corresponding Template in the Layout Folder.
I just tried this:
public function show($arguments) {
echo $this->renderWith("Category");
}
It uses Category.ss for rendering the output, but there is no container html...
Thx for any help.
Regards,
Florian
you can also pass an array to renderWith(), and it will try through the array until it finds a template.
so lets say $this->renderWith(array('Category', 'Page'));
it will first look for a template called Category.ss, but will not find it (in the templates folder, not layout folder), it will then find Page.ss and use it.
Now it hits $Layout inside Page.ss and it checks the array again inside the Layout folder, it will now find the Category.ss, which is exactly what you where looking for if I got the question right.
if you do not want to do return $this->renderWith(); you can also just do return $this; and silverstripe will get the action you called and the class hierarchy of $this and use that as array for renderWith()
So if your classes are Category_Controller > Page_Controller > ContentController the array will look like this:
array(
'Category_show', // because your action is show
'Category',
'Page_show',
'Page',
'ContentController_show',
'ContentController',
)
(I am not a 100% sure if it also includes Page_show and ContentController_show.)