diff --git a/python/src/META-INF/python-core.xml b/python/src/META-INF/python-core.xml
index 6c4665d91e20..8a9fe46241eb 100644
--- a/python/src/META-INF/python-core.xml
+++ b/python/src/META-INF/python-core.xml
@@ -18,6 +18,7 @@
+
diff --git a/python/src/com/jetbrains/python/formatter/PyCodeStyleSettings.java b/python/src/com/jetbrains/python/formatter/PyCodeStyleSettings.java
index 961ca725506a..e727ddb8a05d 100644
--- a/python/src/com/jetbrains/python/formatter/PyCodeStyleSettings.java
+++ b/python/src/com/jetbrains/python/formatter/PyCodeStyleSettings.java
@@ -38,6 +38,8 @@ public class PyCodeStyleSettings extends CustomCodeStyleSettings {
public boolean NEW_LINE_AFTER_COLON = false;
public boolean NEW_LINE_AFTER_COLON_MULTI_CLAUSE = true;
+ public boolean SPACE_AFTER_NUMBER_SIGN = true;
+
public PyCodeStyleSettings(CodeStyleSettings container) {
super("Python", container);
}
diff --git a/python/src/com/jetbrains/python/formatter/PyLanguageCodeStyleSettingsProvider.java b/python/src/com/jetbrains/python/formatter/PyLanguageCodeStyleSettingsProvider.java
index c26a1a1742bd..a7c6fc88331b 100644
--- a/python/src/com/jetbrains/python/formatter/PyLanguageCodeStyleSettingsProvider.java
+++ b/python/src/com/jetbrains/python/formatter/PyLanguageCodeStyleSettingsProvider.java
@@ -72,9 +72,11 @@ public class PyLanguageCodeStyleSettingsProvider extends LanguageCodeStyleSettin
consumer.showCustomOption(PyCodeStyleSettings.class, "SPACE_AROUND_EQ_IN_KEYWORD_ARGUMENT", "Around = in keyword argument",
SPACES_AROUND_OPERATORS);
consumer.showCustomOption(PyCodeStyleSettings.class, "SPACE_WITHIN_BRACES", "Braces", SPACES_WITHIN);
- consumer.showCustomOption(PyCodeStyleSettings.class, "SPACE_BEFORE_PY_COLON", ApplicationBundle.message("checkbox.spaces.before.colon"), SPACES_OTHER);
+ consumer.showCustomOption(PyCodeStyleSettings.class, "SPACE_BEFORE_PY_COLON",
+ ApplicationBundle.message("checkbox.spaces.before.colon"), SPACES_OTHER);
consumer.showCustomOption(PyCodeStyleSettings.class, "SPACE_AFTER_PY_COLON", ApplicationBundle.message("checkbox.spaces.after.colon"), SPACES_OTHER);
consumer.showCustomOption(PyCodeStyleSettings.class, "SPACE_BEFORE_BACKSLASH", "Before '\\'", SPACES_OTHER);
+ consumer.showCustomOption(PyCodeStyleSettings.class, "SPACE_AFTER_NUMBER_SIGN", "After '#'", SPACES_OTHER);
}
else if (settingsType == SettingsType.BLANK_LINES_SETTINGS) {
consumer.showStandardOptions("BLANK_LINES_AROUND_CLASS",
@@ -112,7 +114,7 @@ public class PyLanguageCodeStyleSettingsProvider extends LanguageCodeStyleSettin
CommonCodeStyleSettings.IndentOptions indentOptions = defaultSettings.initIndentOptions();
indentOptions.INDENT_SIZE = 4;
defaultSettings.ALIGN_MULTILINE_PARAMETERS_IN_CALLS = true;
- return defaultSettings;
+ return defaultSettings;
}
@Override
diff --git a/python/src/com/jetbrains/python/formatter/PyPreFormatProcessor.java b/python/src/com/jetbrains/python/formatter/PyPreFormatProcessor.java
new file mode 100644
index 000000000000..081efc27b72f
--- /dev/null
+++ b/python/src/com/jetbrains/python/formatter/PyPreFormatProcessor.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.jetbrains.python.formatter;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.PsiComment;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.codeStyle.CodeStyleSettings;
+import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
+import com.intellij.psi.impl.source.codeStyle.PreFormatProcessor;
+import com.jetbrains.python.PythonLanguage;
+import com.jetbrains.python.psi.LanguageLevel;
+import com.jetbrains.python.psi.PyElementGenerator;
+import com.jetbrains.python.psi.PyRecursiveElementVisitor;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author traff
+ */
+public class PyPreFormatProcessor implements PreFormatProcessor {
+ @NotNull
+ @Override
+ public TextRange process(@NotNull ASTNode element, @NotNull TextRange range) {
+ PsiElement psiElement = element.getPsi();
+ if (psiElement == null) return range;
+
+ if (!psiElement.getLanguage().is(PythonLanguage.getInstance())) return range;
+
+ PsiFile file = psiElement.isValid() ? psiElement.getContainingFile() : null;
+ if (file == null) return range;
+
+ Project project = psiElement.getProject();
+
+ return new PyCommentFormatter(project).process(psiElement, range);
+ }
+
+ /**
+ * @author traff
+ */
+ public static class PyCommentFormatter extends PyRecursiveElementVisitor {
+ private final Project myProject;
+ private final CodeStyleSettings mySettings;
+ private final PyCodeStyleSettings myPyCodeStyleSettings;
+ private TextRange myRange;
+
+ public PyCommentFormatter(Project project) {
+ myProject = project;
+ mySettings = CodeStyleSettingsManager.getSettings(project);
+ myPyCodeStyleSettings = mySettings.getCustomSettings(PyCodeStyleSettings.class);
+ }
+
+ public TextRange process(PsiElement element, TextRange range) {
+ if (!myPyCodeStyleSettings.SPACE_AFTER_NUMBER_SIGN) {
+ return range;
+ }
+ myRange = range;
+ element.accept(this);
+ return element.getTextRange();
+ }
+
+ @Override
+ public void visitComment(PsiComment element) {
+ if (!myRange.contains(element.getTextRange())) {
+ return;
+ }
+ String text = element.getText();
+ int commentStart = text.indexOf('#');
+ if (commentStart != -1 && (commentStart + 1) < text.length()) {
+ String commentText = StringUtil.trimLeading(text.substring(commentStart + 1));
+
+ String newText = "# " + commentText;
+ if (!newText.equals(text)) {
+ element.replace(
+ PyElementGenerator.getInstance(myProject).createFromText(LanguageLevel.getDefault(), PsiComment.class, newText));
+ }
+ }
+ }
+ }
+}