emacs M-x completes to commands that are not Yi.Keymap.Action #292

Open
ethercrow opened this Issue Nov 19, 2012 · 15 comments

Comments

Projects
None yet
3 participants
@ethercrow
Member

ethercrow commented Nov 19, 2012

Original author: juhpeter...@gmail.com (April 01, 2009 03:38:51)

What steps will reproduce the problem?

  1. yi --as=emacs
  2. M-x
  3. Backward RET

What is the expected output?
2. M-x should not suggest Backward, etc if it can't execute them.

What do you see instead?
2. minibuffer shows:
"""
M-x

Backward Character Document Forward Line Point atBoundaryB cabalBuildE
cabalConf
"""
3. minibuffer says "error: value doesn't have type Yi.Keymap.Action"

Please provide relevant version information:

What version of Yi are you using? darcs head
What version of GHC? 6.10.1
What operating system/version? Fedora 10

Original issue: http://code.google.com/p/yi-editor/issues/detail?id=260

@ethercrow

This comment has been minimized.

Show comment
Hide comment
@ethercrow

ethercrow Nov 19, 2012

Member

From juhpeter...@gmail.com on April 01, 2009 03:40:26
(cabalBuildE cabalConfigureE work:)

Member

ethercrow commented Nov 19, 2012

From juhpeter...@gmail.com on April 01, 2009 03:40:26
(cabalBuildE cabalConfigureE work:)

@ethercrow

This comment has been minimized.

Show comment
Hide comment
@ethercrow

ethercrow Nov 19, 2012

Member

From JeanPhil...@gmail.com on April 03, 2009 17:05:22
This would be a very nice addition to make to the "hint" interpreter.
http://hackage.haskell.org/cgi-bin/hackage-scripts/package/hint-0.3.1.0

Member

ethercrow commented Nov 19, 2012

From JeanPhil...@gmail.com on April 03, 2009 17:05:22
This would be a very nice addition to make to the "hint" interpreter.
http://hackage.haskell.org/cgi-bin/hackage-scripts/package/hint-0.3.1.0

@mgajda

This comment has been minimized.

Show comment
Hide comment
@mgajda

mgajda Nov 8, 2014

Contributor

I thought that was intended behaviour? Wasn't it?

I understand it is governed by list of modules imported in Yi.Eval. I just looked there, and there were only all of Yi and Yi.Keymap. That's a lot of identifiers, and most of them are not actions, but some may serve to build a parameter of an action.

In particular flattenExports includes all record field selectors, and all class methods. Unfortunately checking the type from Hint seems a bit more resource consuming ATM.

Contributor

mgajda commented Nov 8, 2014

I thought that was intended behaviour? Wasn't it?

I understand it is governed by list of modules imported in Yi.Eval. I just looked there, and there were only all of Yi and Yi.Keymap. That's a lot of identifiers, and most of them are not actions, but some may serve to build a parameter of an action.

In particular flattenExports includes all record field selectors, and all class methods. Unfortunately checking the type from Hint seems a bit more resource consuming ATM.

@Fuuzetsu

This comment has been minimized.

Show comment
Hide comment
@Fuuzetsu

Fuuzetsu Nov 8, 2014

Member

There is no checking of type we can do from Hint because it's all Action.

We're currently considering ditching Hint for M-x and using lookup tables because it lets us to specify exactly what gets exported (this issue), extend it as modes are activated, easily allows user to expose extra stuff through config and so on. The downside is that we need to maintain such tables of course but it's less effort (and much faster) than trying to achieve similar through hint.

Member

Fuuzetsu commented Nov 8, 2014

There is no checking of type we can do from Hint because it's all Action.

We're currently considering ditching Hint for M-x and using lookup tables because it lets us to specify exactly what gets exported (this issue), extend it as modes are activated, easily allows user to expose extra stuff through config and so on. The downside is that we need to maintain such tables of course but it's less effort (and much faster) than trying to achieve similar through hint.

@mgajda

This comment has been minimized.

Show comment
Hide comment
@mgajda

mgajda Nov 9, 2014

Contributor

I thought it was already implemented, and user-configurable by changing yiConfig { evaluator = publishedActionEvaluator }? Since there may be people that prefer full power of Haskell command line within the editor?

Contributor

mgajda commented Nov 9, 2014

I thought it was already implemented, and user-configurable by changing yiConfig { evaluator = publishedActionEvaluator }? Since there may be people that prefer full power of Haskell command line within the editor?

