--- /dev/null
+def f(a) {
+ return not a
+}
\ No newline at end of file
--- /dev/null
+def f(a) {
+ return <spot>a</spot>$key
+}
\ No newline at end of file
--- /dev/null
+<html>
+<body>
+Negate the expression.
+</body>
+</html>
\ No newline at end of file
<codeFoldingOptionsProvider instance="com.jetbrains.python.PythonFoldingOptionsProvider"/>
<applicationService serviceInterface="com.jetbrains.python.PythonFoldingSettings"
serviceImplementation="com.jetbrains.python.PythonFoldingSettings"/>
+
+ <!-- postfix templates!-->
+ <codeInsight.template.postfixTemplateProvider language="Python"
+ implementationClass="com.jetbrains.python.codeInsight.postfix.PyPostfixTemplateProvider"/>
</extensions>
<extensionPoints>
--- /dev/null
+/*
+ * Copyright 2000-2016 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.codeInsight.postfix;
+
+import com.intellij.codeInsight.template.postfix.templates.NotPostfixTemplate;
+
+public class PyNotPostfixTemplate extends NotPostfixTemplate {
+ public PyNotPostfixTemplate() {
+ super("not", "." + "not", "not expr", PyPostfixUtils.PY_PSI_INFO, PyPostfixUtils.selectorAllExpressionsWithCurrentOffset());
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2016 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.codeInsight.postfix;
+
+import com.intellij.codeInsight.template.postfix.templates.PostfixTemplate;
+import com.intellij.codeInsight.template.postfix.templates.PostfixTemplateProvider;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.psi.PsiFile;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Set;
+
+public class PyPostfixTemplateProvider implements PostfixTemplateProvider {
+ @NotNull
+ @Override
+ public Set<PostfixTemplate> getTemplates() {
+ return ContainerUtil.<PostfixTemplate>newHashSet(new PyNotPostfixTemplate(),
+ new PyParenthesizedExpressionPostfixTemplate());
+ }
+
+ @Override
+ public boolean isTerminalSymbol(char currentChar) {
+ return currentChar == '.'|| currentChar == '!';
+ }
+
+ @Override
+ public void preExpand(@NotNull PsiFile file, @NotNull Editor editor) {
+
+ }
+
+ @Override
+ public void afterExpand(@NotNull PsiFile file, @NotNull Editor editor) {
+
+ }
+
+ @NotNull
+ @Override
+ public PsiFile preCheck(@NotNull PsiFile copyFile, @NotNull Editor realEditor, int currentOffset) {
+ return copyFile;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2016 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.codeInsight.postfix;
+
+import com.intellij.codeInsight.template.postfix.templates.PostfixTemplateExpressionSelector;
+import com.intellij.codeInsight.template.postfix.templates.PostfixTemplateExpressionSelectorBase;
+import com.intellij.codeInsight.template.postfix.templates.PostfixTemplatePsiInfo;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.util.Conditions;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.util.PsiUtilCore;
+import com.jetbrains.python.psi.*;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class PyPostfixUtils {
+
+ private PyPostfixUtils() {
+ }
+
+ public static final PostfixTemplatePsiInfo PY_PSI_INFO = new PostfixTemplatePsiInfo() {
+ @NotNull
+ @Override
+ public PsiElement createExpression(@NotNull PsiElement context, @NotNull String prefix, @NotNull String suffix) {
+ String text = prefix + context.getText() + suffix;
+ return PyElementGenerator.getInstance(context.getProject()).createExpressionFromText(LanguageLevel.forElement(context), text);
+ }
+
+ @NotNull
+ @Override
+ public PsiElement getNegatedExpression(@NotNull PsiElement element) {
+ String newText = element instanceof PyBinaryExpression ? "(" + element.getText() + ")" : element.getText();
+ return PyElementGenerator.getInstance(element.getProject()).
+ createExpressionFromText(LanguageLevel.forElement(element), "not " + newText);
+ }
+ };
+
+
+ public static PostfixTemplateExpressionSelector selectorAllExpressionsWithCurrentOffset(final Condition<PsiElement> additionalFilter) {
+ return new PostfixTemplateExpressionSelectorBase(additionalFilter) {
+ @Override
+ protected List<PsiElement> getNonFilteredExpressions(@NotNull PsiElement context, @NotNull Document document, int newOffset) {
+ PsiElement elementAtCaret = PsiUtilCore.getElementAtOffset(context.getContainingFile(), newOffset - 1);
+ final List<PsiElement> expressions = new ArrayList<PsiElement>();
+ while (elementAtCaret != null) {
+ if (elementAtCaret instanceof PyStatement || elementAtCaret instanceof PyFile) {
+ break;
+ }
+ if (elementAtCaret instanceof PyExpression) {
+ expressions.add(elementAtCaret);
+ }
+ elementAtCaret = elementAtCaret.getParent();
+ }
+ return expressions;
+ }
+ };
+ }
+
+ public static PostfixTemplateExpressionSelector selectorAllExpressionsWithCurrentOffset() {
+ return selectorAllExpressionsWithCurrentOffset(Conditions.<PsiElement>alwaysTrue());
+ }
+}
--- /dev/null
+if a.not<caret>:
+ print(1)
\ No newline at end of file
--- /dev/null
+if not a<caret>:
+ print(1)
\ No newline at end of file
--- /dev/null
+3.not<caret>
\ No newline at end of file
--- /dev/null
+not 3<caret>
\ No newline at end of file
--- /dev/null
+def f():
+ return True and False.not<caret>
\ No newline at end of file
--- /dev/null
+def f():
+ return not (True and False)<caret>
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright 2000-2016 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.postfix;
+
+public class PyNotPostfixTemplateTest extends PyPostfixTemplateTestCase {
+
+ public void testNumber() {
+ doTest();
+ }
+
+ public void testIf() {
+ doTest();
+ }
+
+ public void testParenthesis() {
+ doTest();
+ }
+
+ @Override
+ protected String getTestDataPath() {
+ return super.getTestDataPath() + "not/";
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2016 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.postfix;
+
+import com.jetbrains.python.PythonTestUtil;
+import com.jetbrains.python.fixtures.PyTestCase;
+import org.jetbrains.annotations.NonNls;
+
+public abstract class PyPostfixTemplateTestCase extends PyTestCase {
+ protected void doTest() {
+ myFixture.configureByFile(getTestName(true) + ".py");
+ myFixture.type("\t");
+ myFixture.checkResultByFile(getTestName(true) + "_after" + ".py", true);
+ }
+
+ @Override
+ @NonNls
+ protected String getTestDataPath() {
+ return PythonTestUtil.getTestDataPath() + "/postfix/";
+ }
+}