intellij-community
intellij-community copied to clipboard
Improvements to “Execute Line in Console” feature in PyCharm.
This PR suggests some improvements to the “Execute Line in Console” feature in PyCharm. Currently, that feature submits a line to the Python console, even when the line is an incomplete input. A screencast demonstrating the new feature in this PR is shown below.
In this PR, the following changes are implemented:
When the cursor is on a line and that line is an incomplete input, submit a minimum amount of lines to produce a complete input.
After that, the cursor in the editor is advanced accordingly.
Because of my unfamiliarity with the source code, I have used some code that is clearly not acceptable. I would appreciate if the reviewers can help with improving the code.
I have attached a video clip above to help visualize the feature.
Has this been implemented? If not, when? This is a great addition that I have been hoping for for quite some time. Thank you!
@Jmarks199 I compile from source to use this feature. Hope this will get looked at by the PyCharm developers.
Hi @guoci! Sorry for the late response.
This is really interesting feature, but I think it's worth creating a separate action (for example "Smart Execute Line"), because it changes the original action significantly.
Your implementation need some improvements as well. It isn't a good idea to create a separate Python process for every action run just to check it's syntax correctness. You can look into checkComplete method in PyConsoleEnterHandler
class. We use this class to handle "Enter" pressed in Python Console to check whether we should execute current command or not. I think it would be better to use it instead of passing code to a Python process.
This new action is a nice idea, but I think it need some investigation and testing before including it into PyCharm release. I would like to suggest you to implement it as a PyCharm plugin. So you (and some other users) will be able to use it without manual compiling PyCharm from sources, and you won't depend on our approval.
You can learn about plugin development here: https://www.jetbrains.com/help/idea/plugin-development-guidelines.html. All you need is to create and register a new action (similar to PyExecuteSelectionAction
) and rewrite syntax checking.
Please let me know whether you want to implement this feature as a plugin or you want to continue work on the pull request.
Thank you very much for your interest and for your pull request!
@Elizaveta239 thanks for your reply. Agreed, the action should have a new name.
The checkComplete method doesn't replicate the behavior of the python code. It only checks if some code is valid. If we have compound statements with blank lines, e.g.
class C:
def f():pass
def g():pass
checking for syntax validity will not work here. Code ending at line 2 and line 5 are both valid.
For my own implementation (not in this PR), I start a single Python process once and communicate with it repeatedly through PyCharm to reduce overhead. I haven’t figured out how to implement that within PyCharm yet.
I will prefer it to be a builtin feature, but I will look into working on a plugin if the PyCharm developers don't approve the feature.
@guoci It's still unclear for me, how you decide which piece of code should be executed. Is it a syntactically correct piece of code, which beginning is on the line with cursor and it's surrounded by empty lines?
@Elizaveta239 It is the maximum number of lines starting from the current line (line the cursor is at) such that the number of top-level statements=1. If the cursor is at the beginning of
if 0:
print(1)
else:
print(2)
print(3)
then submitted code is
if 0:
print(1)
else:
print(2)
. The else part will not be left out, as would happen if you type that code in a python shell. We stop at print(3)
because it is another top-level statement.
In short, we submit lines until we reach a new top-level statement or when the file ends, consistent with how code will behave in a script. Blank lines in a compound statement do not matter.
@guoci I got it, thank you! But on the first screen cast you're sending together 3 lines on the top level:
%%time
import time
time.sleep(1)
Anyway, I believe any of this rules can be implemented using static analysis, without sending commands to Python. For example, you can get cursor position, find its PsiElement by offset:
PsiDocumentManager psiDocumentManager = PsiDocumentManager.getInstance(project);
psiDocumentManager.commitDocument(editor.getDocument());
PsiFile psiFile = psiDocumentManager.getPsiFile(editor.getDocument());
VisualPosition caretPos = editor.getCaretModel().getVisualPosition();
int line = caretPos.getLine();
int offset = DocumentUtil.getFirstNonSpaceCharOffset(editor.getDocument(), line);
PsiElement psiElement = psiFile.findElementAt(offset);
And after that you can inspect elements in file, get elements of the same level or on top level (psiElement.getChildren()
and psiElement.getParent()
). There many useful functions in PsiTreeUtil
class as well.
@Elizaveta239 thanks for your time on this and your code examples. I will try reimplementing it with intellij's code. For that 3 lines of code, it is a IPython cell magic code block and so it makes sense to execute all of it. IPython shell translates it to a single statement as standard python code.
@Elizaveta239 I have reimplemented the feature with Intellij's parsing code.
Hi @guoci! Thank you very much! It looks much better now! But it still changes "Execute Selection" action behavior. I think it would be better to create a separate action, so there will be two different actions in a context menu: Execute Selection and Smart Execute Selection. You can read more about new custom actions here: http://www.jetbrains.org/intellij/sdk/docs/tutorials/action_system/working_with_custom_actions.html
I can do it on my own but later, because I'm busy with other tasks at the moment.
Hi @Elizaveta239, I have separated the actions, binding the new action to alt shift A
When there is a code selection, both of the actions behave the same.
But I was thinking if it would be better to replace the original behavior when no code is selected. Although both actions are different when no code is selected, I believe the average user would prefer this new action.
@Elizaveta239 is this PR ok? Let me know if I need to do more.
Hi @guoci! Yes, the PR is ok, thank you! The feature looks interesting, but we still can't estimate its usefulness. Why don't you want to publish it as a separate plugin and share it within JetBrains plugin repository? If it's popular, we'll merge it into PyCharm code base.
@Elizaveta239 thanks! I will need some time to get that done.
@Elizaveta239 where are the instructions for creating a PyCharm plugin? I can find one for creating a Intellij plugin https://www.jetbrains.org/intellij/sdk/docs/, but not for a PyCharm plugin.
@guoci In fact all PyCharm plugins are Intellij IDEA plugins. So you should develop it as IDEA plugin, and mention in settings, that your plugin is compatible only with PyCharm, not with other Intellij-based IDEs.
We even had a webinar about plugin development recently: https://blog.jetbrains.com/pycharm/2019/01/webinar-recording-live-development-of-a-pycharm-plugin-with-joachim-ansorg/ So you can follow steps from it: https://github.com/jansorg/pycharm-webinar-base
Now published as PyCharm plugin. https://plugins.jetbrains.com/plugin/11945-python-smart-execute
Great news! Usually plugin approval takes a few days, I'll ask to make it faster. Thank you very much for your contribution!
Hi @guoci. I just wanted to thank you for he creation of this plugin. For those of us who are learning Python after a background in R, this comes very very handy. Thanks!
@carlosahumada89 Thanks. Me too, I tried to implement this feature to emulate RStudio's Run Selected Line(s) Crtl+Enter
feature. Since Python is not a curly-brace language, the implementation is more complicated.
AFAIK, no Python IDE has this feature.
Actually there is a relatively new pycharm plug-in that works perfectly. Not sure the name at the moment.
Sent from my iPhone
On Aug 30, 2019, at 11:31 AM, guoci <[email protected]mailto:[email protected]> wrote:
@carlosahumada89https://github.com/carlosahumada89 Thanks. Me too, I tried to implement this feature to emulate RStudio's Run Selected Line(s) Crtl+Enter feature. Since Python is not a curly-brace language, the implementation is more complicated.
AFAIK, no Python IDE has this feature.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://github.com/JetBrains/intellij-community/pull/711?email_source=notifications&email_token=AH2CEGBO5IL6ZXD2VMJQ7TDQHE4MJA5CNFSM4EMIWYUKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD5R7S6Y#issuecomment-526645627, or mute the threadhttps://github.com/notifications/unsubscribe-auth/AH2CEGC5ILTKUW2U64O5B4LQHE4MJANCNFSM4EMIWYUA.
@Jmarks199 yes, I am the author of that plugin, link below. The code is based on this PR. https://plugins.jetbrains.com/plugin/11945-python-smart-execute
@guoci @Elizaveta239 @traff Maybe it's time to merge it? I've just implemented pretty the same feature for R plugin. Looks like that's really useful for DataScience mode.
@vedun-z Sure, but at the moment it requires some steps from one of the JetBrains team members. We need to:
- find a shortcut, which doesn't overlap any other action from Intellij IDEA Ultimate (currently
Alt + Shift + A
overlaps "Show all affected files" action) - create a build from this branch and pass it to QA team
- make fixes after testing
- review code and find possible issues there
Unfortunately, I'm currently busy with other tasks. @vedun-z You're welcome to do these steps.
@Elizaveta239 Thank you for great opportunity, but as long as this feature are not going to 2019.3 anyway, there's no reason to rush. We could schedule it to 2020.1, what do you think?
Sure! I've created a feature request for it: https://youtrack.jetbrains.com/issue/PY-38919
@vedun-z @Elizaveta239 it would be nice to get this going again. It's really surprising this hasn't been added as a feature. The real question is, why would anyone ever want to use the default execute in console functionality? Personally, I can't imagine using Pycharm without this feature and the plugin seems to be broken in version 2021.3.
java.lang.NoSuchMethodError: 'void com.jetbrains.python.actions.PyExecuteSelectionAction.showConsoleAndExecuteCode(com.intellij.openapi.actionSystem.AnActionEvent, java.lang.String)'
I have just uploaded an update, currently pending approval from JetBrains. @Jmarks199 Thanks for reporting, you can download it here before the approval.
For code to the plugin, see https://github.com/guoci/pycharm-smart-execute. The code in this PR is no longer working due to API changes.