@mgajda

This comment has been minimized.

Show comment
Hide comment
@mgajda

mgajda Nov 9, 2014

Contributor

Even better idea would be to just limit a set of published actions by replacing getAllNamesInScope method of ghciEvaluator, and thus only changing completion mechanism, not the execution features.

Contributor

mgajda commented Nov 9, 2014

Even better idea would be to just limit a set of published actions by replacing getAllNamesInScope method of ghciEvaluator, and thus only changing completion mechanism, not the execution features.

@Fuuzetsu

This comment has been minimized.

Show comment
Hide comment
@Fuuzetsu

Fuuzetsu Nov 9, 2014

Member

I thought it was already implemented, and user-configurable by changing yiConfig { evaluator = publishedActionEvaluator }?

I believe it is currently not used anywhere, the idea is to make it a first-class member that users/modes can expand rather than an obscure field that's not used by anything.

Since there may be people that prefer full power of Haskell command line within the editor?

Hint will stay, just not for M-x. It is hardly ‘full power of Haskell’ at the moment anyway.

Even better idea would be to just limit a set of published actions by replacing getAllNamesInScope method of ghciEvaluator, and thus only changing completion mechanism, not the execution features.

This only solves this issue and makes us maintain such a completion method without benefits of fully-exposed table.

Member

Fuuzetsu commented Nov 9, 2014

I thought it was already implemented, and user-configurable by changing yiConfig { evaluator = publishedActionEvaluator }?

I believe it is currently not used anywhere, the idea is to make it a first-class member that users/modes can expand rather than an obscure field that's not used by anything.

Since there may be people that prefer full power of Haskell command line within the editor?

Hint will stay, just not for M-x. It is hardly ‘full power of Haskell’ at the moment anyway.

Even better idea would be to just limit a set of published actions by replacing getAllNamesInScope method of ghciEvaluator, and thus only changing completion mechanism, not the execution features.

This only solves this issue and makes us maintain such a completion method without benefits of fully-exposed table.

@mgajda

This comment has been minimized.

Show comment
Hide comment
@mgajda

mgajda Nov 9, 2014

Contributor

I used it for some time a while ago, but for current use we would add many more actions, and their comments.

I would still stick to the current Evaluator structure, possibly expanding it, since it is well engineered.

Contributor

mgajda commented Nov 9, 2014

I used it for some time a while ago, but for current use we would add many more actions, and their comments.

I would still stick to the current Evaluator structure, possibly expanding it, since it is well engineered.

@Fuuzetsu

This comment has been minimized.

Show comment
Hide comment
@Fuuzetsu

Fuuzetsu Nov 9, 2014

Member

How do you propose M-x is extended by user/modes (including removal when modes are turned off/switched) keeping it as-is?

I would only use the Evaluator to actually evaluate some code in a buffer and whatnot rather than making it the central driver behind M-x. Even emacs doesn't have code eval in M-x, you spawn an eval prompt with separate command (C-:).

Member

Fuuzetsu commented Nov 9, 2014

How do you propose M-x is extended by user/modes (including removal when modes are turned off/switched) keeping it as-is?

I would only use the Evaluator to actually evaluate some code in a buffer and whatnot rather than making it the central driver behind M-x. Even emacs doesn't have code eval in M-x, you spawn an eval prompt with separate command (C-:).

@mgajda

This comment has been minimized.

Show comment
Hide comment
@mgajda

mgajda Nov 9, 2014

Contributor

You may put every new action I want into .config/yi/Env.hs.

Contributor

mgajda commented Nov 9, 2014

You may put every new action I want into .config/yi/Env.hs.

@Fuuzetsu

This comment has been minimized.

Show comment
Hide comment
@Fuuzetsu

Fuuzetsu Nov 9, 2014

Member

You still can't remove actions based on which mode is up &c.

Member

Fuuzetsu commented Nov 9, 2014

You still can't remove actions based on which mode is up &c.

@mgajda

This comment has been minimized.

Show comment
Hide comment
@mgajda

mgajda Nov 9, 2014

Contributor

Yes, it needs extension to multiple environments here. EnvNormal.hs, EnvInsert.hs?

But, of course, it may be better to just a custom action filter, that will modify names given by getAllNamesInScope to filter actions only (even if you can use operators for arguments.)

