Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add API to extend and overload actions #12859

Open
goanpeca opened this issue May 26, 2020 · 5 comments
Open

Add API to extend and overload actions #12859

goanpeca opened this issue May 26, 2020 · 5 comments
Assignees

Comments

@goanpeca
Copy link
Member

Extend new API to easily override actions:

Run,
File Open
Save, etc...

@goanpeca goanpeca self-assigned this May 26, 2020
@jitseniesen
Copy link
Member

See also #9514, #8798, #7794.

@goanpeca
Copy link
Member Author

goanpeca commented May 26, 2020

To make this simpler, the new core plugin will probably create all the menus that handles "global" actions, like the ones described here. I will then add a couple of methods to the plugin api something like

# spyder.api.plugins
class ActionConditions:
    PluginHasFocus = 'plugin_has_focus'


class SpyderDockablePlugin:
    # ...
    def extend_action(self, action, triggered=None, toggled=None):
        # to add additional behavior when triggered

    # and

    def overload_action(self, action, triggered=None, toggled=None, condition=None):
        # to overload/replace behavior when triggered


# spyder.api.plugins.some_plugin.plugin
class SomeSpyderPlugin(SpyderDockablePlugin):
    # ...
    def register(self):
        run_action = self.get_plugin(Plugins.Core).get_action(CoreActions.Run)
        self.overload_action(
            run_action,
            triggered=self.some_new_method,
            condition=ActionConditions.PluginHasFocus,
        )
        # If this is Spyder Reports, render the report,
        # if this is a script on the Editor run the script on the console etc...

    def some_new_method(self):
        pass

On the second case need to think about possible conditions, having the overloader plugin be in Focus seems to be the common use case. I think creating an action will also have an extendable/overloadable flag so only certain actions can be used like this?

If we want to apply this to any action then we could create a helper method that could take care of this on behalf of the user so that it does not depend on core. Both are doable, but the former probably requires less lines of code and might seem cleaner.

Things to keep into account:

  • An extendable action needs to be extended or overloaded to be enabled besides the conditions. It could also be invisible until some plugin extends it.
  • The condition could also be a callable returning True or False, so the user can have a arbitrary method perform any necessary checks. For instance check if the file starts with test_so instead of running the file, it would run the test suite with the file.

@ccordoba12 and @jitseniesen any other cases to take into account or additional thoughts?

@jitseniesen
Copy link
Member

I would start the design from the user stories: what do we want the user experience to look like?

I am thinking of the notebook plugin, because that is occupying my mind at the moment.

For File > New, perhaps we want a submenu with "New notebook" and "New file" (and perhaps "New project"). This does not seem to fall neatly in your overload / extend cases.

For File > Open, I would expect the file to open in the notebook plugin if it is a notebook file and in the editor otherwise. This also does not seem to fall neatly in your overload / extend cases.

For File > Save, perhaps we want the plugin which has focus to do the save. So this seems an example of an overloadable action as described above, conditioned on focus. How far do we take this, e.g. the variable explorer has a Save action, which the user may not expect to be triggered by File > Save. And what do we do if the plugin with focus can't save?

For File > Save All, I guess we want all plugins to save all files. This is an extendable action as described above.

For Run, this looks like an overloadable action conditioned on focus, but I am not sure whether it would be clear to the user what this does on a notebook. Perhaps we want to change the label to "Run Entire Notebook". Or perhaps we want to overload the entire "Run" menu?

For inspiration, Jupyter Lab uses something called Semantic Menu Items to achieve this.

I do think we want to restrict the actions that can be overloaded / extended, at least initially.

@goanpeca
Copy link
Member Author

goanpeca commented May 27, 2020

Hi @jitseniesen

Thanks for the feedback.

For the first case you describe that is not really an extension or overload it is just a new action inside a submenu.

For File > Open, I would expect the file to open in the notebook plugin if it is a notebook file and in the editor otherwise. This also does not seem to fall neatly in your overload / extend cases.

This is a different case as well since there might be an actual reason to open a nb in the editor, but the default case should probably do as you describe. This is not really an overloading but more of a file registry so the open command also is a different case.

This is aimed at the other cases you describe, like is for save, run, redo undo copy paste.

There should probably be a default action and in case there is no focus we could either use the latest used or use this default.

If the plugin with focus cannot do an action it will be disabled 🤷🏻‍♂️ or it would not do anything (or default to the default action which is spyder is probably save the file in the editor)

Will take a look at the jlab thinguie.

@ccordoba12
Copy link
Member

I do think we want to restrict the actions that can be overloaded / extended, at least initially.

I agree with this.

@goanpeca goanpeca mentioned this issue Sep 15, 2020
34 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants