Indentation relative to n-th column of the line

Here is the case:

I have an indent processor for perl code, that works fine and i'd like to re-use it in some perl-based templating language. In this language perl lines may start from the % sign at the beginning of the line, like:


% if( $a == 1) {

<div>some html here</div>

% }

I need to make formatter to check indention and to indent lines not relative to the beginning of the line, but relative to the first char %.

It's not possible to change formatting blocks structure without re-writing perl part second time, cause in  the example above if block is one psi element and hence formatting block

Currently i'm digging through the IDEA's formatting mechanism, but some directions (or examples) would be appreciated.


It's not a trivial task. Most of templates have 2 PSI trees: template language tree and HTML one. You need TemplateLanguageFileViewProvider for that. Eventually you get two models: one for HTML and another for the template language (Perl in your case). Perl fragments must OuterLanguageElement instances in HTML.

You can use HTMLFormattingModelBuilder to build the HTML model. When it finds non-HTML elements, it attempts to create  AnotherLanguageBlockWrapper for your Perl fragments. If you don't care about formatting the fragments themselves, you may stop at that point. But if you need formatting for Perl as well, you need to merge block trees so that they cover all the document range without gaps (except pure whitespaces) and not intersecting each other. 

The alternative way is to create language injections for Perl fragments. They will get formatted automatically. There is though one drawback: too many injections may significantly slow down the editor.


Sorry, seem i've made bad example here. MultiPsi just complicates a question. Let's imagine, that there is a language, where every line should begin from some symbol, like % 

so we'll have


% print 1;

% print 2;

% {

%  print 3;

% }


Now we need indention to be measured and adjusted relatively to % sign, not beginning of the line.


Well, there is no straightforward solution for that too. You may need to build a model without leading '%', perform formatting and insert leading '%' back, for example. Basically you can remove '%' in PreFormatProcessor and add some start/end markers instead. After formatting is complete, you can use PostFormatProcessor for removing start/end markers and inserting leading '%' back. The markers will not be visible to end user since you remove them. This sounds like a workaround but there is no direct way to make indent processor to work in a line which doesn't start with whitespaces.


Please sign in to leave a comment.