* Emacsy: Context Sensitive Commands Design Question
@ 2013-08-29 20:57 Shane Celis
2013-08-30 0:26 ` Noah Lavine
` (2 more replies)
0 siblings, 3 replies; 5+ messages in thread
From: Shane Celis @ 2013-08-29 20:57 UTC (permalink / raw)
To: Guile Mailing List; +Cc: Ludovic Courtès
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\x04, 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
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Emacsy: Context Sensitive Commands Design Question
2013-08-29 20:57 Emacsy: Context Sensitive Commands Design Question Shane Celis
@ 2013-08-30 0:26 ` Noah Lavine
2013-08-30 2:02 ` Mark H Weaver
2013-08-30 7:32 ` Thien-Thi Nguyen
2 siblings, 0 replies; 5+ messages in thread
From: Noah Lavine @ 2013-08-30 0:26 UTC (permalink / raw)
To: Shane Celis; +Cc: Guile Mailing List, Ludovic Courtès
[-- Attachment #1: Type: text/plain, Size: 5203 bytes --]
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.celis@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
>
[-- Attachment #2: Type: text/html, Size: 6021 bytes --]
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Emacsy: Context Sensitive Commands Design Question
2013-08-29 20:57 Emacsy: Context Sensitive Commands Design Question Shane Celis
2013-08-30 0:26 ` Noah Lavine
@ 2013-08-30 2:02 ` Mark H Weaver
2013-08-30 11:32 ` Ludovic Courtès
2013-08-30 7:32 ` Thien-Thi Nguyen
2 siblings, 1 reply; 5+ messages in thread
From: Mark H Weaver @ 2013-08-30 2:02 UTC (permalink / raw)
To: Shane Celis; +Cc: Guile Mailing List, Ludovic Courtès
Shane Celis <shane.celis@gmail.com> writes:
> 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?.
This is closest to what Emacs does, and probably the best solution, IMO. See
<https://www.gnu.org/software/emacs/manual/html_node/elisp/Interactive-Call.html>
which describes the 'commandp' predicate, whose definition is in eval.c.
Regards,
Mark
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Emacsy: Context Sensitive Commands Design Question
2013-08-29 20:57 Emacsy: Context Sensitive Commands Design Question Shane Celis
2013-08-30 0:26 ` Noah Lavine
2013-08-30 2:02 ` Mark H Weaver
@ 2013-08-30 7:32 ` Thien-Thi Nguyen
2 siblings, 0 replies; 5+ messages in thread
From: Thien-Thi Nguyen @ 2013-08-30 7:32 UTC (permalink / raw)
To: Shane Celis; +Cc: Guile Mailing List
[-- Attachment #1: Type: text/plain, Size: 1027 bytes --]
() Shane Celis <shane.celis@gmail.com>
() Thu, 29 Aug 2013 16:57:00 -0400
6. Tag commands as special procedures [...] Implement "command?"
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.
Why would you prefer to avoid this?
What would you do?
I'd explore option 6, starting w/:
(define command? (make-object-property))
I think object properties are better suited than procedure properties
after observing this in the (Emacs) *scratch* buffer:
(commandp [42])
t
It would be cool for Emacsy to have good "keyboard macros" support.
Many a non-programmer fall into consciousness via such, in Emacs.
[cc trimmed]
--
Thien-Thi Nguyen
GPG key: 4C807502
(if you're human and you know it)
read my lisp: (responsep (questions 'technical)
(not (via 'mailing-list)))
=> nil
[-- Attachment #2: Type: application/pgp-signature, Size: 197 bytes --]
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Emacsy: Context Sensitive Commands Design Question
2013-08-30 2:02 ` Mark H Weaver
@ 2013-08-30 11:32 ` Ludovic Courtès
0 siblings, 0 replies; 5+ messages in thread
From: Ludovic Courtès @ 2013-08-30 11:32 UTC (permalink / raw)
To: Shane Celis; +Cc: Guile Mailing List
Mark H Weaver <mhw@netris.org> skribis:
> Shane Celis <shane.celis@gmail.com> writes:
>
>> 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?.
>
> This is closest to what Emacs does, and probably the best solution, IMO. See
> <https://www.gnu.org/software/emacs/manual/html_node/elisp/Interactive-Call.html>
> which describes the 'commandp' predicate, whose definition is in eval.c.
I concur (Thien-Thi’s message shows how this can be achieved.)
So it’s a matter of extending Emacsy’s ‘define-interactive’ to add an
object property.
Then you could have a ‘fold-commands’ procedure that traverses all the
bindings of all the available modules (or a subset thereof), and
iterates on those that match ‘command?’.
Ludo’.
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2013-08-30 11:32 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-08-29 20:57 Emacsy: Context Sensitive Commands Design Question Shane Celis
2013-08-30 0:26 ` Noah Lavine
2013-08-30 2:02 ` Mark H Weaver
2013-08-30 11:32 ` Ludovic Courtès
2013-08-30 7:32 ` Thien-Thi Nguyen
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).