YamlScalarTextEvaluator<YAMLScalarTextImpl> () { return new YAMLBlockScalarTextEvaluator<>(this) { @NotNull @Override protected String getRangesJoiner(@NotNull CharSequence text, @NotNull List<TextRange> contentRanges, int indexBefore) { final TextRange leftRange = contentRanges.get(indexBefore); final TextRange rightRange = contentRanges.get(indexBefore + 1); if (leftRange.isEmpty()) { if (rightRange.getLength() == 1 && text.charAt(rightRange.getStartOffset()) == '\n' && getChompingIndicator() != ChompingIndicator.KEEP) return ""; return "\n"; } if (startsWithWhitespace(text, leftRange) || startsWithWhitespace(text, rightRange)) { return "\n"; } if (rightRange.isEmpty()) { int i = indexBefore + 2; // Unfortunately we need to scan to the nearest non-empty line to understand // whether we should add a line here while (i < contentRanges.size() && contentRanges.get(i).isEmpty()) { i++; } if (i >= contentRanges.size()) { // empty lines until the end if (getChompingIndicator() == ChompingIndicator.KEEP) { return "\n"; } } else if (startsWithWhitespace(text, contentRanges.get(i))) { return "\n"; } return ""; } return " "; } @NotNull @Override public String getTextValue(@Nullable TextRange rangeInHost) { String value = super.getTextValue(rangeInHost); if (!StringUtil.isEmptyOrSpaces(value) && getChompingIndicator() != ChompingIndicator.STRIP && isEnding(rangeInHost)) { value += "\n"; } return value; } private static boolean startsWithWhitespace(@NotNull CharSequence text, @NotNull TextRange range) { if (range.isEmpty()) { return false; } final char c = text.charAt(range.getStartOffset()); return c == ' ' || c == '\t'; } }; }