BTW How much would it fix current behaviour, if we import only Yi.Keymap.Actions instead of whole Yi and Yi.Keymap? We may also add Yi.Keymap.Actions.Published that only exports the published actions. I would implement this part, but Yi.Keymap.Actions doesn't seem to exist any more. I do not feel competent to make a list of actions that would make everyone happy ATM (I don't use all functionalities.)

As for documentation, I still hope for a haddock solution, because it is much less effort to keep it up-to-date.

Contributor

mgajda commented Nov 9, 2014

Yes, it needs extension to multiple environments here. EnvNormal.hs, EnvInsert.hs?

But, of course, it may be better to just a custom action filter, that will modify names given by getAllNamesInScope to filter actions only (even if you can use operators for arguments.)

BTW How much would it fix current behaviour, if we import only Yi.Keymap.Actions instead of whole Yi and Yi.Keymap? We may also add Yi.Keymap.Actions.Published that only exports the published actions. I would implement this part, but Yi.Keymap.Actions doesn't seem to exist any more. I do not feel competent to make a list of actions that would make everyone happy ATM (I don't use all functionalities.)

As for documentation, I still hope for a haddock solution, because it is much less effort to keep it up-to-date.

@Fuuzetsu

This comment has been minimized.

Show comment
Hide comment
@Fuuzetsu

Fuuzetsu Nov 10, 2014

Member

Yes, it needs extension to multiple environments here. EnvNormal.hs, EnvInsert.hs?

So rather than simply saying ‘add this Map to available actions‘ you'd create a new module for every single environment you could possibly want, take care to only export actions we want to see and then tell hint to import that? And how do we unload modules? How do we only load some functions from the modules? This approach doesn't scale and is hostile to user-defined (or mode-defined) functions. Also it doesn't scale because we'll need to load more and more modules which would slow it down considerably.

But, of course, it may be better to just a custom action filter, that will modify names given by getAllNamesInScope to filter actions only (even if you can use operators for arguments.)

And how will you do that for arbitrary input from the user/mode?

BTW How much would it fix current behaviour, if we import only Yi.Keymap.Actions instead of whole Yi and Yi.Keymap? We may also add Yi.Keymap.Actions.Published that only exports the published actions. I would implement this part, but Yi.Keymap.Actions doesn't seem to exist any more. I do not feel competent to make a list of actions that would make everyone happy ATM (I don't use all functionalities.)

The point of the discussion we're having right now is that while it is possible to fix this issue with current Hint setup (such as by having a dedicated module with re-exports), we should instead do it differently which solves this problem AND other problems (extensible, easily modifiable, overridable) that are vital for user modes and usability in general as well as much more efficient. As you say yourself, making a list of actions is hard: you don't know what people use and what you use so Hint approach is even harder. But it's easy to let the user provide a Map exposing the actions they want.

As for documentation, I still hope for a haddock solution, because it is much less effort to keep it up-to-date.

I also hope we can leverage Haddock. We could probably read Haddock's interface files in the end but I'm not thinking about this just now. By the way, Map approach allows us to employ a temporary solution of attaching documentation explicitly and Hint does not. Another reason to not use Hint for this.

In summary, yes, we could fix this issue while using Hint but it's close-minded and doesn't fix other problems.

Member

Fuuzetsu commented Nov 10, 2014

Yes, it needs extension to multiple environments here. EnvNormal.hs, EnvInsert.hs?

So rather than simply saying ‘add this Map to available actions‘ you'd create a new module for every single environment you could possibly want, take care to only export actions we want to see and then tell hint to import that? And how do we unload modules? How do we only load some functions from the modules? This approach doesn't scale and is hostile to user-defined (or mode-defined) functions. Also it doesn't scale because we'll need to load more and more modules which would slow it down considerably.

But, of course, it may be better to just a custom action filter, that will modify names given by getAllNamesInScope to filter actions only (even if you can use operators for arguments.)

And how will you do that for arbitrary input from the user/mode?

BTW How much would it fix current behaviour, if we import only Yi.Keymap.Actions instead of whole Yi and Yi.Keymap? We may also add Yi.Keymap.Actions.Published that only exports the published actions. I would implement this part, but Yi.Keymap.Actions doesn't seem to exist any more. I do not feel competent to make a list of actions that would make everyone happy ATM (I don't use all functionalities.)

