Hello, This is a really interesting question.
2 seems like the best combination of elegant and simple to me, but really it's your preference. I wonder what other Guilers think. Best, Noah On Thu, Aug 29, 2013 at 4:57 PM, Shane Celis <shane.ce...@gmail.com> wrote: > Hello guilers, > > I'm developing Emacsy[1], and I'm trying to design a good way of grouping > and exposing interactive commands. My interest is specifically related to > Emacsy, but for guilers in general the question is, How should one provide > exports of a different flavor? We have only "public" exports. In my case > I want a "command" flavor of export. But I might want to export > "customizable" variables, or "minor-mode"s. I'm not trying to tackle the > general task here. > > In Emacs all commands are in the same namespace. Hit M-x TAB , and you'll > probably see thousands of them (I've got ~6k). A lot of the commands may > only be appropriate in certain modes, so I'm playing around with how best > we can go about grouping and exposing commands. My idea is that M-x only > shows commands that are in the current COMMAND_PATH, somewhat like a bash > PATH. To show all commands, one can type C-u M-x. > > A command in Emacsy is a procedure that requires no arguments. It's > written for the user to invoke on command M-x or from a key binding. When > called interactively, it'll ask the user for information. When called with > all arguments provided, it will run non-interactively. > > Suppose I have the following code which creates a command called 'echo': > > (define-module (my-great-mode) > #:use-module (ice-9 optargs) > #:use-module (emacsy) > #:export (some-other-proc)) > > (define (some-other-proc) > "I am not a command." > #f) > > (define* (echo #:optional (text (read-from-minibuffer "Echo what: "))) > (message text)) > > (export-command echo) > > This module exports the procedure "some-other-proc" and I want it to > _somehow_ export a command called "echo". The question is how to export > this other thing, this command? I have a couple of ideas, most based off > grouping some subset of procedures as commands inside a module, and using > modules to group the commands. > > 1. Create a command-interface module similar to the public-interface that > modules have. So instead of 'resolve-interface' and 'export', I'd have > 'resolve-command-interface' and 'export-command'. > > A (resolve-command-interface '(my-great-mode)) would return a module > (%module-command-interface) that contained bindings for all that module's > commands. This is the module that COMMAND_PATH would use for commands. > > PRO: One could export commands and procedures entirely independently. > Also, one can use the module mechanisms of selecting a subset, algorithmic > renaming, etc. on these command modules. > CON: It seems like a lot of magic, but it's using the same mechanisms that > public interfaces use. > > 2. Have (export-command) just keep a list of commands, but just export a > custom public interface. So it might look like this internally: > > (define (export-command-proc names) > (set! %command-set (append! %command-set names))) > > (define (resolve-command-interface module-name) > (resolve-interface module-name #:select %command-set)) > > PRO: Less magic-y. > CON: One must export a command to both the public interface and the > command; maybe that's ok even preferable that they're not independent. > > 3. Have (export-command) create a new sub-module (my-great-mode %command). > > PRO: Not too tricky. > CON: Pollutes the module namespace a little bit. > > 4. Still use modules, but make the user segregate their procedures and > commands into separate modules manually. So the user would have to define > modules (my-great-mode) and (my-great-mode commands). > > PRO: No magic. Programmer does everything. > CON: Everything is managed by convention. Separating the commands and > procedures might be an awkward boundary. Consider an internal procedure in > (my-great-mode) that a command wants to use in (my-great-mode commands). > Do you expose it as public? Move it around? Use @@ to get to it? > > 5. Don't use modules at all. Make the user collect and manage > <command-set>s the same way they manage keymaps, for instance. > > PRO: Nothing tricky, doesn't use modules at all. No magic. > CON: It has to work with the command being redefined; we can't just keep > the command procedure; we have to keep the variable which points to modules > possibly being a better solution. > > 6. Tag commands as special procedures perhaps by adding something to their > procedure properties. Implement a "command?" procedure. Export commands > and procedures to the same module. Then just pluck the commands out of all > the procedures by using command?. > > PRO: No new modules. No new exports. > CON: Adding something to the procedure makes wrapping commands in other > lambdas awkward. Might necessitate a define-command, lambda-command, > method-command, which I'd prefer to avoid. > > * * * > > Thanks for indulging my scheme design question. What's the right thing to > do? What would you do? > > -Shane > > [1]: https://github.com/shanecelis/emacsy >