Team blog

Ceylon command-line plugins

With Ceylon we try our best to make every developer’s life easier. We do this with a great language, a powerful IDE, a wonderful online module repository, but also with an amazing command-line interface (CLI).

Our command line is built around the idea of discoverability where you get a single executable called ceylon and lots of subcommands that you can discover via --help or completion. We have a number of predefined subcommands, but every so often, we want to be able to write new subcommands.

For example, I want to be able to invoke both Java and JavaScript compilers and generate the API documentation in a single command ceylon all, or I want to be able to invoke the ceylon.formatter module with ceylon format instead of ceylon run ceylon.formatter.

Well, with Ceylon 1.1 we now support custom subcommands, fashioned after the git plugin system. They’re easy to write: just place them in script/your/module/ceylon-foo and package them with ceylon plugin pack your.module, and you can publish them to Herd.

Now every one can install your CLI plugin with ceylon plugin install your.module/1.0 and call them with ceylon foo.

What’s even better is that they will be listed in the ceylon --help and even work with autocompletion.

ceylon.formatter uses one, and I encourage you to install them with ceylon plugin install ceylon.formatter/1.1.0 and format your code at will with ceylon format :)

ceylon.build.engine also defines one and it just feels great being able to build your Ceylon project with ceylon build compile, I have to say. Although, unfortunately that particular module has not yet been published to Herd yet, but hopefully it will be pushed soon.

You can find out all about them in our reference.

Planning the future of Ceylon 1.x

With the release of Ceylon 1.1, we've reached a point where we need to do some serious thinking about what are our priorities for the development of Ceylon 1.1.5, 1.2, and beyond. I definitely don't yet have a crystal clear vision of what is going to be in 1.2, so we're also looking for community feedback on this.

I do know of one item which is the top priority right now, and will be the main feature of Ceylon 1.1.5:

This was a feature that slipped from Ceylon 1.0, and which again narrowly missed out on inclusion in Ceylon 1.1. The concept behind serialization in Ceylon is to have an API responsible for assembling and disassembling objects that is agnostic as to the actual format of the serialized stream. Of course, this API also has to be platform neutral, in order to allow serialization between programs running on the JVM and programs running on a JavaScript VM. Tom Bentley already has a working prototype implementation. Once this feature is done, we can start working on serialization libraries supporting JSON and whatever else.

I also count the following as a high priority areas of work:

  • Java EE integration, and support for technologies like JPA and CDI.
  • Adding properties to the language, that is, a new syntax for attribute references, allowing easy MVC UI bindings.
  • Improving the Cayla web framework, and ceylon.html.

Beyond that, we're not sure where else we should concentrate development effort. Here are some things that stick out to me:

  • Addition of named constructors, allowing multiple ways to instantiate and initialize a class.
  • AST transformers—a system of compiler plugins, based around ceylon.ast, enabling advanced compile-time metaprogramming, which would form the foundation for LINQ-style queries, interceptors and proxies, and autogeneration of equals(), hash, and string, and more.
  • Addition of a syntax for expressing patterns in BNF.
  • The Ceylon plugin for IntelliJ IDEA.
  • Android support.
  • Assemblies—a facility for packaging multiple modules into a deployable "application".
  • New platform modules defining dynamic interfaces for typesafe interaction with JavaScript APIs such as the DOM, jQuery, etc.
  • Interoperation with dynamic languages on the JVM, via Ceylon's dynamic blocks and dynamic interfaces.
  • Enabling the use of Ceylon for scripting.

We can't do all of this in Ceylon 1.2. Therefore, we're looking for feedback from the community. Let us know, here in comments, or on the mailing list, what you feel is missing from Ceylon, either from the above list, or whatever else you think is important.

Typesafe APIs for the browser

A new feature in Ceylon 1.1, that I've not blogged about before, is dynamic interfaces. This was something that Enrique and I worked on together with Corbin Uselton, one of our GSoC students.

Ordinarily, when we interact with JavaScript objects, we do it from within a dynamic block, where Ceylon's usual scrupulous typechecking is suppressed. The problem with this approach is that if it's an API I use regularly, my IDE can't help me get remember the names and signatures of all the operations of the API.

Dynamic interfaces make it possible to ascribe static types to an untyped JavaScript API. For example, we could write a dynamic interface for the HTML 5 CanvasRenderingContext2D like this:

dynamic CanvasRenderingContext2D {
    shared formal variable String|CanvasGradient|CanvasPattern fillStyle;
    shared formal variable String font;

    shared formal void beginPath();
    shared formal void closePath();

    shared formal void moveTo(Integer x, Integer y);
    shared formal void lineTo(Integer x, Integer y);

    shared formal void fill();
    shared formal void stroke();

    shared formal void fillText(String text, Integer x, Integer y, Integer maxWidth=-1);

    shared formal void arc(Integer x, Integer y, Integer radius, Float startAngle, Float endAngle, Boolean anticlockwise);
    shared formal void arcTo(Integer x1, Integer y1, Integer x2, Float y2, Integer radius);

    shared formal void bezierCurveTo(Integer cp1x, Integer cp1y, Integer cp2x, Float cp2y, Integer x, Integer y);

    shared formal void strokeRect(Integer x, Integer y, Integer width, Integer height);
    shared formal void fillRect(Integer x, Integer y, Integer width, Integer height);
    shared formal void clearRect(Integer x, Integer y, Integer width, Integer height);

    shared formal CanvasGradient createLinearGradient(Integer x0, Integer y0, Integer x1, Integer y1);
    shared formal CanvasGradient createRadialGradient(Integer x0, Integer y0, Integer r0, Integer x1, Integer y1, Integer r1);
    shared formal CanvasPattern createPattern(dynamic image, String repetition);

    //TODO: more operations!!
}

