sbt-idea & sub-projects - scala

If, say, your sbt project contained 50 sub projects. Is it possible to generate an intellij project where you specify a set of the sub projects comes from your repo and for the other set of sub projects are actually contained in the project file ?
i.e. i'm looking to work on only a small subset of sub projects at a time and I know I won't need to change / compile the the other sub projects.
Thanks

You can define the following layout in project/Build.scala where you combine projects you're working on in meta project:
object MyBuild extends Build {
lazy val meta = Project(
id = "meta",
base = file(".")) aggregate(A,B) dependsOn(A,B)
lazy val A = Project(id = "A",base = file("A")))
lazy val B = Project(id = "B",base = file("B")))
... }
Then type project meta at sbt startup (if it is not meta already) and then gen-idea.
But every time you need to change projects set you're working on, you need to change meta definition and issue gen-idea.

Related

issue changing properties on project items using multi-project vstemplate with IWizard

I am creating a VSIX extension that generates a multi-project solution to be distributed. I would like to do several things to individual items I include in each projects vstemplate but think I may be taking the wrong approach. I have created a IWizard and am able to debug the solution. I added a custom item type to the project items in vstemplate in order to identify which ones I want to flag. I am then doing the following to change a ProjectItems Build Action from Content to Compile. I am still learning Visual Studio Extensability and have very limited experience using the objects so I apologize if the below is horrendous!
public void ProjectFinishedGenerating(Project project)
{
var myproject = (VSProject)project.Object;
foreach (ProjectItem pi in myproject.ProjectItems)
{
var myBuildAction = pi.Properties.Item("ItemType").Value;
if myBuildAction == "CompileContent")
pi.Properties.Item("ItemType").Value = "Compile";
}
}
This is my item in vstemplate
<VSTemplate Version="3.0.0" Type="Project" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005" xmlns:sdk="http://schemas.microsoft.com/developer/vstemplate-sdkextension/2010">
<ProjectItem TargetFileName="MyFolder\$ext_safeprojectname$\$ext_safeprojectname$_CodeFile.cs" ReplaceParameters="true" ItemType="CompileContent">CodeFile.cs</ProjectItem>

How to get all projects in a SBT task?

I'm writing a SBT task, which will get all projects of the whole project, then I can run some tasks against them.
The pseudo code is like:
val projects = someTaskToGetProjects.value
val updateReports = projects.map(p => (update in p).value)
But I can't find any task or setting to get the project list, how to do it?
I think buildDependencies might suit your needs, otherwise loadedBuild has everything.
val projects = buildDependencies.value.classpath.keys
val updateReports = projects.map(p => (update in p).value)

Playframework were to put files that get rendered in views

I am using the playframework to render Asciidoc text from a file inside my view.
Since that content is used in my view, I want to be able to put it in the app/views so it gets packaged when deploying with activator dist.
Right now the files get lost after running activator dist. Because the content gets rendered by my view I don't want to put in in public/ or in app/assets.
My view looks versy simple:
#(html: String)(implicit flash: Flash, lang: Lang)
#main(Messages("application.name")){
#Html(html)
}
And my controller sends the String content to the view:
def about = Action { implicit request =>
Ok(views.html.statics.normal(Static.render_file("app/views/adoc/about.adoc")))
}
Where should I put this file? and how to I access it other than with the path from the root?
You can put "internal" documents in the conf folder, it's the equivalent to resources in standard sbt projects.
To access it, you'd use Play.resourceAsStream(). Note that this gives you an java.io.InputStream because your file will be part of the JAR created by activator dist.
Play.resourceAsStream("adoc/about.adoc") map { adocStream =>
Ok(views.html.statics.normal(Static.render_file(adocStream)))
} getOrElse (InternalServerError)

Define Custom Source File Dependencies in SBT

How can I cause SBT to recompile some file A whenever another non-scala file B changes?
I have defined a macro:
printMacro("path/to/file")
which creates a string literal from the file indicated by "path/to/file".
Whenever that file changes, the file that uses that macro needs to be recompiled to reflect those changes. I can use watchSources to monitor that file for changes and recompile the project when it does, but because of the incremental compiler, this recompile doesn't actually do anything.
I'll almost certainly need to write a plugin to accomplish this, but I cannot find which hooks into sbt will enable me to write such a plugin.
EDIT: Recompiling the whole project isn't desirable, since there might be multiple tracked files and the project itself might be very large.
How about this solution, which is based on FileFunction.cached.
Basically define a function, which takes:
cachedBaseDirectory - the place where it's going to keep cache metadata
inStyle - which determines how it checks for changes
action - which is invoked when the observed file is changed
The function returns another function, which takes a set of monitored files.
def cached(cacheBaseDirectory: File, inStyle: FilesInfo.Style)(action: => Unit): Set[File] => Unit = {
import Path._
lazy val inCache = Difference.inputs(cacheBaseDirectory / "in-cache", inStyle)
inputs => {
inCache(inputs) { inReport =>
if(!inReport.modified.isEmpty) action
}
}
}
This is how you can use it in build.sbt
val recompileWhenFileChanges = taskKey[Unit]("Recompiles the project when a file changes")
recompileWhenFileChanges := {
val base = baseDirectory.value
val mySpecialFile = baseDirectory.value / "path" / "to" / "file" / "test.txt"
val cache = cacheDirectory.value / "my_cache_dir"
val cachedFunction = cached(cache, FilesInfo.lastModified)(IO.delete((classDirectory in Compile).value))
cachedFunction(mySpecialFile.get.toSet)
}
compile in Compile := ((compile in Compile) dependsOn recompileWhenFileChanges).value
The task deletes classDirectory only if the file is changed. Deleting the classDirectory makes the project to recompile.
Last we make the original compile to depend on our newly created task.

How can I create a custom project layout based on another eclipse plugin?

My ultimate goal is to create an eclipse plugin that sets up a PDT project, but with some added builders (and custom build scripts) as well as a specific folder layout (and different folders should be treated as source and some as regular folders).
I've looked at / followed eclipse plugin development tutorials, and ok. I get the gist of creating a wizard that creates a file, but I'm having trouble trying to figure out how to create a project, and more importantly, make that project associated with the PDT (PHP Development Tools) feature.
Answer:
I did stumble upon a solution myself before the answer was given, but it's quite similar.
First, WizardNewProjectCreationPage was used as the first page of my wizard.
Second, on performFinish() I ran the following code:
IProgressMonitor m = new NullProgressMonitor();
IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
IProject project = root.getProject(_pageOne.getProjectName());
if (!project.exists())
{
IProjectDescription desc = project.getWorkspace().newProjectDescription(project.getName());
URI projectLocation = _pageOne.getLocationURI();
// desc.setLocationURI(projectLocation);
String[] natures = desc.getNatureIds();
String[] newNatures = new String[natures.length + 1];
System.arraycopy(natures, 0, newNatures, 0, natures.length);
newNatures[natures.length] = PHPNature.ID;
desc.setNatureIds(newNatures);
project.create(desc, m);
project.open(m);
}
how to create a project
Take a look at BasicNewProjectResourceWizard.createNewProject() method.
make that project associated with the PDT (PHP Development Tools) feature
You need to add "org.eclipse.php.core.PHPNature" to the project (that's what Add PHP Support... action does). Use IProjectDescription.setNatureIds().