How to çreate live-template-like red box edit regions in an editor?

I'd like to simulate how IDEA highlights things in a red box, like when using a
Live Template, or completing an XML tag with required attributes, or renaming a
reference. I can't find this in the OpenAPI or the forums. How do I do this?

Thanks,
-Keith

4 comments
Comment actions Permalink

I wrote some code to define a live template on the fly and replace the current
editor selection with it.
If that suits your needs I can post it as soon as I am one my other machine
again (that is in about 10 hours).
IIRC it relies on some code that is not exactly in the open api, though.
(I was trying to simulate the 'SyncEdit' mode of JBuilder, but Idea's live
templates behave too differently and do not scale well to larger code blocks
to make this useful.)

Keith Lea wrote:

I'd like to simulate how IDEA highlights things in a red box, like when
using a Live Template, or completing an XML tag with required
attributes, or renaming a reference. I can't find this in the OpenAPI or
the forums. How do I do this?

Thanks,
-Keith

0
Comment actions Permalink

That sounds awesome. There's no rush. Have you filed issues for the performance
and behavior problems in JIRA? I think SyncEdit would be cool every once in a while.

Stephen Kelvin wrote:

I wrote some code to define a live template on the fly and replace the
current editor selection with it.
If that suits your needs I can post it as soon as I am one my other
machine again (that is in about 10 hours).
IIRC it relies on some code that is not exactly in the open api, though.
(I was trying to simulate the 'SyncEdit' mode of JBuilder, but Idea's live
templates behave too differently and do not scale well to larger code
blocks
to make this useful.)

Keith Lea wrote:

>> I'd like to simulate how IDEA highlights things in a red box, like
>> when using a Live Template, or completing an XML tag with required
>> attributes, or renaming a reference. I can't find this in the OpenAPI
>> or the forums. How do I do this?
>>
>> Thanks,
>> -Keith

0
Comment actions Permalink

Find below the complete code my very raw sync edit action.
Guess you can figure it out quite easily.
It's really not that usefull (e.g. it does not use psi in any way,
so you can sync edit all "if"s to "void"s).

I haven't yet filed any issues in Jira.
What I would like to have is ALL variable occurences of a template highlighted,
not just the one I am currently editing.

I was thinking about trying to do the highlighting and modifying myself, but
that would probably be either too complicated or plain impossible.

Keith Lea wrote:

That sounds awesome. There's no rush. Have you filed issues for the
performance and behavior problems in JIRA? I think SyncEdit would be
cool every once in a while.


package com.xduke.syncedit;

