mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
typed handlers quote style customization for html
#WEB-459 fixed
This commit is contained in:
@@ -402,7 +402,7 @@ public class CodeStyleSettings extends CommonCodeStyleSettings implements Clonea
|
||||
@NonNls public String HTML_INLINE_ELEMENTS =
|
||||
"a,abbr,acronym,b,basefont,bdo,big,br,cite,cite,code,dfn,em,font,i,img,input,kbd,label,q,s,samp,select,span,strike,strong,sub,sup,textarea,tt,u,var";
|
||||
@NonNls public String HTML_DONT_ADD_BREAKS_IF_INLINE_CONTENT = "title,h1,h2,h3,h4,h5,h6,p";
|
||||
|
||||
public QuoteStyle HTML_QUOTE_STYLE = QuoteStyle.Double;
|
||||
// ---------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -1019,4 +1019,15 @@ public class CodeStyleSettings extends CommonCodeStyleSettings implements Clonea
|
||||
return WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN;
|
||||
}
|
||||
|
||||
public enum QuoteStyle {
|
||||
Single("'"),
|
||||
Double("\""),
|
||||
None("");
|
||||
|
||||
public final String quote;
|
||||
|
||||
QuoteStyle(String quote) {
|
||||
this.quote = quote;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,6 +89,7 @@ checkbox.wrap.text=Wrap text
|
||||
checkbox.parentheses.around.method.arguments=Add parentheses around method arguments
|
||||
checkbox.rename.local.variables.inplace=Enable in-place mode
|
||||
checkbox.rename.local.variables.preselect=Preselect old name
|
||||
generated.quote.marks=Generated quote marks:
|
||||
editbox.keep.blank.lines=Keep blank lines:
|
||||
checkbox.keep.white.spaces=Keep white spaces
|
||||
checkbox.align.text=Align text
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<grid id="ca5bb" layout-manager="GridLayoutManager" row-count="7" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<grid id="ca5bb" layout-manager="GridLayoutManager" row-count="8" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
@@ -180,6 +180,20 @@
|
||||
<text value=""/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="396b9" class="javax.swing.JLabel">
|
||||
<constraints>
|
||||
<grid row="7" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text resource-bundle="messages/ApplicationBundle" key="generated.quote.marks"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="74327" class="javax.swing.JComboBox" binding="myQuotesCombo">
|
||||
<constraints>
|
||||
<grid row="7" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
<grid id="b8acc" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
|
||||
@@ -28,6 +28,7 @@ import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
|
||||
import com.intellij.ui.EnumComboBoxModel;
|
||||
import com.intellij.ui.components.JBScrollPane;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.PlatformIcons;
|
||||
@@ -66,6 +67,7 @@ public class CodeStyleHtmlPanel extends CodeStyleAbstractPanel {
|
||||
private TextFieldWithBrowseButton myDontBreakIfInlineContent;
|
||||
private JBScrollPane myJBScrollPane;
|
||||
private JPanel myRightMarginPanel;
|
||||
private JComboBox myQuotesCombo;
|
||||
private RightMarginForm myRightMarginForm;
|
||||
|
||||
public CodeStyleHtmlPanel(CodeStyleSettings settings) {
|
||||
@@ -73,6 +75,7 @@ public class CodeStyleHtmlPanel extends CodeStyleAbstractPanel {
|
||||
installPreviewPanel(myPreviewPanel);
|
||||
|
||||
fillWrappingCombo(myWrapAttributes);
|
||||
fillQuotesCombo(myQuotesCombo);
|
||||
|
||||
customizeField(ApplicationBundle.message("title.insert.new.line.before.tags"), myInsertNewLineTagNames);
|
||||
customizeField(ApplicationBundle.message("title.remove.line.breaks.before.tags"), myRemoveNewLineTagNames);
|
||||
@@ -162,9 +165,15 @@ public class CodeStyleHtmlPanel extends CodeStyleAbstractPanel {
|
||||
settings.HTML_KEEP_WHITESPACES_INSIDE = myKeepWhiteSpacesTagNames.getText();
|
||||
settings.HTML_KEEP_LINE_BREAKS = myShouldKeepBlankLines.isSelected();
|
||||
settings.HTML_KEEP_LINE_BREAKS_IN_TEXT = myShouldKeepLineBreaksInText.isSelected();
|
||||
settings.HTML_QUOTE_STYLE = (CodeStyleSettings.QuoteStyle)myQuotesCombo.getSelectedItem();
|
||||
myRightMarginForm.apply(settings);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected String getQuotes() {
|
||||
return ApplicationBundle.message("single.quotes").equals(myQuotesCombo.getSelectedItem()) ? "'" : "\"";
|
||||
}
|
||||
|
||||
private static int getIntValue(JTextField keepBlankLines) {
|
||||
try {
|
||||
return Integer.parseInt(keepBlankLines.getText());
|
||||
@@ -196,6 +205,7 @@ public class CodeStyleHtmlPanel extends CodeStyleAbstractPanel {
|
||||
myDontBreakIfInlineContent.setText(settings.HTML_DONT_ADD_BREAKS_IF_INLINE_CONTENT);
|
||||
myKeepWhiteSpacesTagNames.setText(settings.HTML_KEEP_WHITESPACES_INSIDE);
|
||||
myRightMarginForm.reset(settings);
|
||||
myQuotesCombo.setSelectedItem(settings.HTML_QUOTE_STYLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -266,6 +276,10 @@ public class CodeStyleHtmlPanel extends CodeStyleAbstractPanel {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (myQuotesCombo.getSelectedItem() != settings.HTML_QUOTE_STYLE) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return myRightMarginForm.isModified(settings);
|
||||
}
|
||||
|
||||
@@ -290,4 +304,8 @@ public class CodeStyleHtmlPanel extends CodeStyleAbstractPanel {
|
||||
protected void prepareForReformat(final PsiFile psiFile) {
|
||||
//psiFile.putUserData(PsiUtil.FILE_LANGUAGE_LEVEL_KEY, LanguageLevel.HIGHEST);
|
||||
}
|
||||
|
||||
private static void fillQuotesCombo(JComboBox combo) {
|
||||
combo.setModel(new EnumComboBoxModel<>(CodeStyleSettings.QuoteStyle.class));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSchemes;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.xml.XmlAttribute;
|
||||
import com.intellij.psi.xml.XmlFile;
|
||||
@@ -34,6 +35,7 @@ import com.intellij.psi.xml.XmlTag;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.text.CharArrayUtil;
|
||||
import com.intellij.xml.XmlNamespaceHelper;
|
||||
import com.intellij.xml.util.HtmlUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -66,14 +68,20 @@ public class XmlAttributeInsertHandler implements InsertHandler<LookupElement> {
|
||||
final PsiFile file = context.getFile();
|
||||
|
||||
final CharSequence chars = document.getCharsSequence();
|
||||
final boolean insertQuotes = WebEditorOptions.getInstance().isInsertQuotesForAttributeValue();
|
||||
final boolean hasQuotes = CharArrayUtil.regionMatches(chars, caretOffset, "=\"");
|
||||
if (!hasQuotes && !CharArrayUtil.regionMatches(chars, caretOffset, "='")) {
|
||||
final String quote = getAttributeQuote(HtmlUtil.hasHtml(file) || HtmlUtil.supportsXmlTypedHandlers(file));
|
||||
final boolean insertQuotes = WebEditorOptions.getInstance().isInsertQuotesForAttributeValue() && StringUtil.isNotEmpty(quote);
|
||||
final boolean hasQuotes = CharArrayUtil.regionMatches(chars, caretOffset, "=\"") ||
|
||||
CharArrayUtil.regionMatches(chars, caretOffset, "='");
|
||||
if (!hasQuotes) {
|
||||
PsiElement fileContext = file.getContext();
|
||||
String toInsert= "=\"\"";
|
||||
String toInsert = null;
|
||||
|
||||
if(fileContext != null) {
|
||||
if (fileContext.getText().startsWith("\"")) toInsert = "=''";
|
||||
if (fileContext.getText().startsWith("\'")) toInsert = "=\"\"";
|
||||
}
|
||||
if (toInsert == null) {
|
||||
toInsert = "=" + quote + quote;
|
||||
}
|
||||
|
||||
if (!insertQuotes) toInsert = "=";
|
||||
@@ -118,6 +126,10 @@ public class XmlAttributeInsertHandler implements InsertHandler<LookupElement> {
|
||||
}
|
||||
}
|
||||
|
||||
public static String getAttributeQuote(boolean html) {
|
||||
return html ? CodeStyleSchemes.getInstance().getCurrentScheme().getCodeStyleSettings().HTML_QUOTE_STYLE.quote : "\"";
|
||||
}
|
||||
|
||||
private static void qualifyWithPrefix(@NotNull String namespacePrefix, @NotNull PsiElement context) {
|
||||
final PsiElement parent = context.getParent();
|
||||
|
||||
|
||||
@@ -230,9 +230,9 @@ public class XmlTagInsertHandler implements InsertHandler<LookupElement> {
|
||||
if (shouldBeInserted && (tag == null || tag.getAttributeValue(attributeName) == null)) {
|
||||
if (!notRequiredAttributes.contains(attributeName)) {
|
||||
if (!extension.isIndirectSyntax(attributeDecl)) {
|
||||
template.addTextSegment(" " + attributeName + "=\"");
|
||||
template.addTextSegment(" " + attributeName + "=" + XmlAttributeInsertHandler.getAttributeQuote(htmlCode));
|
||||
template.addVariable(new MacroCallNode(new CompleteMacro()), true);
|
||||
template.addTextSegment("\"");
|
||||
template.addTextSegment(XmlAttributeInsertHandler.getAttributeQuote(htmlCode));
|
||||
}
|
||||
else {
|
||||
if (indirectRequiredAttrs == null) indirectRequiredAttrs = new StringBuilder();
|
||||
@@ -241,7 +241,8 @@ public class XmlTagInsertHandler implements InsertHandler<LookupElement> {
|
||||
}
|
||||
}
|
||||
else if (shouldBeInserted && attributeDecl.isFixed() && attributeDecl.getDefaultValue() != null && !htmlCode) {
|
||||
template.addTextSegment(" " + attributeName + "=\"" + attributeDecl.getDefaultValue() + "\"");
|
||||
template.addTextSegment(" " + attributeName + "=" + XmlAttributeInsertHandler.getAttributeQuote(false) +
|
||||
attributeDecl.getDefaultValue() + XmlAttributeInsertHandler.getAttributeQuote(false));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -254,6 +255,7 @@ public class XmlTagInsertHandler implements InsertHandler<LookupElement> {
|
||||
XmlTag tag,
|
||||
Template template,
|
||||
StringBuilder indirectRequiredAttrs) {
|
||||
boolean htmlCode = HtmlUtil.hasHtml(tag.getContainingFile()) || HtmlUtil.supportsXmlTypedHandlers(tag.getContainingFile());
|
||||
|
||||
if (completionChar == '>' || (completionChar == '/' && indirectRequiredAttrs != null)) {
|
||||
template.addTextSegment(">");
|
||||
@@ -290,7 +292,7 @@ public class XmlTagInsertHandler implements InsertHandler<LookupElement> {
|
||||
else if (completionChar == ' ' && template.getSegmentsCount() == 0) {
|
||||
if (WebEditorOptions.getInstance().isAutomaticallyStartAttribute() &&
|
||||
(descriptor.getAttributesDescriptors(tag).length > 0 || isTagFromHtml(tag) && !HtmlUtil.isTagWithoutAttributes(tag.getName()))) {
|
||||
completeAttribute(template);
|
||||
completeAttribute(template, htmlCode);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -301,7 +303,7 @@ public class XmlTagInsertHandler implements InsertHandler<LookupElement> {
|
||||
else {
|
||||
if (needAlLeastOneAttribute(tag) && WebEditorOptions.getInstance().isAutomaticallyStartAttribute() && tag.getAttributes().length == 0
|
||||
&& template.getSegmentsCount() == 0) {
|
||||
completeAttribute(template);
|
||||
completeAttribute(template, htmlCode);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
@@ -313,12 +315,12 @@ public class XmlTagInsertHandler implements InsertHandler<LookupElement> {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void completeAttribute(Template template) {
|
||||
private static void completeAttribute(Template template, boolean htmlCode) {
|
||||
template.addTextSegment(" ");
|
||||
template.addVariable(new MacroCallNode(new CompleteMacro()), true);
|
||||
template.addTextSegment("=\"");
|
||||
template.addTextSegment("=" + XmlAttributeInsertHandler.getAttributeQuote(htmlCode));
|
||||
template.addEndVariable();
|
||||
template.addTextSegment("\"");
|
||||
template.addTextSegment(XmlAttributeInsertHandler.getAttributeQuote(htmlCode));
|
||||
}
|
||||
|
||||
private static boolean needAlLeastOneAttribute(XmlTag tag) {
|
||||
|
||||
@@ -17,12 +17,14 @@ package com.intellij.codeInsight.editorActions;
|
||||
|
||||
import com.intellij.application.options.editor.WebEditorOptions;
|
||||
import com.intellij.codeInsight.AutoPopupController;
|
||||
import com.intellij.codeInsight.completion.XmlAttributeInsertHandler;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.xml.XmlAttribute;
|
||||
import com.intellij.xml.util.HtmlUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class XmlEqTypedHandler extends TypedHandlerDelegate {
|
||||
@@ -50,13 +52,18 @@ public class XmlEqTypedHandler extends TypedHandlerDelegate {
|
||||
if (needToInsertQuotes) {
|
||||
int offset = editor.getCaretModel().getOffset();
|
||||
PsiElement fileContext = file.getContext();
|
||||
String toInsert= "\"\"";
|
||||
String toInsert = null;
|
||||
|
||||
if(fileContext != null) {
|
||||
if (fileContext.getText().startsWith("\"")) toInsert = "''";
|
||||
if (fileContext.getText().startsWith("\'")) toInsert = "\"\"";
|
||||
}
|
||||
if (toInsert == null) {
|
||||
final String quote = XmlAttributeInsertHandler.getAttributeQuote(HtmlUtil.hasHtml(file) || HtmlUtil.supportsXmlTypedHandlers(file));
|
||||
toInsert = quote + quote;
|
||||
}
|
||||
editor.getDocument().insertString(offset, toInsert);
|
||||
editor.getCaretModel().moveToOffset(offset + 1);
|
||||
editor.getCaretModel().moveToOffset(offset + toInsert.length() / 2);
|
||||
AutoPopupController.getInstance(project).scheduleAutoPopup(editor);
|
||||
}
|
||||
needToInsertQuotes = false;
|
||||
|
||||
@@ -28,6 +28,8 @@ import com.intellij.javaee.ExternalResourceManagerEx;
|
||||
import com.intellij.javaee.ExternalResourceManagerExImpl;
|
||||
import com.intellij.openapi.application.Result;
|
||||
import com.intellij.openapi.command.WriteCommandAction;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSchemes;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
import com.intellij.psi.statistics.StatisticsManager;
|
||||
import com.intellij.psi.statistics.impl.StatisticsManagerImpl;
|
||||
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
|
||||
@@ -342,6 +344,30 @@ public class XmlCompletionTest extends LightCodeInsightFixtureTestCase {
|
||||
checkResultByFile("37_after.xml");
|
||||
}
|
||||
|
||||
public void testInsertExtraRequiredAttributeSingleQuote() throws Exception {
|
||||
final CodeStyleSettings settings = CodeStyleSchemes.getInstance().getCurrentScheme().getCodeStyleSettings();
|
||||
final CodeStyleSettings.QuoteStyle quote = settings.HTML_QUOTE_STYLE;
|
||||
try {
|
||||
settings.HTML_QUOTE_STYLE = CodeStyleSettings.QuoteStyle.Single;
|
||||
configureByFile(getTestName(true) + ".html");
|
||||
checkResultByFile(getTestName(true) + "_after.html");
|
||||
} finally {
|
||||
CodeStyleSchemes.getInstance().getCurrentScheme().getCodeStyleSettings().HTML_QUOTE_STYLE = quote;
|
||||
}
|
||||
}
|
||||
|
||||
public void testInsertExtraRequiredAttributeNoneQuote() throws Exception {
|
||||
final CodeStyleSettings settings = CodeStyleSchemes.getInstance().getCurrentScheme().getCodeStyleSettings();
|
||||
final CodeStyleSettings.QuoteStyle quote = settings.HTML_QUOTE_STYLE;
|
||||
try {
|
||||
settings.HTML_QUOTE_STYLE = CodeStyleSettings.QuoteStyle.None;
|
||||
configureByFile(getTestName(true) + ".html");
|
||||
checkResultByFile(getTestName(true) + "_after.html");
|
||||
} finally {
|
||||
CodeStyleSchemes.getInstance().getCurrentScheme().getCodeStyleSettings().HTML_QUOTE_STYLE = quote;
|
||||
}
|
||||
}
|
||||
|
||||
public void testBeforeAttributeValue() throws Throwable {
|
||||
configureByFile(getTestName(true) + ".xml");
|
||||
assertEmpty(myFixture.getLookupElements());
|
||||
|
||||
@@ -16,7 +16,10 @@
|
||||
package com.intellij.codeInsight.completion;
|
||||
|
||||
import com.intellij.application.options.editor.WebEditorOptions;
|
||||
import com.intellij.ide.highlighter.HtmlFileType;
|
||||
import com.intellij.ide.highlighter.XmlFileType;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSchemes;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase;
|
||||
|
||||
/**
|
||||
@@ -95,6 +98,32 @@ public class XmlTypedHandlersTest extends LightPlatformCodeInsightFixtureTestCas
|
||||
}
|
||||
}
|
||||
|
||||
public void testSingleQuotes() {
|
||||
final CodeStyleSettings settings = CodeStyleSchemes.getInstance().getCurrentScheme().getCodeStyleSettings();
|
||||
final CodeStyleSettings.QuoteStyle quote = settings.HTML_QUOTE_STYLE;
|
||||
try {
|
||||
settings.HTML_QUOTE_STYLE = CodeStyleSettings.QuoteStyle.Single;
|
||||
myFixture.configureByText(HtmlFileType.INSTANCE, "<foo bar<caret>");
|
||||
myFixture.type('=');
|
||||
myFixture.checkResult("<foo bar='<caret>'");
|
||||
} finally {
|
||||
CodeStyleSchemes.getInstance().getCurrentScheme().getCodeStyleSettings().HTML_QUOTE_STYLE = quote;
|
||||
}
|
||||
}
|
||||
|
||||
public void testNoneQuotes() {
|
||||
final CodeStyleSettings settings = CodeStyleSchemes.getInstance().getCurrentScheme().getCodeStyleSettings();
|
||||
final CodeStyleSettings.QuoteStyle quote = settings.HTML_QUOTE_STYLE;
|
||||
try {
|
||||
settings.HTML_QUOTE_STYLE = CodeStyleSettings.QuoteStyle.None;
|
||||
myFixture.configureByText(HtmlFileType.INSTANCE, "<foo bar<caret>>text");
|
||||
myFixture.type('=');
|
||||
myFixture.checkResult("<foo bar=<caret>>text");
|
||||
} finally {
|
||||
CodeStyleSchemes.getInstance().getCurrentScheme().getCodeStyleSettings().HTML_QUOTE_STYLE = quote;
|
||||
}
|
||||
}
|
||||
|
||||
public void testFooBar() throws Exception {
|
||||
doTest("<foo>\n" +
|
||||
" <bar<caret></bar>\n" +
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
<im<caret>
|
||||
@@ -0,0 +1 @@
|
||||
<img src= alt=>
|
||||
@@ -0,0 +1 @@
|
||||
<im<caret>
|
||||
@@ -0,0 +1 @@
|
||||
<img src='' alt=''>
|
||||
Reference in New Issue
Block a user