janssen@parc.xerox.com (Bill Janssen) (07/21/90)
Here it is (meta-x) as a shar file: ---- Enclosure ---- #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of shell archive." # Contents: Imakefile metax.c metax.ch # Wrapped by janssen@nora on Fri Jul 20 16:05:40 1990 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'Imakefile' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Imakefile'\" else echo shar: Extracting \"'Imakefile'\" \(248 characters\) sed "s/^X//" >'Imakefile' <<'END_OF_FILE' XLOCALINCLUDES = -I/import/local/andrew/include/atk X XDOBJS = metax.do X XIHFILES = metax.ih X XDESTDIR = /import/local/andrew X XNormalObjectRule() XNormalATKRule() XDependTarget() X XDynamicObject(metax,,$(UTILLIB)) XInstallClassFiles($(DOBJS),$(IHFILES)) END_OF_FILE if test 248 -ne `wc -c <'Imakefile'`; then echo shar: \"'Imakefile'\" unpacked with wrong size! fi # end of 'Imakefile' fi if test -f 'metax.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'metax.c'\" else echo shar: Extracting \"'metax.c'\" \(2947 characters\) sed "s/^X//" >'metax.c' <<'END_OF_FILE' X/*| -*- Mode: C -*- X/*|------------------------------------------------------------ X/*| X/*| File: metax.c X/*| Created: Thu Jun 7 19:07:32 1990 X/*| Author: Bill Janssen (janssen@holmes) X/*| $Locker$ X/*| X/*|------------------------------------------------------------ X/*| X/*| Description: X/*| X/*| Behaviour code to implement meta-x for Andrew. X/*| X/*|------------------------------------------------------------ X/*| X/*| Copyright 1990 Xerox Corporation X/*| All Rights Reserved Worldwide. X/*/ X static char xerox_copyright[] = "\ X \ X Copyright 1990 Xerox Corporation \ X All Rights Reserved"; X/*|------------------------------------------------------------ X/*| X/*| "$Header$" X/*/ X static char rcs_id[] = "$Header$"; X/*| X/*|------------------------------------------------------------ X/*/ X X#include <class.h> X X#include <view.ih> X#include <proctbl.ih> X#include <message.ih> X#include <bind.ih> X#include <im.ih> X X#include "metax.eh" X Xstatic char lastCommand[1000]; X Xstatic void callProcedure (self, key) X struct view *self; X char key; X{ X char buf[1000]; X X if (message_AskForString (self, 0 , "M-x ", "", X buf, sizeof(buf)) == -1) X { X message_DisplayString (self, 0, ""); X return; X } X X CallNamedProcedure (self, buf); X X strcpy (lastCommand, buf); X} X XCallNamedProcedure (self, procname) X struct view *self; X char *procname; X{ X char buf[1000]; X struct proctable_Entry *pe; X int stat; X X /* should lookup synonyms here... */ X X pe = proctable_Lookup (procname); X if (pe == NULL) X { X message_DisplayString (self, 0, "No such command."); X return; X } X X if (pe->proc != NULL X && (pe->module == NULL || (class_Load(pe->module) != NULL))) X { X if (pe->doc != NULL) X message_DisplayString (self, 0, pe->doc); X im_ForceUpdate(); X stat = (*pe->proc)(self, 0); X sprintf (buf, "%s returns %d.", pe->name, stat); X message_DisplayString (self, 0, buf); X }; X} X Xstatic void repeatProcedure (view, key) X struct view *view; X char key; X{ X char buf[1000]; X X if (*lastCommand != 0) X { X if (message_AskForString (view, 0 , "M-x ", lastCommand, X buf, sizeof(buf)) == -1) X { X message_DisplayString (view, 0, ""); X return; X } X X CallNamedProcedure (view, buf); X } X else X message_DisplayString (view, 0, "No previous Meta-X command."); X} X Xboolean metax__InitializeClass(classID) X struct classheader *classID; X{ X static struct bind_Description fns[] = { X {"view-call-named-procedure", "\033x", 0, NULL, 0, 0, callProcedure, "Call the procedure named as an argument", "metax" }, X {"view-repeat-named-procedure", "\030\033", 0, NULL, 0, 0, repeatProcedure, "Call the procedure named as an argument", "metax" }, X NULL }; X struct classinfo *viewClassinfo; X X viewClassinfo = class_Load("view"); X if (viewClassinfo != NULL) { X bind_BindList(fns, NULL, NULL, viewClassinfo); X return TRUE; X } X else X return FALSE; X} X END_OF_FILE if test 2947 -ne `wc -c <'metax.c'`; then echo shar: \"'metax.c'\" unpacked with wrong size! fi # end of 'metax.c' fi if test -f 'metax.ch' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'metax.ch'\" else echo shar: Extracting \"'metax.ch'\" \(717 characters\) sed "s/^X//" >'metax.ch' <<'END_OF_FILE' X/*| -*- Mode: C -*- X/*|------------------------------------------------------------ X/*| X/*| File: metax.ch X/*| Created: Thu Jun 7 19:06:27 1990 X/*| Author: Bill Janssen (janssen@holmes) X/*| $Locker$ X/*| X/*|------------------------------------------------------------ X/*| X/*| Description: X/*| X/*| Package declaration for meta-x code. X/*| X/*|------------------------------------------------------------ X/*| X/*| Copyright 1990 Xerox Corporation X/*| All Rights Reserved Worldwide. X/*|------------------------------------------------------------ X/*| X/*| "$Header$" X/*| X/*|------------------------------------------------------------ X/*/ X Xpackage metax { X X classprocedures: X InitializeClass() returns boolean; X}; END_OF_FILE if test 717 -ne `wc -c <'metax.ch'`; then echo shar: \"'metax.ch'\" unpacked with wrong size! fi # end of 'metax.ch' fi echo shar: End of shell archive. exit 0 ---- Enclosure ----
janssen@parc.xerox.com (Bill Janssen) (07/21/90)
Whoops. I notice the Imakefile defines LOCALINCLUDES. Just remove that line, it isn't needed. Bill
wjh+@ANDREW.CMU.EDU (Fred Hansen) (07/24/90)
The meta-X facility recently posted here will let you call any proctable function, but has some problems: There is no provision for passing an argument to the function. There is no completion of the name while typing it in. I can't offer a solution to the second problem, though someone could easily write a completion package that inspected that proctable. To pass arguments you can utilize Ness. I do this by adding to my .atkinit the line addkey ness-dostmt \e\e view Then when I type ESC-ESC (or meta-ESC, I suppose) it prompts for Ness statements. Any proctable function can be called and arguments passed. For instance, to classify a message into a folder (am operation I don't have in my messages menu) I can type ESC-ESC and give the command: messages_classify_by_name(currentinset, "foldername") Note that the dashes in the proctable names become underlines in Ness and that the first argument should be currentinset because that is expected by the proctable function. For more information see section 5 of /usr/andrew/doc/atk/ness/nessuser.doc. Have fun, Fred Hansen
rr2b+@ANDREW.CMU.EDU (Robert Andrew Ryan) (07/24/90)
I have a meta-x package which will be in the contrib dir for patch 7, if you don't want to wait, I'll post it in a few days to a week. This meta-x package features completion and argument passing, and even help in the style of the filename completion used by ez. -Rob Ryan Student Programmer, ITC Disclaimer: as evidenced by its placement in contrib the ITC makes no promises of support for this package.
guy@auspex.auspex.com (Guy Harris) (07/26/90)
> There is no provision for passing an argument to the function. > > There is no completion of the name while typing it in. > >I can't offer a solution to the second problem, though someone could >easily write a completion package that inspected that proctable. I looked at it sufficiently long to conclude that "easily" may not be the right word here; the whole completion stuff wasn't wonderfully-well documented and seemed a bit intricate. I'm sure it's doable; it just looked like more work than I was about to do. >To pass arguments you can utilize Ness. But can you pass arguments to a function in any EMACS by doing M-X? I tried it on both MicroEMACS and GNU EMACS (not the latest version) with functions that took arguments, and they prompted me for the argument, just as they would have had they been bound to keys. I assume they'd do the same with Bill's M-X package. >I do this by adding to my .atkinit the line > > addkey ness-dostmt \e\e view > >Then when I type ESC-ESC (or meta-ESC, I suppose) it prompts for Ness >statements. Any proctable function can be called and arguments passed. At least in Gosling EMACS, there is a "run a command" function, done with M-X, and an "evaluate Mlisp expression" function, done with something else. "ness-dostmt" seems more like the latter than the former. I don't see the inability to pass an argument to a function using M-X as a problem, for those reasons. It might be cleaner if proctable functions worked the way GNU EMACS functions worked; i.e., if the proctable entry included a spec for what arguments the function took, with M-X doing the prompting, rather than the code that implements the function doing so, and the arguments being passed to the function as, say, an array of unions or some such. This would centralize some of the user interaction, and shrink the code of some proctable functions; it would also, given code that could cope with the idea of a dialog box with more than one item, let Andrew prompt for a multi-argument function with a dialog box if the value of DialogPriority specified that the function in question should use a dialog box. Unfortunately, it could also require some rewriting of proctable function code. >For instance, to classify a message into a folder (am operation I don't >have in my messages menu) I can type ESC-ESC and give the command: > > messages_classify_by_name(currentinset, "foldername") > >Note that the dashes in the proctable names become underlines in Ness >and that the first argument should be currentinset because that is >expected by the proctable function. OK, I'll bite. Where's the code that prompts for a folder name if, say, you have "messages-classify-by-name" bound to a key or menu item, and you invoke it through a key sequence or menu item, rather than from Ness? The proctable function takes a "name" argument, but I didn't see any code in the function for "messages-classify-by-name" that does the prompting if there's a NULL argument, nor did I see anything in the proctable entry telling any common code to prompt for it. I must be missing something....
wjh+@ANDREW.CMU.EDU (Fred Hansen) (07/27/90)
Excerpts from internet.info-andrew: 26-Jul-90 Re: Meta-X package Guy Harris@uunet.uu.net (3111) > the whole completion stuff wasn't wonderfully-well > documented and seemed a bit intricate. Amen. > in Gosling EMACS, there is a "run a command" function, done > with M-X, and an "evaluate Mlisp expression" function, done with > something else. "ness-dostmt" seems more like the latter than the > former. This is precisely right. > OK, I'll bite. Where's the code that prompts for a folder name if, say, > you have "messages-classify-by-name" bound to a key or menu item, and > you invoke it through a key sequence or menu item, rather than from > Ness? I must admit I didn't check to see if messages-classify-by-name prompted for the folder name. Apparently this function is meant to be called with one of the messages-compound-... operations which permit calling functions and passing arguments in a fairly ad hoc and undocumented manner. Fred Hansen
janssen@parc.xerox.com (Bill Janssen) (07/27/90)
Excerpts from ext.andrew: 26-Jul-90 Re: Meta-X package Guy Harris@uunet.uu.net (3112) > >[A reply to Fred Hansen's posting about using ESC-ESC and Ness, turning > into a discussion about passing args to procs] The proc system in ATK is unfortunately designed to be called by a keystroke and/or menu item on some kind of view. The notion is that a single arg can be passed, through the Emacs standard of typing ^U argument before invoking the function (the function im_ProvideArg() can also be called to set the argument value). The function can then call im_Argument() to retrieve the argument, which is passed as a long. But in general, ATK procs are argument-less functions designed to be called by user actions, that often prompt for input from the user. This severely limits their usefulness in extension languages, such as Ness. GNU Emacs has a triple model: 1) Internal procedures are coded in C, and are meant to be called from C code. These correspond to module-private functions. 2) Elisp functions are coded in C or Elisp, and are meant to be called from the extension language (Elisp). These are more like the exported interface provided by the ATK .ch files. Almost all Emacs functionality is available through these, including many low-level primitives. 3) A special set of procedures, corresponding to ATK procs, are defined to be called by the user. These wrap a different interface around some set of the Elisp functions. A stylized approach to defining them ensures that they prompt for possible arguments, if such are defined. They may also be called from Elisp. This middle layer seems to be what ATK is missing. I think if one were to re-do such a project, having an extension language (Scheme sounds nice) in mind from the beginning, and implementing part of the application in the extension language, would be a good idea. Such a layer can be added after the fact, though. Ness almost does it right; it can call Class methods as well as procs. But is has to re-parse the .ch file each time the function is interpreted (I think), which makes for slow execution. I think the class compiler should do the parsing and leave the results in another .dox file, in a form that could be easily loaded by the extension language. Bill
nsb@THUMPER.BELLCORE.COM (Nathaniel Borenstein) (07/27/90)
Excerpts from internet.info-andrew: 26-Jul-90 Re: Meta-X package Fred Hansen@andrew.cmu.e (940+0) >> OK, I'll bite. Where's the code that prompts for a folder name if, say, >> you have "messages-classify-by-name" bound to a key or menu item, and >> you invoke it through a key sequence or menu item, rather than from >> Ness? > I must admit I didn't check to see if messages-classify-by-name prompted > for the folder name. Apparently this function is meant to be called > with one of the messages-compound-... operations which permit calling > functions and passing arguments in a fairly ad hoc and undocumented > manner. I think you're looking for the last 4 functions defined in atkams/messages/lib/ams.c. This is an example of using the completion package, in this case for folder name completion. In this case, it can't be made to take an argument, I believe. However, in general you can exploit the (undocumented) fact that when you call a proctable entry from an init file and do NOT pass an argument to it, the argument is NULL. Thus you can write a proctable entry that interacts with the user if & only if that parameter is NULL. For an example of a function that does this successfully, look in atkams/messages/lib/sendaux.c, at the code that implements the ^O function in the sending window. This is bound to the procedure UserWantsAHeader. If no arguments are passed, it will prompt the user for the header, otherwise it will use what is passed in.
wjh+@ANDREW.CMU.EDU (Fred Hansen) (07/29/90)
Excerpts from internet.info-andrew: 26-Jul-90 Re: Meta-X package Bill Janssen@parc.xerox. (2270+0) > This middle layer seems to be what ATK is missing. I think if one were > to re-do such a project, having an extension language (Scheme sounds > nice) in mind from the beginning, and implementing part of the > application in the extension language, would be a good idea. Such a layer can be added after the fact, though. Yes, much work is needed to make ATK really accessible from an extension language. Scheme sounds wonderful for hackers, but not so nice for mere mortals. > Ness almost does it right; it can call Class methods as well as procs. > But is has to re-parse the .ch file each time the function is > interpreted (I think), which makes for slow execution. I think the > class compiler should do the parsing and leave the results in another > .dox file, in a form that could be easily loaded by the extension > language. Not only can Ness functions call methods and class procedures, they can also access and set instance variables in objects. The .ch files are parsed only once, the first time they are needed. All subsequent Ness compilations in the same process reuse the .ch reparse already done. Ness compilation could indeed avoid this reparsing if .dox files were generated, though the class compiler does not do as thorough a job of parsing the declarations as does Ness. (Actually, Ness could use the .dog file directly, though then we would pay for loading it.) A problem with access to C from Ness is the mismatch in types. Not all C types and structures are implemented in Ness. Fred Hansen
ham@Neon.Stanford.EDU (Peter R. Ham) (07/29/90)
What's "Ness", I'm interested in extension languages. I've missed the beginning of this discussion. --