diff options
| author | Philipp Stephani | 2020-09-13 20:21:41 +0200 |
|---|---|---|
| committer | Philipp Stephani | 2020-09-13 20:26:47 +0200 |
| commit | da0e75e7410226d7fd6d760f0ebe8a04d815506d (patch) | |
| tree | 1c850a5c13e3af18b7ca8cfe1b785d51300d9dde /src | |
| parent | 3eb4e0db5ce247f8396daac3156087fbb7aefbd4 (diff) | |
| download | emacs-da0e75e7410226d7fd6d760f0ebe8a04d815506d.tar.gz emacs-da0e75e7410226d7fd6d760f0ebe8a04d815506d.zip | |
Add facility to make module functions interactive (Bug#23486).
* src/module-env-28.h: Add field for 'make_interactive' function.
* src/emacs-module.c (Lisp_Module_Function): Add new field holding the
interactive form.
(allocate_module_function): Adapt to structure layout change.
(module_make_interactive, module_function_interactive_form): New
functions.
(initialize_environment): Use them.
* src/eval.c (Fcommandp):
* src/data.c (Finteractive_form): Also handle interactive module
functions.
* test/data/emacs-module/mod-test.c (Fmod_test_identity): New test
function.
(emacs_module_init): Create two interactive module test functions.
* test/src/emacs-module-tests.el (module/interactive/return-t)
(module/interactive/return-t-int, module/interactive/identity):
New unit tests.
* doc/lispref/internals.texi (Module Functions): Document new
function. Rework paragraph about wrapping module functions, as the
example no longer applies.
* etc/NEWS: Document new facility.
Diffstat (limited to 'src')
| -rw-r--r-- | src/data.c | 7 | ||||
| -rw-r--r-- | src/emacs-module.c | 23 | ||||
| -rw-r--r-- | src/eval.c | 7 | ||||
| -rw-r--r-- | src/lisp.h | 2 | ||||
| -rw-r--r-- | src/module-env-28.h | 4 |
5 files changed, 41 insertions, 2 deletions
diff --git a/src/data.c b/src/data.c index 59d148166fe..dae8b10ef55 100644 --- a/src/data.c +++ b/src/data.c | |||
| @@ -906,6 +906,13 @@ Value, if non-nil, is a list (interactive SPEC). */) | |||
| 906 | if (PVSIZE (fun) > COMPILED_INTERACTIVE) | 906 | if (PVSIZE (fun) > COMPILED_INTERACTIVE) |
| 907 | return list2 (Qinteractive, AREF (fun, COMPILED_INTERACTIVE)); | 907 | return list2 (Qinteractive, AREF (fun, COMPILED_INTERACTIVE)); |
| 908 | } | 908 | } |
| 909 | else if (MODULE_FUNCTIONP (fun)) | ||
| 910 | { | ||
| 911 | Lisp_Object form | ||
| 912 | = module_function_interactive_form (XMODULE_FUNCTION (fun)); | ||
| 913 | if (! NILP (form)) | ||
| 914 | return form; | ||
| 915 | } | ||
| 909 | else if (AUTOLOADP (fun)) | 916 | else if (AUTOLOADP (fun)) |
| 910 | return Finteractive_form (Fautoload_do_load (fun, cmd, Qnil)); | 917 | return Finteractive_form (Fautoload_do_load (fun, cmd, Qnil)); |
| 911 | else if (CONSP (fun)) | 918 | else if (CONSP (fun)) |
diff --git a/src/emacs-module.c b/src/emacs-module.c index a0bab118019..3581daad112 100644 --- a/src/emacs-module.c +++ b/src/emacs-module.c | |||
| @@ -551,7 +551,7 @@ struct Lisp_Module_Function | |||
| 551 | union vectorlike_header header; | 551 | union vectorlike_header header; |
| 552 | 552 | ||
| 553 | /* Fields traced by GC; these must come first. */ | 553 | /* Fields traced by GC; these must come first. */ |
| 554 | Lisp_Object documentation; | 554 | Lisp_Object documentation, interactive_form; |
| 555 | 555 | ||
| 556 | /* Fields ignored by GC. */ | 556 | /* Fields ignored by GC. */ |
| 557 | ptrdiff_t min_arity, max_arity; | 557 | ptrdiff_t min_arity, max_arity; |
| @@ -564,7 +564,7 @@ static struct Lisp_Module_Function * | |||
| 564 | allocate_module_function (void) | 564 | allocate_module_function (void) |
| 565 | { | 565 | { |
| 566 | return ALLOCATE_PSEUDOVECTOR (struct Lisp_Module_Function, | 566 | return ALLOCATE_PSEUDOVECTOR (struct Lisp_Module_Function, |
| 567 | documentation, PVEC_MODULE_FUNCTION); | 567 | interactive_form, PVEC_MODULE_FUNCTION); |
| 568 | } | 568 | } |
| 569 | 569 | ||
| 570 | #define XSET_MODULE_FUNCTION(var, ptr) \ | 570 | #define XSET_MODULE_FUNCTION(var, ptr) \ |
| @@ -630,6 +630,24 @@ module_finalize_function (const struct Lisp_Module_Function *func) | |||
| 630 | func->finalizer (func->data); | 630 | func->finalizer (func->data); |
| 631 | } | 631 | } |
| 632 | 632 | ||
| 633 | static void | ||
| 634 | module_make_interactive (emacs_env *env, emacs_value function, emacs_value spec) | ||
| 635 | { | ||
| 636 | MODULE_FUNCTION_BEGIN (); | ||
| 637 | Lisp_Object lisp_fun = value_to_lisp (function); | ||
| 638 | CHECK_MODULE_FUNCTION (lisp_fun); | ||
| 639 | Lisp_Object lisp_spec = value_to_lisp (spec); | ||
| 640 | /* Normalize (interactive nil) to (interactive). */ | ||
| 641 | XMODULE_FUNCTION (lisp_fun)->interactive_form | ||
| 642 | = NILP (lisp_spec) ? list1 (Qinteractive) : list2 (Qinteractive, lisp_spec); | ||
| 643 | } | ||
| 644 | |||
| 645 | Lisp_Object | ||
| 646 | module_function_interactive_form (const struct Lisp_Module_Function *fun) | ||
| 647 | { | ||
| 648 | return fun->interactive_form; | ||
| 649 | } | ||
| 650 | |||
| 633 | static emacs_value | 651 | static emacs_value |
| 634 | module_funcall (emacs_env *env, emacs_value func, ptrdiff_t nargs, | 652 | module_funcall (emacs_env *env, emacs_value func, ptrdiff_t nargs, |
| 635 | emacs_value *args) | 653 | emacs_value *args) |
| @@ -1463,6 +1481,7 @@ initialize_environment (emacs_env *env, struct emacs_env_private *priv) | |||
| 1463 | env->get_function_finalizer = module_get_function_finalizer; | 1481 | env->get_function_finalizer = module_get_function_finalizer; |
| 1464 | env->set_function_finalizer = module_set_function_finalizer; | 1482 | env->set_function_finalizer = module_set_function_finalizer; |
| 1465 | env->open_channel = module_open_channel; | 1483 | env->open_channel = module_open_channel; |
| 1484 | env->make_interactive = module_make_interactive; | ||
| 1466 | Vmodule_environments = Fcons (make_mint_ptr (env), Vmodule_environments); | 1485 | Vmodule_environments = Fcons (make_mint_ptr (env), Vmodule_environments); |
| 1467 | return env; | 1486 | return env; |
| 1468 | } | 1487 | } |
diff --git a/src/eval.c b/src/eval.c index 126ee2e9555..fdc3cd1e9f4 100644 --- a/src/eval.c +++ b/src/eval.c | |||
| @@ -1948,6 +1948,13 @@ then strings and vectors are not accepted. */) | |||
| 1948 | else if (COMPILEDP (fun)) | 1948 | else if (COMPILEDP (fun)) |
| 1949 | return (PVSIZE (fun) > COMPILED_INTERACTIVE ? Qt : if_prop); | 1949 | return (PVSIZE (fun) > COMPILED_INTERACTIVE ? Qt : if_prop); |
| 1950 | 1950 | ||
| 1951 | /* Module functions are interactive if their `interactive_form' | ||
| 1952 | field is non-nil. */ | ||
| 1953 | else if (MODULE_FUNCTIONP (fun)) | ||
| 1954 | return NILP (module_function_interactive_form (XMODULE_FUNCTION (fun))) | ||
| 1955 | ? if_prop | ||
| 1956 | : Qt; | ||
| 1957 | |||
| 1951 | /* Strings and vectors are keyboard macros. */ | 1958 | /* Strings and vectors are keyboard macros. */ |
| 1952 | if (STRINGP (fun) || VECTORP (fun)) | 1959 | if (STRINGP (fun) || VECTORP (fun)) |
| 1953 | return (NILP (for_call_interactively) ? Qt : Qnil); | 1960 | return (NILP (for_call_interactively) ? Qt : Qnil); |
diff --git a/src/lisp.h b/src/lisp.h index 88e69b9061d..a24898004d4 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -4210,6 +4210,8 @@ extern Lisp_Object funcall_module (Lisp_Object, ptrdiff_t, Lisp_Object *); | |||
| 4210 | extern Lisp_Object module_function_arity (const struct Lisp_Module_Function *); | 4210 | extern Lisp_Object module_function_arity (const struct Lisp_Module_Function *); |
| 4211 | extern Lisp_Object module_function_documentation | 4211 | extern Lisp_Object module_function_documentation |
| 4212 | (struct Lisp_Module_Function const *); | 4212 | (struct Lisp_Module_Function const *); |
| 4213 | extern Lisp_Object module_function_interactive_form | ||
| 4214 | (const struct Lisp_Module_Function *); | ||
| 4213 | extern module_funcptr module_function_address | 4215 | extern module_funcptr module_function_address |
| 4214 | (struct Lisp_Module_Function const *); | 4216 | (struct Lisp_Module_Function const *); |
| 4215 | extern void *module_function_data (const struct Lisp_Module_Function *); | 4217 | extern void *module_function_data (const struct Lisp_Module_Function *); |
diff --git a/src/module-env-28.h b/src/module-env-28.h index 5d884c148c4..40b03b92b52 100644 --- a/src/module-env-28.h +++ b/src/module-env-28.h | |||
| @@ -12,3 +12,7 @@ | |||
| 12 | 12 | ||
| 13 | int (*open_channel) (emacs_env *env, emacs_value pipe_process) | 13 | int (*open_channel) (emacs_env *env, emacs_value pipe_process) |
| 14 | EMACS_ATTRIBUTE_NONNULL (1); | 14 | EMACS_ATTRIBUTE_NONNULL (1); |
| 15 | |||
| 16 | void (*make_interactive) (emacs_env *env, emacs_value function, | ||
| 17 | emacs_value spec) | ||
| 18 | EMACS_ATTRIBUTE_NONNULL (1); | ||