File Template extension with IntelliJ plugin - scala

So I want to create a file template in my IntelliJ IDEA plugin and I managed to mine these out from some other plugins, but the template always wants to be a java file and I cannot change the extension of it to be .cqt insteaf of .java
What I figured out:
I need to add these to the plugin.xml
<internalFileTemplate name="Croquette File" />
and I need
<createFromTemplateHandler implementation="...CroquetteCreateFromTemplateHandler" />
with the file creation action
<action
id="Croquette.NewFile"
class="...NewCroquetteFileDefinitionAction"
text="Croquette File"
description="Create a new Croquette file" >
<add-to-group group-id="NewGroup" anchor="after" relative-to-action="NewGroup1"/>
</action>
The NewCroquetteFileDefinitionAction contains this:
class NewCroquetteFileDefinitionAction
extends CreateFileFromTemplateAction(
NewCroquetteFileDefinitionAction.NEW_CQT_FILE,
"",
CroquetteIcons.fileIcon)
with DumbAware {
import NewCroquetteFileDefinitionAction._
override def buildDialog(
project: Project,
directory: PsiDirectory,
builder: CreateFileFromTemplateDialog.Builder): Unit = {
builder
.setTitle(NEW_CQT_FILE)
.addKind("Croquette File", CroquetteIcons.fileIcon, "Croquette File")
.setValidator(new InputValidatorEx {
override def getErrorText(inputString: String): String =
if (!inputString.isEmpty && !containsFuckyCharacters(inputString))
s"'$inputString' is not a valid Croquette file name."
else null
override def checkInput(inputString: String): Boolean = getErrorText(inputString) != null
override def canClose(inputString: String): Boolean = checkInput(inputString)
})
}
override def getActionName(directory: PsiDirectory, newName: String, templateName: String): String = NEW_CQT_FILE
override def hashCode(): Int = 0
override def equals(obj: Any): Boolean = obj.isInstanceOf[NewCroquetteFileDefinitionAction]
}
object NewCroquetteFileDefinitionAction {
val NEW_CQT_FILE = "New Croquette File"
def containsFuckyCharacters(strIn: String): Boolean = {
List("+", "-", "<", ">", "\\", "/", ",", ".", "[", "]", "{", "}", "#", "&", "$", ";", "*").foreach(ch =>
if (strIn.contains(ch))
return true
)
false
}
}
And I am guessing I have to do something here in the CroquetteDefaultPropertiesProvider class but not sure what, or even if that guess is correct or not as I cannot find any documentation on how to create file templates with plugins.
class CroquetteDefaultPropertiesProvider extends TemplatePackagePropertyProvider {
override def fillProperties(directory: PsiDirectory, props: Properties) {
super.fillProperties(directory, props)
}
}

You need to put some Name.your-lang-extension.ft files under fileTemplates package, like this, and declare <internalFileTemplate name="Name" />, like this (this Name corresponds to the Name in Name.your-lang-extension.ft).
In the template files you may use some variables, there're some predefined ones and you can use your own. The syntax is ${MY_VAR}.
Then you should implement buildDialog like this, the third argument to addKind is the Name in Name.your-lang-extension.ft, the first one is the displayed name.
Then you should create a action class extending CreateFileFromTemplateAction, like this, and create a Properties instance by using FileTemplateManager.getInstance(project).defaultProperties like this and add some properties like this which will be filled in to the variables, like you can properties.add("MY_VAR", yourCodeToGetSomeInformation()) and ${MY_VAR} in your template will the replaced with the return value of yourCodeToGetSomeInformation().
After that you should implement createFileFromTemplate like this, the key part is the call to CreateFromTemplateDialog's create(), just look at my code example and you'll know.
After implementing the action class you should register it into plugin.xml just like what you're doing now.
BTW please remove your dangerously incorrect implementation of equals and hashCode.
You don't need a createFromTemplateHandler.

Related

Unable to write a CommonJS module in ScalaJS that gets "imported" in Atom editor as a plugin

What should i do if i want to export some ScalaJS methods as CommonJS module? I have the following but it doesn't seem to work:
#ScalaJSDefined
#JSExportTopLevel("default")
object SourceFetch extends js.Object {
def activate(state: js.Dynamic): Unit = {
global.console.log("activate")
}
def deactivate(): Unit = {
global.console.log("deactivate")
}
}
And yes, scalaJSModuleKind := ModuleKind.CommonJSModule is in the build.sbt.
What i want as output is a commonjs module that looks like this;
export default {
activate(state) {
console.log("activate");
}.
deactivate() {
console.log("deactivate");
}
};
What i ended up doing is to use the deprecated sbt key "scalaJSOutputWrapper" and append 'module.exports = exports["default"];' at the end of output JS file.
I did try "scalaJSUseMainModuleInitializer" but I am only able to get a hold of "module.exports" not "exports" and the value of "module.exports" is undefined.
Your above snippet does indeed correspond to the piece of ECMAScript 2015 code that you wrote. However, that does not export the methods as direct members of the module, but as members of the default object. And no, the default export is not the same as the module itself (although many people think so).
To export the functions as direct members of the module, you should write:
object SourceFetch {
#JSExportTopLevel("activate")
def activate(state: js.Dynamic): Unit = {
global.console.log("activate")
}
#JSExportTopLevel("deactivate")
def deactivate(): Unit = {
global.console.log("deactivate")
}
}

