guile-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Emacsy: Context Sensitive Commands Design Question


From: Shane Celis
Subject: Emacsy: Context Sensitive Commands Design Question
Date: Thu, 29 Aug 2013 16:57:00 -0400

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


reply via email to

[Prev in Thread] Current Thread [Next in Thread]