dynamic CanvasGradient {
    shared formal void addColorStop(Integer offset, String color);
}

dynamic CanvasPattern {
    //todo
}

Now, if we assign an instance of JavaScript's CanvasRenderingContext2D to this interface type, we won't need to be inside a dynamic block when we call its methods. You can try it out in your own browser by clicking the "TRY ONLINE" button!

CanvasRenderingContext2D ctx;
dynamic {
    //get the CanvasRenderingContext2D from the 
    //canvas element using dynamically typed code
    ctx = ... ;
}

//typesafe code, checked at compile time 
ctx.fillStyle = "navy";
ctx.fillRect(50, 50, 235, 60);
ctx.beginPath();
ctx.moveTo(100,50);
ctx.lineTo(60,5);
ctx.lineTo(75,75);
ctx.fill();
ctx.fillStyle = "orange";
ctx.font = "40px PT Sans";
ctx.fillText("Hello world!", 60, 95);

Notice that we don't need to ascribe an explicit type to every operation of the interface. We can leave some methods, or even just some parameters of a method untyped, by declaring them dynamic. Such operations may only be called from within a dynamic block, however.

A word of caution: dynamic interfaces are a convenient fiction. They can help make it easier to work with an API in your IDE, but at runtime there is nothing Ceylon can do to ensure that the object you assign to the dynamic interface type actually implements the operations you've ascribed to it.

Write in Ceylon, deploy as OSGI, use in Java EE

... or how to use Ceylon inside Java EE application servers.

The Ceylon language is inherently modular, and is shipped with a complete infrastructure that allows leveraging this modularity out-of-the box. However Ceylon is not captive of its own infrastructure. After the Java and JS interoperability efforts, the 1.1.0 version has brought out-of-the-box compatibility with OSGI, which enables running Ceylon code inside many other containers.

Every module archive produced by the Ceylon compiler contains OSGI headers in its MANIFEST file, that describe the module as it should seen by OSGI containers.

Containers tested so far are:

  • Apache Felix 4.4.1,
  • Oracle Glassfish v4.1,
  • Equinox platform,
  • JBoss WildFly 8.0.0.alpha3 (with JBossOSGi installed)

Of course, the Ceylon distribution and SDK modules should first be added inside the OSGI container as OSGI bundles.

But instead of writing long explanations here, let me direct you to some concrete examples provided, with the required instructions, in the following repository:

https://github.com/davidfestal/Ceylon-Osgi-Examples/

For the moment, it contains a single example that, though very simple, will give you the main steps to start.

It also shows the use of a Ceylon module totally outside Ceylon's standard infrastructure, even outside the JBoss world, in a Web application servlet running on a Glassfish v4.1 application server. But of course you should be able to run it inside other OSGI-enabled application servers or containers.

In the next examples we'll try to go further an do more interesting things such as providing services, using Ceylon annotations (which are compatible with Java annotations), or using OSGI services.

Please report any problem you might encounter while testing, and feel free to submit pull requests for any other successful use cases you might have built.

Looking forward for your remarks, and for the time to write the following examples.

Ceylon 1.1.0 is now available

Ten whole months in the making, this is the biggest release of Ceylon so far! Ceylon 1.1.0 incorporates oodles of enhancements and bugfixes, with well over 1400 issues closed.

Ceylon is a modern, modular, statically typed programming language for the Java and JavaScript virtual machines. The language features a flexible and very readable syntax, a unique and uncommonly elegant static type system, a powerful module architecture, and excellent tooling, including an awesome Eclipse-based IDE.

Ceylon enables the development of cross-platform modules that execute portably in both virtual machine environments. Alternatively, a Ceylon module may target one or the other platform, in which case it may interoperate with native code written for that platform.

For the end user, the most significant improvements in Ceylon 1.1 are:

  • performance enhancements, especially to compilation times in the IDE,
  • even smoother interoperation with Java overloading and Java generics,
  • out of the box support for deployment of Ceylon modules on OSGi containers,
  • enhancements to the Ceylon SDK, including the new platform modules ceylon.promise, ceylon.locale, and ceylon.logging, along with many improvements to ceylon.language, ceylon.collection, and ceylon.test,
  • many new features and improvements in Ceylon IDE, including
  • ceylon.formatter, a high-quality code formatter written in Ceylon,
  • support for command line tool plugins, including the new ceylon format and ceylon build plugins, and
  • integration with vert.x.

A longer list of changes may be found here.

In the box