import com.intellij.codeInsight.template.TemplateManager;
import com.intellij.codeInsight.template.impl.TemplateImpl;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.SelectionModel;
import com.intellij.openapi.project.Project;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class SyncEditAction extends AnAction {
private static final Logger LOGGER = Logger.getInstance(SyncEditAction.class.getName());

public SyncEditAction() {
super("SyncEdit");
}

public void update(AnActionEvent e) {
DataContext dataContext = e.getDataContext();
boolean enabled = false;
Editor editor = (Editor) dataContext.getData(DataConstants.EDITOR);
if (editor != null) {
SelectionModel selectionModel = editor.getSelectionModel();
enabled = selectionModel.hasSelection();
}
final Presentation presentation = e.getPresentation();
presentation.setEnabled(enabled);
}

public void actionPerformed(AnActionEvent event) {
DataContext dataContext = event.getDataContext();
Project project = (Project) dataContext.getData(DataConstants.PROJECT);

TemplateManager templateManager = TemplateManager.getInstance(project);

Editor editor = (Editor) dataContext.getData(DataConstants.EDITOR);
if(editor != null) {
SelectionModel selectionModel = editor.getSelectionModel();
if (selectionModel.hasSelection()) {
Document document = editor.getDocument();
boolean isWritable = document.isWritable();

if (isWritable) {
int selectionStart = selectionModel.getSelectionStart();
int selectionEnd = selectionModel.getSelectionEnd();

CharSequence content = document.getCharsSequence();
String selection = content.subSequence(selectionStart, selectionEnd).toString();
List words = splitIntoWords(selection);
Map countMap = countWords(words);
final List variables = getVariables(words, countMap);
final String text = joinWords(words);

TemplateImpl tempTemplate = createTemplate(text, variables);

templateManager.startTemplate(editor, "", tempTemplate);
}
}
}
}



private static List getVariables(List words, Map wordCountMap) {
final ArrayList variables = new ArrayList();
final int wordCount = words.size();
final Map word2VariableIndex = new HashMap();
for (int wordIndex = 0; wordIndex < wordCount; wordIndex++) {
String word = (String) words.get(wordIndex);
if (isWordChar(word.charAt(0))) {
Integer countInteger = (Integer) wordCountMap.get(word);
int count = countInteger.intValue();
if (count > 1) {
Integer variableIndexInteger = (Integer) word2VariableIndex.get(word);
int variableIndex;
if (variableIndexInteger != null) {
variableIndex = variableIndexInteger.intValue();
}
else {
variableIndex = variables.size();
word2VariableIndex.put(word, new Integer(variableIndex));
variables.add(word);
}
final String variableName = getVariableName(variableIndex);
String variableExpression = '$' + variableName + '$';
words.set(wordIndex, variableExpression);
}
}
}
return variables;
}

private static Map countWords(List words) {
final HashMap map = new HashMap();
final int wordCount = words.size();
for (int wordIndex = 0; wordIndex < wordCount; wordIndex++) {
String word = (String) words.get(wordIndex);
if (isWordChar(word.charAt(0))) {
Integer countInteger = (Integer) map.get(word);
if (countInteger == null) {
map.put(word, ONE);
}
else {
int count = countInteger.intValue();
map.put(word, new Integer(count + 1));
}
}
}
return map;
}

private static final Integer ONE = new Integer(1);

private static List splitIntoWords(final String text) {
int length = text.length();
ArrayList words = new ArrayList(length / 3);
int wordStartIndex = 0;
boolean isWordChar = isWordChar(text.charAt(0));
int i;
for (i = 1; i < length; ++i) {
boolean newIsWordChar = isWordChar(text.charAt(i));
if (isWordChar != newIsWordChar) {
String word = text.substring(wordStartIndex, i);
words.add(word);
wordStartIndex = i;
}
isWordChar = newIsWordChar;
}
if (wordStartIndex != length) {
String word = text.substring(wordStartIndex, i);
words.add(word);
}
return words;
}

public static void main(String[] args) {
final List words = splitIntoWords(" Ha 34lk bubuu ");
for (int i = 0; i < words.size(); i++) {
Object o = words.get(i);
System.out.println(">" + o + "<-");
}
}

private static boolean isWordChar(char c) {
return Character.isLetter(c) || Character.isDigit(c);
}

private static String joinWords(List words) {
final StringBuffer buffer = new StringBuffer();
final int wordCount = words.size();
for (int i = 0; i < wordCount; i++) {
String word = (String) words.get(i);
buffer.append(word);
}
return new String(buffer);
}

private static String getVariableName(int i) {
return 'v' + Integer.toString(i);
}

private TemplateImpl createTemplate(String text, List variables) {
TemplateImpl tempTemplate = new TemplateImpl("", text, "other");

tempTemplate.setKey("hi");
tempTemplate.setDescription("sync edit template");
tempTemplate.setToIndent(false);
tempTemplate.setToReformat(false);
tempTemplate.setToShortenLongNames(false);
tempTemplate.parseSegments();
tempTemplate.setInline(false);

final int variableCount = variables.size();
for (int i = 0; i < variableCount; i++) {
String value = (String) variables.get(i);
String name = getVariableName(i);
String quotedValue = '"' + value + '"';
tempTemplate.addVariable(name, quotedValue, quotedValue, true);
}
return tempTemplate;
}
}

0
Comment actions Permalink

Thank you, this is exactly what I wanted.

Stephen Kelvin wrote:

I haven't yet filed any issues in Jira.


Maybe you should file an issue for allowing the red boxes anywhere, not only in
live templates.

0

Please sign in to leave a comment.