The point of the discussion we're having right now is that while it is possible to fix this issue with current Hint setup (such as by having a dedicated module with re-exports), we should instead do it differently which solves this problem AND other problems (extensible, easily modifiable, overridable) that are vital for user modes and usability in general as well as much more efficient. As you say yourself, making a list of actions is hard: you don't know what people use and what you use so Hint approach is even harder. But it's easy to let the user provide a Map exposing the actions they want.

As for documentation, I still hope for a haddock solution, because it is much less effort to keep it up-to-date.

I also hope we can leverage Haddock. We could probably read Haddock's interface files in the end but I'm not thinking about this just now. By the way, Map approach allows us to employ a temporary solution of attaching documentation explicitly and Hint does not. Another reason to not use Hint for this.

In summary, yes, we could fix this issue while using Hint but it's close-minded and doesn't fix other problems.

@mgajda

This comment has been minimized.

Show comment
Hide comment
@mgajda

mgajda Nov 10, 2014

Contributor

I offered my help and contribution, and got an answer about 'close-minded' and wrong solution.
It sounds almost like my voice was not welcome :-D.

Even though, I risk a flamewar, and I'd argue that blindly following complex Emacs solutons is not the way to go. Since we can textually filter completions, and freely juggle sub-scopes using Hint, it would be a reckless abandon of arbitrary subexpression arguments.
And significant increase of effort by the need of maintenance of published actions list beside module exports. May it be better to use Template Haskell to expose a submodule for each mode, and thus assure that mode-specific bindings will be exposed only then?
I thought that the whole point of using Haskell-based editor would be to consistently use Haskell for scripting, actions, and configuration, and thus abandon the need to invent three different languages, and even more duplicated namespaces.

That is just an argument for the superiority of homogeneous Haskell-based (hint) solution.
What you say, is that it seems difficult (oh my, I try to be even worse in my arguments) to interface with the module namespaces, and thus you want to make the solution more complex to engineer, maintain, and understand (by replicating namespaces in different dictionaries), because of desire to easily implement it in an inferior way to most users (by arbitrarily constraining scripting capability to a limited set of actions.)

That sounds wrong in principle! (Ok, sorry for that. Felt compelled to counter the technical argument.)

Contributor

mgajda commented Nov 10, 2014

I offered my help and contribution, and got an answer about 'close-minded' and wrong solution.
It sounds almost like my voice was not welcome :-D.

Even though, I risk a flamewar, and I'd argue that blindly following complex Emacs solutons is not the way to go. Since we can textually filter completions, and freely juggle sub-scopes using Hint, it would be a reckless abandon of arbitrary subexpression arguments.
And significant increase of effort by the need of maintenance of published actions list beside module exports. May it be better to use Template Haskell to expose a submodule for each mode, and thus assure that mode-specific bindings will be exposed only then?
I thought that the whole point of using Haskell-based editor would be to consistently use Haskell for scripting, actions, and configuration, and thus abandon the need to invent three different languages, and even more duplicated namespaces.

That is just an argument for the superiority of homogeneous Haskell-based (hint) solution.
What you say, is that it seems difficult (oh my, I try to be even worse in my arguments) to interface with the module namespaces, and thus you want to make the solution more complex to engineer, maintain, and understand (by replicating namespaces in different dictionaries), because of desire to easily implement it in an inferior way to most users (by arbitrarily constraining scripting capability to a limited set of actions.)

That sounds wrong in principle! (Ok, sorry for that. Felt compelled to counter the technical argument.)

@Fuuzetsu

This comment has been minimized.

Show comment
Hide comment
@Fuuzetsu

Fuuzetsu Nov 10, 2014

Member

I offered my help and contribution, and got an answer about 'close-minded' and wrong solution.
It sounds almost like my voice was not welcome :-D.

Well, I don't mean to offend and it's certainly not ‘not welcome’. It just seems to fix this issue and this issue only and it seems like the wrong fix in general to employ.

I thought that the whole point of using Haskell-based editor would be to consistently use Haskell for scripting, actions, and configuration, and thus abandon the need to invent three different languages, and even more duplicated namespaces.

Maps would still be using Haskell. It would be no different than it is now. The only difference is the source of the Actions: currently they come from Hint. I propose they should come from somewhere else, in this case some Map. Reasoning is simple: we can easily change the Map, we can't easily change Hint output.

What you say, is that it seems difficult (oh my, I try to be even worse in my arguments) to interface with the module namespaces, and thus you want to make the solution more complex to engineer, maintain, and understand

I agree namespacing may become awkward but it is not very difficult. If we want to prefix commands from some mode, map over keys. To achieve the same thing in Hint we'd have to import all modules we're interested in, rename clashes, re-export everything and have Hint load it.