This release includes:

  • a complete language specification that defines the syntax and semantics of Ceylon in language accessible to the professional developer,
  • a command line toolset including compilers for Java and JavaScript, a documentation compiler, and support for executing modular programs on the JVM and Node.js,
  • a powerful module architecture for code organization, dependency management, and module isolation at runtime,
  • the language module, our minimal, cross-platform foundation of the Ceylon SDK, and
  • a full-featured Eclipse-based integrated development environment.

Language

Ceylon is a highly understandable object-oriented language with static typing. The language features:

  • an emphasis upon readability and a strong bias toward omission or elimination of potentially-harmful or potentially-ambiguous constructs and toward highly disciplined use of static types,
  • an extremely powerful and uncommonly elegant type system combining subtype and parametric polymorphism with:
    • first-class union and intersection types,
    • both declaration-site and use-site variance, and
    • the use of principal types for local type inference and flow-sensitive typing,
  • a unique treatment of function and tuple types, enabling powerful abstractions, along with the most elegant approach to null of any modern language,
  • first-class constructs for defining modules and dependencies between modules,
  • a very flexible syntax including comprehensions and support for expressing tree-like structures, and
  • fully-reified generic types, on both the JVM and JavaScript virtual machines, and a unique typesafe metamodel.

More information about these language features may be found in the feature list and quick introduction.

This release introduces the following new language features:

  • support for use-site variance, enabling complete interop with Java generics,
  • dynamic interfaces, providing a typesafe way to interoperate with dynamically typed native JavaScript code,
  • type inference for parameters of anonymous functions that occur in an argument list, and
  • a Byte class that is optimized by the compiler.

Language module

The language module was a major focus of attention in this release, with substantial performance improvements, API optimizations, and new features, including the addition of a raft of powerful operations for working with streams.

The language module now includes an API for deploying Ceylon modules programmatically from Java.

The language module is now considered stable, and no further breaking changes to its API are contemplated.

Command line tools

The ceylon command now supports a plugin architecture. For example, type:

ceylon plugin install ceylon.formatter/1.1.0

To install the ceylon format subcommand.

IDE

This release of the IDE features dramatic improvements to build performance, and introduces many new features, including:

  • a code formatter,
  • seven new refactorings and many improvements to existing refactorings,
  • many new quick fixes/assists,
  • IntelliJ-style "chain completion" and completion of toplevel functions applying to a value,
  • a rewritten Explorer view, with better presentation of modules and modular dependencies,
  • synchronization of all keyboard accelerators with JDT equivalents,
  • Quick Find References, Recently Edited Files, Format Block, Visualize Modular Dependencies, Open in Type Hierarchy View, Go to Refined Declaration, and much more.

SDK

The platform modules, recompiled for 1.1.0, are available in the shared community repository, Ceylon Herd.

This release introduces the following new platform modules:

  • ceylon.promise, cross-platform support for promises,
  • ceylon.locale, a cross-platform library for internationalization, and
  • ceylon.logging, a simple logging API.

In addition, there were many improvements to ceylon.collection, which is now considered stable, and to ceylon.test.

The Ceylon SDK is available from Ceylon Herd, the community module repository.

Vert.x integration

mod-lang-ceylon implements Ceylon 1.1 support for Vert.x 2.1.x, and may be downloaded here.

Community

The Ceylon community site, http://ceylon-lang.org, includes documentation, and information about getting involved.

Source code

The source code for Ceylon, its specification, and its website is freely available from GitHub.

Issues

Bugs and suggestions may be reported in GitHub's issue tracker.

Acknowledgement

We're deeply indebted to the community volunteers who contributed a substantial part of the current Ceylon codebase, working in their own spare time. The following people have contributed to this release:

Gavin King, Stéphane Épardaud, Tako Schotanus, Emmanuel Bernard, Tom Bentley, Aleš Justin, David Festal, Max Rydahl Andersen, Mladen Turk, James Cobb, Tomáš Hradec, Ross Tate, Ivo Kasiuk, Enrique Zamudio, Roland Tepp, Diego Coronel, Daniel Rochetti, Loic Rouchon, Matej Lazar, Lucas Werkmeister, Akber Choudhry, Corbin Uselton, Julien Viet, Stephane Gallès, Paco Soberón, Renato Athaydes, Michael Musgrove, Flavio Oliveri, Michael Brackx, Brent Douglas, Lukas Eder, Markus Rydh, Julien Ponge, Pete Muir, Henning Burdack, Nicolas Leroux, Brett Cannon, Geoffrey De Smet, Guillaume Lours, Gunnar Morling, Jeff Parsons, Jesse Sightler, Oleg Kulikov, Raimund Klein, Sergej Koščejev, Chris Marshall, Simon Thum, Maia Kozheva, Shelby, Aslak Knutsen, Fabien Meurisse, Sjur Bakka, Xavier Coulon, Ari Kast, Dan Allen, Deniz Türkoglu, F. Meurisse, Jean-Charles Roger, Johannes Lehmann, Alexander Altman, allentc, Nikolay Tsankov, Chris Horne, gabriel-mirea, Georg Ragaller, Griffin DeJohn, Harald Wellmann, klinger, Luke, Oliver Gondža, Stephen Crawley.