While creating Object, setting values to methods or variable without using def or val keyword

I come from a Java background and as expected, am having problem understanding some patterns used in Scala (see below). Every time I feel that I have a good understanding of Scala patterns or programming methodology, something pops up that is beyond my programming understanding and puts me back in learning mode. I guess that's a beauty of scala that always inspires me to keep learning :)
Anyway I trying to do some sample programming in scala swing.............
val frame = new MainFrame {
title = "Electronic Classroom"
contents = new BorderPanel {
layout += new GridPanel(1, 2) {
contents += new ScrollPane(semesterList)
contents += new ScrollPane(courseList)
} -> West
}
menuBar = new MenuBar {
contents += new Menu("File") {
contents += new MenuItem("Login") {
action = Action("Login"){
login
user match{
case Some(inst:Instructor) => instructorMenu.enabled = true
enabled = false
case Some(_) => instructorMenu.enabled = false
enabled = false
case _ =>
}
}
}
contents += new Separator
contents += new MenuItem(Action("Exit")(sys.exit(0)))
}
}
contents += instructorMenu
}
size = new Dimension(1000, 600)
centerOnScreen
}
Here we are setting values to def and val without using def or val keyword while defining them (like title, size, contents etc) and it's now looking more like a body script which is different that the way we do in java where all the assignments etc takes place in a method body.. I guess I am missing a big design pattern here
Can someone help, abd explain to me the Scala design pattern??
This is actually not very different from Java—instead of creating an instance and then customising it, you are creating anonymous sub classes. E.g.
val frame = new MainFrame {
title = "Electronic Classroom"
}
instead of
val frame = new MainFrame
frame.title = "Electronic Classroom"
The difference to Java is that since Scala doesn't have dedicated constructor methods but treats all expressions within the body of a class part of the constructor, your anonymous sub class kind of "overrides" the constructor.
To compare directly with Java, lets say it wasn't anonymous:
class MyMainFrame extends MainFrame {
title = "Electronic Classroom"
}
In Java, this would be roughly equivalent to:
public class MyMainFrame extends JFrame {
public MyMainFrame() {
super();
setTitle("Electronic Classroom");
}
}
(I hope this is valid Java syntax, I'm a bit rusty)
This is the same case for MenuBar, Menu, MenuItem. Only Action { ... } is not subclassing but calling method apply on the Action companion object, making the syntax a bit more succinct (this way you won't have "constructor" statements, e.g. you couldn't write accelerator = None and so forth).
I subscribe to 0__'s explanation, just wanting to add that if I recall correctly you can do the same in java with
JFrame frame = new JFrame {{
title = "Electronic Classroom";
}};
This should create an anonymous subclass with the additional code appended to the constructor

code generate with xtend in xtext project

I'm working on xtext project and I'm generating objects through .xtext file.
I want to add new attribute to one of the generated object.
I saw in http://christiandietrich.wordpress.com/2011/07/22/customizing-xtext-metamodel-inference-using-xtend2/
the following code is generating a temp variable in ObjectValue
but i want temp to be of type MyObject.
How to do so? where can i read about it?
import org.eclipse.emf.codegen.ecore.genmodel.GenModelPackage
import org.eclipse.emf.common.util.BasicEMap$Entry
import org.eclipse.emf.ecore.EClass
import org.eclipse.emf.ecore.EPackage
import org.eclipse.emf.ecore.EcoreFactory
import org.eclipse.emf.ecore.EcorePackage
import org.eclipse.xtext.GeneratedMetamodel
import org.eclipse.xtext.xtext.ecoreInference.IXtext2EcorePostProcessor
class CodeGeneratorClass implements IXtext2EcorePostProcessor {
override process(GeneratedMetamodel metamodel) {
metamodel.EPackage.process
}
def process(EPackage p) {
for (c : p.EClassifiers.filter(typeof(EClass))) {
if (c.name == "ObjectValue") {
c.handle
}
}
}
def handle (EClass c) {
val attr = EcoreFactory::eINSTANCE.createEAttribute
attr.name = "temp"
attr.EType = EcorePackage::eINSTANCE.EString
c.EStructuralFeatures += attr
}
}
First: MyObject must be described either by an EClass or an EDataType. A plain Java Object won't do it.
If MyObject is an EDataType then you must add an EAttribute in the handle method. Your handle method is almost right, only the EType must be adjusted:
attr.EType = MyPackage::eINSTANCE.MyObject
Otherwise: If MyObject is an EClass then you must add an EReference instead of an EAttribute. The handle method for this case looks like this:
def handleReference(EClass c){
val ref = EcoreFactory::eINSTANCE.createEReference
ref.name = "temp"
ref.EType = MyPackage::eINSTANCE.MyObject
c.EStructuralFeatures += ref
}
EDIT
In order to define a new, minimal EDataType and hook it up into the model the following snippet should work:
def void process(GeneratedMetamodel it){
// create new dynamic EDataType
val dataType = EcoreFactory::eINSTANCE.createEDataType => [
name = 'MyObject'
instanceTypeName = 'java.package.with.MyObject'
]
// register new EDataType in own model package
EPackage.EClassifiers += dataType
// attach as EAttribute to appropriate EClasses
EPackage.EClassifiers.filter(typeof(EClass)).filter[name == 'ObjectValue'].forEach[
EStructuralFeatures += EcoreFactory::eINSTANCE.createEAttribute => [
name = "temp"
EType = dataType
]
]
}

Omit empty attributes with groovy DOMBuilder

Groovy's MarkupBuilder has an omitNullAttributes and an omitEmptyAttributes. But DOMBuilder doesn't. This is the code I have
>>> def xml = DOMBuilder.newInstance()
>>> def maybeEmpty = null
>>> println xml.foo(bar: maybeEmpty)
<foo bar=""/>
I want bar to be omitted if empty. I found a workaround in an answer to Groovy AntBuilder, omit conditional attributes... to findAll empty attributes and remove them. Since I have a complex DOM to be generated, I'm looking for other options.
I believe there is no built-in option for that, but if you need a DOMBuilder, you could subclass it and filter the attributes...
#groovy.transform.InheritConstructors
class DOMBuilderSubclass extends groovy.xml.DOMBuilder {
#Override
protected Object createNode(Object name, Map attributes) {
super.createNode name, attributes.findAll{it.value != null}
}
}
You might want to tune the construction as in standard DOMBuilder, this is just an example.
def factory = groovy.xml.FactorySupport.createDocumentBuilderFactory().newDocumentBuilder()
def builder = new DOMBuilderSubclass(factory)
println builder.foo(bar: null, baz: 1)
//<?xml version="1.0" encoding="UTF-8"?>
//<foo baz="1"/>
standard output as you said was...
println groovy.xml.DOMBuilder.newInstance().foo(bar: null, baz: 1)
//<?xml version="1.0" encoding="UTF-8"?>
//<foo bar="" baz="1"/>

How do I update an HTML class from a CometActor

In response to some asynchronous event on the server, I want to update the class of an HTML node in order to reflect its updated status. I know the id of the node, and the class I want to change it to. What JsCmd do I need to use to update the class? In general, where can I find a good reference on the JsCmd's and what they do?
A simple example:
case class UpdateClass(id: String, htmlClass: String)
class ClassUpdater extends CometActor {
override def lowPriority: scala.PartialFunction[scala.Any, scala.Unit] = {
case UpdateClass(id, htmlClass) =>
partialUpdate(Noop /* now what? */)
}
def render = NodeSeq.Empty
}
So if I had the HTML:
<html><body>
<lift:comet type="ClassUpdater"/>
<div id="foo" class="bar">insert text here</div>
</body></html>
If I sent the message UpdateClass("foo", "baz") to my ClassUpdater, I want the class of my div to change to baz.
Edit: I’ve found a better way to do it. The old code is now more of a blueprint for more complicated stuff.
Looks like there is a more straightforward way of doing it without jQuery:
SetElemById("foo", JE.Str("baz"), "className")
which translates to a JavaScript call
document.getElementById("foo").className = "baz";
Note that JE.Str("baz") can be any JsExp and if you could also do something like
SetElemById("foo", JE.Str("baz"), "firstChild", "className")
which would change the class of the first child. (See: SetElemById)
You can have a look at the code for the JsCMD trait for what else is possible with build-in commands.
In case you want to something more complicated, however, something like this might help you. It sends a jQuery command which will change the class in #oldId to newClass.
case class ChangeClassAtId(oldId: String, newClass: String) extends JsCmd {
def toJsCmd = """try {
$(""" + ("#" + oldId).encJs + """).attr("class", """ + newClass.encJs + """);
} catch (e) {}"""
}
Changing all occurrences of a class everywhere is a bit more complicated:
case class ChangeClass(oldClass: String, newClass: String) extends JsCmd {
def toJsCmd = """try {
$(""" + ("." + oldClass).encJs + """).each(function(){
$(this).addClass(""" + newClass.encJs + """).removeClass(""" + oldClass.encJs + """);
});
} catch (e) {}"""
}
You should use it instead of Noop of course.
EDIT - I misread the question. My answer merely updates the contents of the div.
Check out: http://github.com/lift/lift/blob/master/examples/example/src/main/scala/net/liftweb/example/comet/Clock.scala
You'll want something like this:
case UpdateClass(id, htmlClass) =>
partialUpdate(SetHtml(id, Text("TEXT TO SHOVE INTO DIV")))