Additonally, easy access to the names may prove beneficial: we may want to override certain available actions (consider situation where we eval some piece of code (through Hint or otherwise) and want it to be available in M-x immedatielly instead of the old version). With Map it is easy, simply replace that name. With Hint, not so much: you'll either have to have a different name or Hint will throw a fit about a name clash.

because of desire to easily implement it in an inferior way to most users (by arbitrarily constraining scripting capability to a limited set of actions.)

This is incorrect, nothing is being constrained. Hint does a simple thing, it spits out Action. Our Map would also spit out Action. The power is the same, the only thing that changes is ease of extension and modification.

My ‘proposal’ is simple: source actions for M-x from a Map instead from Hint. Motivation is also simple: we can easily change the Map, we can't easily change what Hint has available. As a side effect, using Map fixes this issue because we can specify exactly which actions we want. If we're going to instead fix this issue by mandating the choices Hint shows, how is that any more flexible than the Map approach? Either way we have to maintain some sort of list of functions so why not use this fact and solve other problems along the way?

Removing hint from M-x all together (at least by default) is a good thing: it makes Yi faster, it makes it take less memory and it makes it easy to try. I get questions frequently about why M-x doesn't work (due to messed up GHC_PACKAGE_PATH or else) or why user-defined functions don't show up (because Hint doesn't load the module they defined them in). With Map first question doesn't exist. Second question can simply be answered with ‘just put them in this Map’. With Hint first question is a big problem because it depends heavily on user's setup. Second question is also not easy to answer. So in light of this I think what is wrong in principle is to fix and close this issue by changing Hint code.

Member

Fuuzetsu commented Nov 10, 2014

I offered my help and contribution, and got an answer about 'close-minded' and wrong solution.
It sounds almost like my voice was not welcome :-D.

Well, I don't mean to offend and it's certainly not ‘not welcome’. It just seems to fix this issue and this issue only and it seems like the wrong fix in general to employ.

I thought that the whole point of using Haskell-based editor would be to consistently use Haskell for scripting, actions, and configuration, and thus abandon the need to invent three different languages, and even more duplicated namespaces.

Maps would still be using Haskell. It would be no different than it is now. The only difference is the source of the Actions: currently they come from Hint. I propose they should come from somewhere else, in this case some Map. Reasoning is simple: we can easily change the Map, we can't easily change Hint output.

What you say, is that it seems difficult (oh my, I try to be even worse in my arguments) to interface with the module namespaces, and thus you want to make the solution more complex to engineer, maintain, and understand

I agree namespacing may become awkward but it is not very difficult. If we want to prefix commands from some mode, map over keys. To achieve the same thing in Hint we'd have to import all modules we're interested in, rename clashes, re-export everything and have Hint load it.

Additonally, easy access to the names may prove beneficial: we may want to override certain available actions (consider situation where we eval some piece of code (through Hint or otherwise) and want it to be available in M-x immedatielly instead of the old version). With Map it is easy, simply replace that name. With Hint, not so much: you'll either have to have a different name or Hint will throw a fit about a name clash.

because of desire to easily implement it in an inferior way to most users (by arbitrarily constraining scripting capability to a limited set of actions.)

This is incorrect, nothing is being constrained. Hint does a simple thing, it spits out Action. Our Map would also spit out Action. The power is the same, the only thing that changes is ease of extension and modification.

My ‘proposal’ is simple: source actions for M-x from a Map instead from Hint. Motivation is also simple: we can easily change the Map, we can't easily change what Hint has available. As a side effect, using Map fixes this issue because we can specify exactly which actions we want. If we're going to instead fix this issue by mandating the choices Hint shows, how is that any more flexible than the Map approach? Either way we have to maintain some sort of list of functions so why not use this fact and solve other problems along the way?

Removing hint from M-x all together (at least by default) is a good thing: it makes Yi faster, it makes it take less memory and it makes it easy to try. I get questions frequently about why M-x doesn't work (due to messed up GHC_PACKAGE_PATH or else) or why user-defined functions don't show up (because Hint doesn't load the module they defined them in). With Map first question doesn't exist. Second question can simply be answered with ‘just put them in this Map’. With Hint first question is a big problem because it depends heavily on user's setup. Second question is also not easy to answer. So in light of this I think what is wrong in principle is to fix and close this issue by changing Hint code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment