After discussing the pros and cons of generic and custom empty lines yesterday, let’s have a look at the steps required to implement custom empty lines. I provide them in the form of a checklist, similar to another language design pattern that I described earlier, Inline definitions.
To make the following text less abstract and easier to follow, I will use an example where we have a StatementList
concept that contains a multiple child statements of concept Statement, i.e. statements: Statement[0..n]. Assuming
that Statement is abstract and we want to add an EmptyStatement to represent an empty line, here is what we have to
do:
- Create
EmptyStatementconcept.- Structure:
EmptyStatementextendsStatement. - Editor:
EmptyStatement_Editorconsists of a single empty<constant>cell witheditable : truestyle. Making the cell editable will let the user convert (substitute) the empty statement with a non-empty one by typing.EmptyStatement_SubstituteMenu, the default substitution menu forEmptyStatement, is defined and left empty. This will causeEmptyStatementto be excluded from completion menus.
- Structure:
StatementList_Editor: the%statements%collection is modified to include an element factory that returnsnew node<EmptyStatement>. This will tell MPS to create a newEmptyStatementnode whenEnteris pressed, instead of creating the abstractStatement.- (Optional.) In
StatementList_Behaviorit may be useful to add a behavior method that filters out empty statements:public sequence<node<Statement>> nonEmptyStatements() { this.statements.where({~it => !it.isInstanceOf(EmptyStatement); }); }
And that’s all there is to it.
Some more improvements:
- Empty lines are good places for context assistant menu
placeholders, so if you use context assistant in your language, consider adding a placeholder after the empty constant
cell. This is illustrated in the
robot_KajaMPS sample. - If you use mbeddr platform, it provides interface
com.mbeddr.core.base.structure.IEmptythat can be used as a marker for empty lines. It also defines an empty default substitution menu so you don’t have to create one yourself if you extend the interface.