├── .gitignore ├── README.md ├── build.sbt └── src └── main ├── resources ├── build.xml └── nbproject │ ├── build-impl.xml │ ├── genfiles.properties │ ├── private │ ├── config.properties │ ├── private.properties │ └── private.xml │ ├── project.properties │ └── project.xml └── scala └── netbeans ├── NetbeansCommands.scala ├── NetbeansPlugin.scala ├── NetbeansTasks.scala └── project ├── AntScript.scala ├── NetbeansConfigFile.scala ├── ProjectConfiguration.scala ├── ProjectContext.scala └── ProjectProperties.scala /.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | /build.xml 3 | /lib 4 | /manifest.mf 5 | /nbproject 6 | /project 7 | /target 8 | 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | **sbt-netbeans-plugin** is a plugin for simple-build-tool that allows working with SBT projects in Netbeans IDE. 2 | 3 | ### Installing the plugin 4 | 5 | You can either add sources of the plugin to `~/.sbt/plugins` or add a managed dependency to the plugin artifact (in the both cases, plugin will be globally available): 6 | 7 | $ cd ~/.sbt/plugins/ 8 | $ xsbt 9 | > set resolvers += ScalaToolsSnapshots 10 | > set resolvers += "remeniuk repo" at "http://remeniuk.github.com/maven" 11 | > set libraryDependencies += "org.netbeans" %% "sbt-netbeans-plugin" % "0.1.4" 12 | > update 13 | > session save 14 | > exit 15 | 16 | Version `0.1.4` is compatible with `Scala 2.9.1` and `SBT 0.11.1`. 17 | 18 | ### Older versions of the plugin 19 | 20 | Older versions of the plugin are available here: http://remeniuk.github.com/maven/org/netbeans/ 21 | 22 | ### Building from source 23 | 24 | Clone **sbt-netbeans-plugin**: 25 | 26 | $ git clone -n git://github.com/remeniuk/sbt-netbeans-plugin.git 27 | $ cd sbt-netbeans-plugin 28 | 29 | Publish to the local ivy repository: 30 | 31 | $ xsbt publish-local 32 | 33 | ### Using the plugin 34 | 35 | By default, any command is applied only to the current project. If you want to apply it to all the projects it depends on or aggregates, `transitive` command should be added (e.g., `netbeans create transitive` applied to the root project will create Netbeans files not only for the root, but also for all the dependencies, etc.). 36 | 37 | Create Netbeans files: 38 | 39 | > netbeans create 40 | 41 | ,or simply: 42 | 43 | > netbeans 44 | 45 | *Along with the Netbeans project files, `netbeans-update-dependencies` task is added to the project settings. This task is automatically triggered every time `update` is called, and checks, if Netbeans project classpath matches SBT classpath. If classpaths differ, `project.properties` is updated. Therefore, when you add a dependency (either managed or unmanaged), and call `update`, those dependencies are immediately plugged to the project and reflected in the IDE* 46 | 47 | **Now, you can open SBT project in Netbeans!** 48 | 49 | Create an empty source/resource folders: 50 | 51 | > netbeans create source-directories 52 | 53 | Update Netbeans files with SBT project settings: 54 | 55 | > netbeans update all 56 | 57 | ,or: 58 | 59 | > netbeans update 60 | 61 | If you don't want to add `netbeans-update-dependencies` to the project settings, you will have to trigger update of the Netbeans project properties manually. In order to update only those files that contain project classpaths, use the following command: 62 | 63 | > netbeans update dependencies 64 | 65 | Remove Netbeans files: 66 | 67 | > netbeans remove 68 | 69 | ### Settings 70 | 71 | `sbtExecutable (sbt-executable)` - holds the name of SBT executable in your local environment (could be `sbt` on Linux, or `sbt.bat` on Windows). Default value is `sbt`. The setting can be modified through SBT console: 72 | 73 | set sbtExecutable := "xsbt" 74 | sesion save 75 | 76 | ## Credits 77 | 78 | Special thanks for contributed ideas and help with testing to: 79 | 80 | * Andrew Gaydenko 81 | * Ali Mukadam 82 | -------------------------------------------------------------------------------- /build.sbt: -------------------------------------------------------------------------------- 1 | organization := "org.netbeans" 2 | 3 | name := "sbt-netbeans-plugin" 4 | 5 | version := "0.1.5" 6 | 7 | sbtPlugin := true 8 | 9 | resolvers ++= Seq(ScalaToolsSnapshots, "Typesafe Repo" at "http://repo.typesafe.com/typesafe") 10 | 11 | libraryDependencies += "org.scalaz" %% "scalaz-core" % "6.0.4" 12 | 13 | publishArtifact in (Compile, packageDoc) := false 14 | 15 | publishMavenStyle := true 16 | 17 | projectID <<= (organization,moduleName,version,artifacts,crossPaths){ (org,module,version,as,crossEnabled) => 18 | ModuleID(org, module, version).cross(crossEnabled).artifacts(as : _*) 19 | } 20 | 21 | publishTo := Some(Resolver.file("ghrepo", new File("/home/remeniuv/projects/remeniuk.github.com/maven"))(Patterns(true, Resolver.mavenStyleBasePattern))) 22 | -------------------------------------------------------------------------------- /src/main/resources/build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Builds, tests, and runs the project sbt-netbeans-plugin. 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | You must set the main class for the main 'run' task. Change Compile to Test to set it for 'test:run': 41 | mainClass in (Compile, run) := Some({main.class}) 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | Add -Xrunjdwp:transport=dt_socket,address={jpda.address} as an argument 51 | to the SBT (specifying desired `jpda.address`), attach debugger and run the file. 52 | 53 | 54 | 55 | 56 | 57 | Add -Xrunjdwp:transport=dt_socket,address={jpda.address} as an argument 58 | to the SBT (specifying desired `jpda.address`), attach debugger and run the project. 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /src/main/resources/nbproject/build-impl.xml: -------------------------------------------------------------------------------- 1 | 2 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | Must set src.dir 148 | Must set test.src.dir 149 | Must set build.dir 150 | Must set dist.dir 151 | Must set build.classes.dir 152 | Must set dist.javadoc.dir 153 | Must set build.test.classes.dir 154 | Must set build.test.results.dir 155 | Must set build.classes.excludes 156 | Must set dist.jar 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | Must set javac.includes 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | Must set javac.includes 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | Must select some files in the IDE or set javac.includes 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | To run this application from the command line without Ant, try: 456 | 457 | 458 | 459 | 460 | 461 | 462 | java -cp "${run.classpath.with.dist.jar}" ${main.class} 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | To run this application from the command line without Ant, try: 487 | 488 | java -jar "${dist.jar.resolved}" 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | Must select one file in the IDE or set run.class 513 | 514 | 515 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | 529 | 530 | 531 | 532 | 533 | 534 | 535 | 536 | Must select one file in the IDE or set debug.class 537 | 538 | 539 | 540 | 541 | Must set fix.includes 542 | 543 | 544 | 545 | 546 | 547 | 548 | 553 | 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 | 563 | 564 | 565 | 566 | 567 | 568 | 573 | 574 | 575 | 576 | 577 | 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 | 592 | 593 | 594 | 595 | 596 | 597 | 598 | 599 | Must select some files in the IDE or set javac.includes 600 | 601 | 602 | 603 | 604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 616 | 617 | 618 | 619 | 620 | 621 | 622 | 623 | Some tests failed; see details above. 624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | Must select some files in the IDE or set test.includes 633 | 634 | 635 | 636 | Some tests failed; see details above. 637 | 638 | 639 | 644 | 645 | Must select one file in the IDE or set test.class 646 | 647 | 648 | 649 | 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | 675 | 676 | Must select one file in the IDE or set applet.url 677 | 678 | 679 | 680 | 681 | 682 | 683 | 688 | 689 | Must select one file in the IDE or set applet.url 690 | 691 | 692 | 693 | 694 | 695 | 696 | 697 | 702 | 703 | 704 | 705 | 706 | 707 | 708 | 709 | 710 | 711 | 712 | 713 | 714 | -------------------------------------------------------------------------------- /src/main/resources/nbproject/genfiles.properties: -------------------------------------------------------------------------------- 1 | build.xml.data.CRC32=f84bcc79 2 | build.xml.script.CRC32=bb95f086 3 | build.xml.stylesheet.CRC32=ca9d572e@1.4 4 | # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. 5 | # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. 6 | nbproject/build-impl.xml.data.CRC32=f84bcc79 7 | nbproject/build-impl.xml.script.CRC32=c4e21bf1 8 | nbproject/build-impl.xml.stylesheet.CRC32=5220179f@1.4 9 | -------------------------------------------------------------------------------- /src/main/resources/nbproject/private/config.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/remeniuk/sbt-netbeans-plugin/582e75817cfea8f49dec3e3d8d06e0592794f3e4/src/main/resources/nbproject/private/config.properties -------------------------------------------------------------------------------- /src/main/resources/nbproject/private/private.properties: -------------------------------------------------------------------------------- 1 | compile.on.save=false 2 | do.depend=false 3 | do.jar=true 4 | javac.debug=true 5 | javadoc.preview=true 6 | -------------------------------------------------------------------------------- /src/main/resources/nbproject/private/private.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/main/resources/nbproject/project.properties: -------------------------------------------------------------------------------- 1 | application.title=sbt-netbeans-plugin 2 | file.reference.main-scala= 3 | file.reference.test-scala= 4 | dist.dir=target 5 | dist.jar=${dist.dir}\\scala_2.8.1\\sbt-netbeans-plugin_2.8.1-0.1.jar 6 | build.classes.dir=${build.dir}/classes 7 | build.classes.excludes=**/*.java,**/*.form,**/*.scala 8 | # This directory is removed when the project is cleaned: 9 | build.dir=target 10 | build.generated.dir=${build.dir}/generated 11 | # Only compile against the classpath explicitly listed here: 12 | build.sysclasspath=ignore 13 | build.test.classes.dir=${build.dir}/test/classes 14 | build.test.results.dir=${build.dir}/test/results 15 | debug.classpath=\ 16 | ${run.classpath} 17 | debug.test.classpath=\ 18 | ${run.test.classpath} 19 | # This directory is removed when the project is cleaned: 20 | dist.javadoc.dir=${dist.dir}/scaladoc 21 | includes=** 22 | excludes=**/boot/scala-*/ , **/src_managed/, **/lib_managed/, **/*.lock, **/*.log, **/*.jar, **/*.pom, **/target/, boot/, plugins/project/ , plugins/target/ 23 | jar.compress=false 24 | java.platform.active=java_default_platform 25 | # Space-separated list of extra javac options 26 | javac.compilerargs= 27 | javac.deprecation=false 28 | javac.source=1.5 29 | javac.target=1.5 30 | javadoc.additionalparam= 31 | javadoc.author=false 32 | javadoc.encoding=${source.encoding} 33 | javadoc.noindex=false 34 | javadoc.nonavbar=false 35 | javadoc.notree=false 36 | javadoc.private=false 37 | javadoc.splitindex=true 38 | javadoc.use=true 39 | javadoc.version=false 40 | javadoc.windowtitle= 41 | main.class= 42 | manifest.file=manifest.mf 43 | meta.inf.dir=${src.dir}/META-INF 44 | platform.active=default_platform 45 | run.classpath=\ 46 | ${javac.classpath}:\ 47 | ${build.classes.dir} 48 | # Space-separated list of JVM arguments used when running the project 49 | # (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value 50 | # or test-sys-prop.name=value to set system properties for unit tests): 51 | run.jvmargs= 52 | run.test.classpath=\ 53 | ${javac.test.classpath}:\ 54 | ${build.test.classes.dir} 55 | # Space-separated list of extra scalac options 56 | scalac.compilerargs= 57 | scalac.deprecation=no 58 | scalac.unchecked=no 59 | source.encoding=UTF-8 60 | src.dir=${file.reference.main-scala} 61 | src.java.dir=${file.reference.main-java} 62 | test.src.dir=${file.reference.test-scala} 63 | resources.dir= 64 | test.resources.dir= 65 | sources.sbt.project=project -------------------------------------------------------------------------------- /src/main/resources/nbproject/project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | org.netbeans.modules.scala.project 4 | 5 | 6 | ${application.title} 7 | 1.6.5 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/main/scala/netbeans/NetbeansCommands.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this template, choose Tools | Templates 3 | * and open the template in the editor. 4 | */ 5 | 6 | package netbeans 7 | 8 | import sbt._ 9 | import sbt.complete.DefaultParsers._ 10 | 11 | object NetbeansCommands { 12 | 13 | import NetbeansPlugin._ 14 | import scalaz._ 15 | import Scalaz._ 16 | 17 | val create = for{c <- createNetbeansFiles(_); 18 | u <- updateAll(_)} yield c andThen u 19 | 20 | val createSourceDirs = for{c <- createSourceDirectories(_); 21 | u <- updateProjectConfig(_)} yield c andThen u 22 | 23 | /** If `transitive` is used, command is applied to all projects used by 24 | * current project */ 25 | val transitive = token(Space ~> ("transitive" ^^^ true)) ?? false 26 | 27 | val createOptions = "create" ~> (token(Space ~> ("source-directories" ^^^ createSourceDirs)) ?? create) 28 | 29 | val updateOptions = "update" ~> (token(Space ~> ("all" ^^^ updateAll _ | 30 | "dependencies" ^^^ updateProjectProperties _)) ?? updateAll _) 31 | 32 | val removeOptions = "remove" ^^^ removeNetbeansFiles _ 33 | 34 | val netbeansConsole = Space ~> 35 | (((createOptions | updateOptions | removeOptions) ~ transitive) map { 36 | case (command, transitive) => (command, transitive) 37 | }) ?? (create, true) 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/scala/netbeans/NetbeansPlugin.scala: -------------------------------------------------------------------------------- 1 | package netbeans 2 | 3 | import sbt._ 4 | import Keys._ 5 | import project._ 6 | import CommandSupport._ 7 | 8 | object NetbeansPlugin extends Plugin { 9 | 10 | val sbtExecutable = SettingKey[String]("sbt-executable") 11 | 12 | /** build.xml template under ./sbt/plugins (overrides the template in plugin jar) */ 13 | private val buildXmlTemplateLocation = (state: State) => BuildPaths.getGlobalPluginsDirectory(state, BuildPaths.defaultGlobalBase) / "src" / "main" / "resources" / "build.xml" 14 | /** project.properties template under ./sbt/plugins (overrides the template in plugin jar) */ 15 | private val projectFilesTemplateLocation = (state: State) => BuildPaths.getGlobalPluginsDirectory(state, BuildPaths.defaultGlobalBase) / "src" / "main" / "resources" / "nbproject" 16 | 17 | /** Extracts Netbeans project files templates from the plugin jar */ 18 | private def copyNetbeansFiles(basePath: File)(pluginJarPath: File) = 19 | IO.unzip(pluginJarPath, basePath, "*.xml" | "*.properties") 20 | 21 | /** Copies packed Netbeans project files templates to the project folder */ 22 | private def copyPackedTemplates(libClasspath: Seq[File], dest: File) = 23 | libClasspath.filter(_.getName.contains("sbt-netbeans-plugin")) 24 | .headOption.map(copyNetbeansFiles(dest)) 25 | 26 | /** Copies Netbeans project files templates from ./sbt/plugins */ 27 | private def copyUnpackedTemplates(dest: File, state: State) = { 28 | buildXmlTemplateLocation(state).get.map { template => 29 | IO.copy(Seq(template.asFile -> (dest / "build.xml").asFile), false) 30 | } 31 | projectFilesTemplateLocation(state).get.map { template => 32 | IO.copyDirectory(template.asFile, (dest / "nbproject").asFile, false) 33 | } 34 | } 35 | 36 | /** Adds sbt-netbeans commands globally */ 37 | override lazy val settings = Seq(commands += netbeansCommands) 38 | 39 | /** Updates Netbeans project files with SBT project settings */ 40 | private[netbeans] def updateNetbeansFiles(projectRef: ProjectRef, 41 | s: State, 42 | projectFiles: Seq[ProjectContext => NetbeansConfigFile]): State = { 43 | 44 | import scalaz.Scalaz._ 45 | 46 | s.log.info("Updating Netbeans files for project `%s`..." format(projectRef.project)) 47 | 48 | ProjectContext.netbeansContext(projectRef, s).map{context => 49 | projectFiles.map(_(context)).foreach{ projectFile => 50 | projectFile.validate.fold ({ errors => 51 | s.log.error("%s: failed to update %s" 52 | .format(projectRef.project, projectFile.description)) 53 | }, { _ => 54 | projectFile.store() 55 | s.log.info("%s: successfully updated %s" 56 | .format(projectRef.project, projectFile.description)) 57 | } 58 | ) 59 | } 60 | } 61 | 62 | s 63 | } 64 | 65 | /** Updates all Netbeans project files */ 66 | private[netbeans] def updateAll(projectRef: ProjectRef)(s: State): State = 67 | updateNetbeansFiles(projectRef, s, 68 | Seq((context => AntScript(context.baseDirectory / "build.xml")(context)), 69 | (context => ProjectConfiguration(context.baseDirectory / "nbproject" /"project.xml")(context)), 70 | (context => ProjectProperties(context.baseDirectory / "nbproject" / "project.properties")(context))) 71 | ) 72 | 73 | /** Updates project.properties */ 74 | private[netbeans] def updateProjectProperties(projectRef: ProjectRef)(s: State): State = 75 | updateNetbeansFiles(projectRef, s, Seq((context => ProjectProperties(context.baseDirectory / "nbproject" /"project.properties")(context)))) 76 | 77 | /** Updates project.xml */ 78 | private[netbeans] def updateProjectConfig(projectRef: ProjectRef)(s: State): State = 79 | updateNetbeansFiles(projectRef, s, Seq((context => ProjectConfiguration(context.baseDirectory / "nbproject" /"project.xml")(context)))) 80 | 81 | /** Creates empty source/resource directories */ 82 | private[netbeans] def createSourceDirectories(projectRef: ProjectRef)(s: State): State = { 83 | ProjectContext.netbeansContext(projectRef, s).map{context => 84 | s.log.info("Creating empty source directories for project `%s`..." format(projectRef.project)) 85 | 86 | IO.createDirectories(Seq( 87 | context.baseDirectory / "src" / "main" / "scala", 88 | context.baseDirectory / "src" / "test" / "scala", 89 | context.baseDirectory / "src" / "main" / "resources", 90 | context.baseDirectory / "src" / "test" / "resources" 91 | )) 92 | } 93 | s 94 | } 95 | 96 | /** Adds Netbeans project files to the SBT project */ 97 | private[netbeans] def createNetbeansFiles(projectRef: ProjectRef)(s: State): State = { 98 | val extracted = Project extract s 99 | import extracted._ 100 | 101 | s.log.info("Creating Netbeans files for project `%s`" format(projectRef.project)) 102 | for{base <- baseDirectory in (projectRef, Compile) get structure.data}{ 103 | copyPackedTemplates(currentUnit.unit.plugins.classpath, 104 | base) 105 | copyUnpackedTemplates(base, s) 106 | } 107 | 108 | if(session.original.filter(_.key.key.label == NetbeansTasks.updateDepTaskKey).isEmpty){ 109 | s.log.info("Writing plugin settings for project `%s`" format(projectRef.project)) 110 | NetbeansTasks.writePluginSettings(projectRef, structure) 111 | s.reload 112 | } else s 113 | } 114 | 115 | /** Removes Netbeans project files from the SBT project */ 116 | private[netbeans] def removeNetbeansFiles(projectRef: ProjectRef)(s: State): State = { 117 | val extracted = Project extract s 118 | import extracted._ 119 | 120 | s.log.info("Removing Netbeans files from project `%s`" format(projectRef.project)) 121 | (baseDirectory in (projectRef, Compile) get structure.data) map { base => 122 | IO.delete((base / "build.xml" +++ base / "nbproject").get) 123 | } 124 | 125 | s 126 | } 127 | 128 | type NetbeansCommand = ProjectRef => State => State 129 | 130 | lazy val netbeansCommands = 131 | Command("netbeans")(_ => NetbeansCommands.netbeansConsole) { (state: State, output: Any) => 132 | output match { 133 | case (cmd: NetbeansCommand, transitive: Boolean) => 134 | val extracted = Project extract state 135 | val s = cmd(extracted.currentRef)(state) 136 | if(transitive){ 137 | state.log.info("Executing command transitively...") 138 | (s /: extracted.currentProject.uses) {(_s, _ref) => cmd(_ref)(_s)} 139 | } else s 140 | case other => 141 | state.log.error("Failed to process command line: " + other) 142 | state.fail 143 | } 144 | } 145 | 146 | } 147 | -------------------------------------------------------------------------------- /src/main/scala/netbeans/NetbeansTasks.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this template, choose Tools | Templates 3 | * and open the template in the editor. 4 | */ 5 | 6 | package netbeans 7 | 8 | import sbt._ 9 | import Keys._ 10 | import java.nio.charset.Charset 11 | import project._ 12 | import CommandSupport._ 13 | import NetbeansPlugin._ 14 | 15 | object NetbeansTasks { 16 | 17 | val exportedSettings = Seq("seq(netbeans.NetbeansTasks.netbeansSettings:_*)") 18 | 19 | val updateDepTaskKey = "netbeans-update-dependencies" 20 | 21 | val netbeansUpdateDependencies = TaskKey[Any](updateDepTaskKey) 22 | 23 | val netbeansSettings = Seq( 24 | sbtExecutable := "sbt", 25 | netbeansUpdateDependencies <<= updateProjectPropertiesTask triggeredBy(update) 26 | ) 27 | 28 | /** Updates project properties, if project classpath has changed */ 29 | def updateProjectPropertiesTask = (baseDirectory, fullClasspath in Compile, thisProjectRef, state) map { (base, classpath, projectRef, s) => 30 | val pluginCachePath = base / "nbproject" / "netbeans.cache" 31 | 32 | s.log.info("Triggered update dependencies task for proect %s" format(projectRef)) 33 | 34 | val cachedClasspath = (pluginCachePath.get.map{ path => 35 | val classpathCache = IO.readLines(path, Charset.defaultCharset).mkString(":") 36 | s.log.info("Cache file exists: %s" format(classpathCache)) 37 | classpathCache 38 | }).headOption.getOrElse("") 39 | 40 | val currentClasspath = classpath.files.mkString(":") 41 | 42 | if(currentClasspath != cachedClasspath){ 43 | s.log.info("Updating classpath: %s" format(currentClasspath)) 44 | IO.write(pluginCachePath, currentClasspath.getBytes) 45 | updateProjectProperties(projectRef)(s) 46 | } 47 | } 48 | 49 | /** Persists plugin settings in SBT project config */ 50 | def writePluginSettings(pref: ProjectRef, structure: sbt.Load.BuildStructure) = { 51 | val project = Project.getProject(pref, structure).getOrElse(sys.error("Invalid project reference " + pref)) 52 | val appendTo: File = BuildPaths.configurationSources(project.base).headOption.getOrElse(new File(project.base, "build.sbt")) 53 | val baseAppend = exportedSettings.flatMap("" :: _ :: Nil) 54 | val adjustedLines = if(appendTo.isFile && !SessionSettings.needsTrailingBlank(IO readLines appendTo) ) baseAppend else "" +: baseAppend 55 | IO.writeLines(appendTo, adjustedLines, append = true) 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/main/scala/netbeans/project/AntScript.scala: -------------------------------------------------------------------------------- 1 | package netbeans.project 2 | 3 | import netbeans.NetbeansPlugin 4 | import netbeans.NetbeansTasks 5 | import sbt._ 6 | import java.io.File 7 | import scala.xml.{Node, XML} 8 | import scala.xml.transform.{RuleTransformer, RewriteRule} 9 | 10 | case class AntScript(originalFilePath: File)(implicit context: ProjectContext) extends NetbeansConfigFile{ 11 | 12 | val description = "Ant-script (build.xml)" 13 | 14 | lazy val operatingSystem = System.getProperty("os.name") 15 | 16 | private val scriptRewriter = new RuleTransformer(new RewriteRule { 17 | 18 | import context._ 19 | 20 | val extracted = Project.extract(currentState) 21 | 22 | val sbtExecutableName = (NetbeansPlugin.sbtExecutable in 23 | extracted.currentRef get 24 | extracted.structure.data).getOrElse("sbt") 25 | 26 | override def transform(n: Node): Seq[Node] = n match { 27 | case {children @ _*} => 28 | { 29 | children 30 | } 31 | 32 | case {args @ _*} => 33 | {args} 36 | 37 | case arg @ => 38 | 44 | 45 | case other => other 46 | } 47 | 48 | }) 49 | 50 | def store(outputFile: File): Unit = { 51 | val script = scriptRewriter(XML.loadFile(originalFilePath.asFile)) 52 | IO.write(outputFile.asFile, script.toString.getBytes) 53 | } 54 | 55 | } -------------------------------------------------------------------------------- /src/main/scala/netbeans/project/NetbeansConfigFile.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this template, choose Tools | Templates 3 | * and open the template in the editor. 4 | */ 5 | 6 | package netbeans.project 7 | 8 | import java.io.File 9 | import scalaz._ 10 | import Scalaz._ 11 | import sbt._ 12 | 13 | trait NetbeansConfigFile { 14 | 15 | val originalFilePath: File 16 | 17 | def description: String 18 | 19 | def validate = (originalFilePath.get.toList match { 20 | case Nil => originalFilePath.fail 21 | case head :: tail => this.success 22 | }).liftFailNel 23 | 24 | def store(outputFile: File = originalFilePath): Unit 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/scala/netbeans/project/ProjectConfiguration.scala: -------------------------------------------------------------------------------- 1 | package netbeans.project 2 | 3 | import scala.xml.{XML, Node, NodeSeq, Elem, UnprefixedAttribute, Null} 4 | import scala.xml.transform.{RewriteRule, RuleTransformer} 5 | import sbt._ 6 | import ProjectContext._ 7 | import java.io.File 8 | 9 | case class ProjectConfiguration(originalFilePath: File)(implicit context: ProjectContext) extends NetbeansConfigFile{ 10 | 11 | val description = "project configuration (nbproject/project.xml)" 12 | 13 | private val sourceRoots = { 14 | import context._ 15 | import src._ 16 | import res._ 17 | 18 | Map( 19 | ("src.dir", "Scala Source") -> scalaSource.isEmpty, 20 | ("src.java.dir", "Java Source") -> javaSource.isEmpty, 21 | ("resources.dir", "Resources") -> resources.isEmpty, 22 | ("sources.sbt.project", "Configuration") -> false 23 | ).filter(_._2 == false).keys 24 | } 25 | 26 | private val testRoots = { 27 | import context._ 28 | import src._ 29 | import res._ 30 | 31 | Map( 32 | ("test.src.dir", "Scala Test Sources") -> scalaTestSource.isEmpty, 33 | ("file.reference.test-java", "Java Test Sources") -> javaTestSource.isEmpty, 34 | ("test.resources.dir", "Test Resources") -> testResources.isEmpty 35 | ).filter(_._2 == false).keys 36 | } 37 | 38 | private val projectConfig = XML.loadFile(originalFilePath.asFile) 39 | 40 | private val projectConfigRuleTransformer = 41 | new RuleTransformer(new RewriteRule { 42 | val references = context.project.uses.flatMap(subProject => 43 | 44 | {subProject.project} 45 | jar 46 | 47 | jar 48 | clean 49 | jar 50 | 51 | ).toSeq 52 | 53 | override def transform(n: Node): Seq[Node] = 54 | n match { 55 | case {_} => 56 | {context.name} 57 | 58 | case Elem(prefix, "references", attribs, scope) => 59 | Elem(prefix, "references", attribs, scope, references:_ *) 60 | 61 | case {_*} => 62 | { 63 | sourceRoots.flatMap{case (id, name) => } 64 | } 65 | 66 | case {_*} => 67 | { 68 | testRoots.flatMap{case (id, name) => } 69 | } 70 | 71 | case other => other 72 | } 73 | 74 | 75 | }) 76 | 77 | def store(outputFile: File): Unit = 78 | IO.write(outputFile.asFile, projectConfigRuleTransformer(projectConfig).toString.getBytes) 79 | 80 | } 81 | -------------------------------------------------------------------------------- /src/main/scala/netbeans/project/ProjectContext.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this template, choose Tools | Templates 3 | * and open the template in the editor. 4 | */ 5 | 6 | package netbeans.project 7 | 8 | import java.io.File 9 | import sbt._ 10 | 11 | object ProjectContext{ 12 | 13 | import Keys._ 14 | import scalaz.Scalaz._ 15 | 16 | class EmptyPath(path: File){ 17 | def isEmpty = path.get.headOption.isEmpty 18 | } 19 | 20 | def toOption[T](res: Result[T]) = res match { 21 | case Value(r) => Some(r) 22 | case _ => None 23 | } 24 | 25 | implicit def fileToEmptyPath(file: File) = new EmptyPath(file) 26 | 27 | def projectSources(currentProjectRef: ProjectRef, s: State) = { 28 | val extracted = Project extract s 29 | import extracted._ 30 | 31 | val _mainClass = Project.evaluateTask(mainClass in (currentProjectRef, Compile, run), s) 32 | .flatMap(toOption).flatMap(x => x) 33 | 34 | (scalaSource in (currentProjectRef, Compile) get structure.data) |@| 35 | (scalaSource in (currentProjectRef, Test) get structure.data) |@| 36 | (javaSource in (currentProjectRef, Compile) get structure.data) |@| 37 | (javaSource in (currentProjectRef, Test) get structure.data) |@| 38 | Some(_mainClass) apply ProjectSources.apply 39 | } 40 | 41 | def projectResources(currentProjectRef: ProjectRef, s: State) = { 42 | val extracted = Project extract s 43 | import extracted._ 44 | 45 | (resourceDirectory in (currentProjectRef, Compile) get structure.data) |@| 46 | (resourceDirectory in (currentProjectRef, Test) get structure.data) apply ProjectResources.apply 47 | } 48 | 49 | def projectClasspaths(currentProjectRef: ProjectRef, s: State) = { 50 | val extracted = Project extract s 51 | import extracted._ 52 | 53 | ((Project.evaluateTask(externalDependencyClasspath in (currentProjectRef, Compile), s) |@| 54 | Project.evaluateTask(externalDependencyClasspath in (currentProjectRef, Test), s)) apply { (compCp, testCp) => 55 | (toOption(compCp) |@| toOption(testCp)) apply ProjectClasspaths.apply 56 | }).flatten.headOption 57 | } 58 | 59 | def netbeansContext(currentProjectRef: ProjectRef, s: State) = { 60 | val extracted = Project extract s 61 | import extracted._ 62 | 63 | Option(s) |@| 64 | (thisProject in (currentProjectRef, Compile) get structure.data) |@| 65 | (name in (currentProjectRef, Compile) get structure.data) |@| 66 | (baseDirectory in (currentProjectRef, Compile) get structure.data) |@| 67 | projectSources(currentProjectRef, s) |@| 68 | projectResources(currentProjectRef, s) |@| 69 | projectClasspaths(currentProjectRef, s) |@| 70 | Project.evaluateTask(scalaInstance in (currentProjectRef, Compile), s).flatMap(toOption) apply ProjectContext.apply 71 | } 72 | 73 | } 74 | 75 | case class ProjectSources(scalaSource: File, scalaTestSource: File, 76 | javaSource: File, javaTestSource: File, mainClass: Option[String]) 77 | case class ProjectResources(resources: File, testResources: File) 78 | case class ProjectClasspaths(compileClasspath: Keys.Classpath, testClasspath: Keys.Classpath) 79 | 80 | case class ProjectContext(currentState: State, project: ResolvedProject, name: String, 81 | baseDirectory: File, src: ProjectSources, res: ProjectResources, 82 | classpaths: ProjectClasspaths, scalaInstance: ScalaInstance){ 83 | 84 | protected def subprojectClasspath = 85 | project.uses 86 | .map(subProject => "${reference.%s.jar}".format(subProject.project)) 87 | 88 | val sbtJars = (baseDirectory \ "project" ** "sbt" ** "*.jar").get.map(_.absolutePath).toList 89 | val scalaJars = scalaInstance.jars 90 | 91 | val compileClasspathString = (subprojectClasspath ++ classpaths.compileClasspath.files ++ 92 | scalaJars ++ sbtJars).mkString(":") 93 | val testClasspathString = (classpaths.testClasspath.files ++ scalaJars).mkString(":") 94 | 95 | } 96 | -------------------------------------------------------------------------------- /src/main/scala/netbeans/project/ProjectProperties.scala: -------------------------------------------------------------------------------- 1 | package netbeans.project 2 | 3 | import java.nio.charset.Charset 4 | import java.util.Properties 5 | import sbt._ 6 | import java.io.File 7 | 8 | case class ProjectProperties(originalFilePath: File) 9 | (implicit context: ProjectContext) 10 | extends Properties with NetbeansConfigFile{ 11 | 12 | import context._ 13 | import src._ 14 | import res._ 15 | 16 | val description = "project properties (nbproject/project.properties)" 17 | 18 | val extracted = Project.extract(currentState) 19 | 20 | IO.reader(originalFilePath, Charset.defaultCharset)(load) 21 | 22 | protected def destPath(projectRef: ProjectRef) = 23 | (Keys.artifactPath in (projectRef, Keys.makePom) get extracted.structure.data) 24 | .map(_.absolutePath.replaceAll("\\.pom", ".jar")) 25 | 26 | private def subprojectProperties = { 27 | import scalaz.Scalaz._ 28 | 29 | project.uses.flatMap{subProject => 30 | ((Keys.artifactPath in (subProject, Keys.makePom) get extracted.structure.data) |@| 31 | (Keys.baseDirectory in subProject get extracted.structure.data)) { (_dest, _baseDirectory) => 32 | "reference." + subProject.project + ".jar" -> _dest.absolutePath.replaceAll("\\.pom", ".jar") :: 33 | "project." + subProject.project -> _baseDirectory :: 34 | Nil 35 | } getOrElse Nil 36 | } 37 | } 38 | 39 | def properties = Map( 40 | "application.title" -> name, 41 | "file.reference.main-scala" -> scalaSource, 42 | "file.reference.test-scala" -> scalaTestSource, 43 | "file.reference.main-java" -> javaSource, 44 | "file.reference.test-java" -> javaTestSource, 45 | "test.resources.dir" -> testResources, 46 | "resources.dir" -> resources, 47 | "javac.classpath" -> compileClasspathString, 48 | "javac.test.classpath" -> testClasspathString, 49 | "main.class" -> mainClass.getOrElse(""), 50 | "dist.jar" -> destPath(extracted.currentRef).getOrElse("") 51 | ) ++ subprojectProperties 52 | 53 | def store(outputFile: File): Unit = 54 | IO.writer(outputFile.asFile, "", Charset.defaultCharset, false) { content => 55 | properties.foreach(prop => setProperty(prop._1, prop._2.toString)) 56 | store(content, "Generated with sbt-netbeans-plugin") 57 | } 58 | } 59 | --------------------------------------------------------------------------------