?: go back to numexpr
[nedit-bw.git] / define_macro.patch
blobc2c1330d7a3e96bee117744dbbc6878b4b478d86
1 Subject: define() macro
3 This lets you define a new function in runtime.
5 With the "override" option you can override preexisting macro functions, but
6 only macro functions, no action routines nor c functions.
8 ---
10 doc/help.etx | 5 ++
11 source/highlightData.c | 2 -
12 source/macro.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++++
13 source/parse.y | 2 -
14 4 files changed, 104 insertions(+), 2 deletions(-)
16 diff --quilt old/source/macro.c new/source/macro.c
17 --- old/source/macro.c
18 +++ new/source/macro.c
19 @@ -446,6 +446,9 @@ static int dictappendMS(WindowInfo *wind
20 static int dictiselementMS(WindowInfo *window, DataValue *argList, int nArgs,
21 DataValue *result, char **errMsg);
23 +static int defineMS(WindowInfo *window, DataValue *argList, int nArgs,
24 + DataValue *result, char **errMsg);
26 /* Built-in subroutines and variables for the macro language */
27 static const BuiltInSubrName MacroSubrs[] = {
28 { "args", argsMS },
29 @@ -514,6 +517,7 @@ static const BuiltInSubrName MacroSubrs[
30 { "dict_save", dictsaveMS },
31 { "dict_append", dictappendMS },
32 { "dict_is_element", dictiselementMS },
33 + { "define", defineMS },
34 { NULL, NULL } /* sentinel */
37 @@ -3681,6 +3685,99 @@ static int callMS(WindowInfo *window, Da
38 return OverlayRoutineFromSymbol(sym, nArgs, 1);
41 +/*
42 + * define(func_name, func_body[, "override"])
43 + */
44 +static int defineMS(WindowInfo *window, DataValue *argList, int nArgs,
45 + DataValue *result, char **errMsg)
47 + char stringStorage[3][TYPE_INT_STR_SIZE(int)];
48 + char *name = NULL;
49 + char *body = NULL;
50 + char *bodysave = NULL;
51 + char *stoppedAt = NULL;
52 + char *namePtr;
53 + char *override = NULL;
54 + Program *prog;
55 + Symbol *sym;
56 + DataValue subrPtr;
58 + if (nArgs < 2 || nArgs > 3) {
59 + return wrongNArgsErr(errMsg);
60 + }
61 + if (!readStringArg(argList[0], &name, stringStorage[0], errMsg)) {
62 + return False;
63 + }
64 + if (!readStringArg(argList[1], &body, stringStorage[1], errMsg)) {
65 + return False;
66 + }
67 + if (nArgs > 2) {
68 + if (!readStringArg(argList[2], &override, stringStorage[2], errMsg)) {
69 + return False;
70 + }
71 + if (strcmp(override, "override")) {
72 + *errMsg = "Unknown parameter for subroutine %s";
73 + return False;
74 + }
75 + }
77 + /* check function name */
78 + if (strlen(name) > MAX_SYM_LEN ||
79 + (!isalpha((unsigned char)name[0]) && !name[0] != '$')) {
80 + *errMsg = "subroutine name is not a valid identifier";
81 + return False;
82 + }
83 + namePtr = name + 1;
84 + while (isalnum((unsigned char)*namePtr) || *namePtr == '_')
85 + namePtr++;
86 + if (*namePtr) {
87 + *errMsg = "subroutine name is not a valid identifier";
88 + return False;
89 + }
91 + /* add a terminating newline */
92 + bodysave = XtMalloc(strlen(body) + 2);
93 + if (!bodysave) {
94 + *errMsg = "Internal error";
95 + return False;
96 + }
97 + strcpy(bodysave, body);
98 + strcat(bodysave, "\n");
100 + /* Parse the macro and report errors if it fails */
101 + prog = ParseMacro(bodysave, errMsg, &stoppedAt, False, name);
102 + if (!prog) {
103 + ParseError(window->macroCmdData ? window->shell : NULL,
104 + bodysave, stoppedAt, name, *errMsg);
105 + XtFree(bodysave);
106 + return False;
108 + XtFree(bodysave);
110 + sym = LookupSymbol(name);
111 + if (sym) {
112 + if (!override) {
113 + FreeProgram(prog);
114 + *errMsg = "Try to override existing function.";
115 + return False;
116 + } else {
117 + if (sym->type != MACRO_FUNCTION_SYM) {
118 + FreeProgram(prog);
119 + *errMsg = "Try to override a non macro function.";
120 + return False;
122 + FreeProgram(sym->value.val.prog);
123 + sym->value.val.prog = prog;
125 + } else {
126 + subrPtr.tag = NO_TAG;
127 + subrPtr.val.prog = prog;
128 + sym = InstallSymbol(name, MACRO_FUNCTION_SYM, subrPtr);
131 + return True;
134 /* T Balinski */
135 static int listDialogMS(WindowInfo *window, DataValue *argList, int nArgs,
136 DataValue *result, char **errMsg)
137 diff --quilt old/source/highlightData.c new/source/highlightData.c
138 --- old/source/highlightData.c
139 +++ new/source/highlightData.c
140 @@ -551,7 +551,7 @@ static char *DefaultPatternSets[] = {
141 Built-in Misc Vars:\"(?<!\\Y)\\$(?:active_pane|args|calltip_ID|column|cursor|display_width|empty_array|file_name|file_path|language_mode|line|locked|max_font_width|min_font_width|modified|n_display_lines|n_panes|rangeset_list|read_only|selection_(?:start|end|left|right)|server_name|text_length|top_line|transient|VERSION|NEDIT_HOME)>\":::Identifier::\n\
142 Built-in Pref Vars:\"(?<!\\Y)\\$(?:auto_indent|em_tab_dist|file_format|font_name|font_name_bold|font_name_bold_italic|font_name_italic|highlight_syntax|incremental_backup|incremental_search_line|make_backup_copy|match_syntax_based|overtype_mode|show_line_numbers|show_matching|statistics_line|tab_dist|use_tabs|wrap_margin|wrap_text)>\":::Identifier2::\n\
143 Built-in Special Vars:\"(?<!\\Y)\\$(?:[1-9]|list_dialog_button|n_args|read_status|search_end|shell_cmd_status|string_dialog_button|sub_sep)>\":::String1::\n\
144 - Built-in Subrs:\"<(?:args|append_file|beep|call|calltip|clipboard_to_string|dialog|filename_dialog|dict_(?:insert|complete|save|append|is_element)|focus_window|get_character|get_matching|get_pattern_(by_name|at_pos)|get_range|get_selection|get_style_(by_name|at_pos)|getenv|highlight_calltip_line|kill_calltip|length|list_dialog|max|min|n_args|rangeset_(?:add|create|destroy|get_by_name|includes|info|invert|range|set_color|set_mode|set_name|subtract)|read_file|replace_in_string|replace_range|replace_selection|replace_substring|search|search_string|select|select_rectangle|set_cursor_pos|set_transient|shell_command|split|string_compare|string_dialog|string_to_clipboard|substring|t_print|tolower|toupper|valid_number|write_file)(?=\\s*\\()\":::Subroutine::\n\
145 + Built-in Subrs:\"<(?:args|append_file|beep|call|calltip|clipboard_to_string|define|dialog|filename_dialog|dict_(?:insert|complete|save|append|is_element)|focus_window|get_character|get_matching|get_pattern_(by_name|at_pos)|get_range|get_selection|get_style_(by_name|at_pos)|getenv|highlight_calltip_line|kill_calltip|length|list_dialog|max|min|n_args|rangeset_(?:add|create|destroy|get_by_name|includes|info|invert|range|set_color|set_mode|set_name|subtract)|read_file|replace_in_string|replace_range|replace_selection|replace_substring|search|search_string|select|select_rectangle|set_cursor_pos|set_transient|shell_command|split|string_compare|string_dialog|string_to_clipboard|substring|t_print|tolower|toupper|valid_number|write_file)(?=\\s*\\()\":::Subroutine::\n\
146 Menu Actions:\"<(?:new(?:_tab|_opposite)?|open|open-dialog|open_dialog|open-selected|open_selected|close|save|save-as|save_as|save-as-dialog|save_as_dialog|revert-to-saved|revert_to_saved|revert_to_saved_dialog|include-file|include_file|include-file-dialog|include_file_dialog|load-macro-file|load_macro_file|load-macro-file-dialog|load_macro_file_dialog|load-tags-file|load_tags_file|load-tags-file-dialog|load_tags_file_dialog|unload_tags_file|load_tips_file|load_tips_file_dialog|unload_tips_file|print|print-selection|print_selection|exit|undo|redo|delete|select-all|select_all|shift-left|shift_left|shift-left-by-tab|shift_left_by_tab|shift-right|shift_right|shift-right-by-tab|shift_right_by_tab|find|find-dialog|find_dialog|find-again|find_again|find-selection|find_selection|find_incremental|start_incremental_find|replace|replace-dialog|replace_dialog|replace-all|replace_all|replace-in-selection|replace_in_selection|replace-again|replace_again|replace_find|replace_find_same|replace_find_again|goto-line-number|goto_line_number|goto-line-number-dialog|goto_line_number_dialog|goto-selected|goto_selected|mark|mark-dialog|mark_dialog|goto-mark|goto_mark|goto-mark-dialog|goto_mark_dialog|match|select_to_matching|goto_matching|find-definition|find_definition|show_tip|split-pane|split_pane|close-pane|close_pane|detach_document(?:_dialog)?|move_document_dialog|(?:next|previous|last)_document|uppercase|lowercase|fill-paragraph|fill_paragraph|control-code-dialog|control_code_dialog|filter-selection-dialog|filter_selection_dialog|filter-selection|filter_selection|execute-command|execute_command|execute-command-dialog|execute_command_dialog|execute-command-line|execute_command_line|shell-menu-command|shell_menu_command|macro-menu-command|macro_menu_command|bg_menu_command|post_window_bg_menu|post_tab_context_menu|beginning-of-selection|beginning_of_selection|end-of-selection|end_of_selection|repeat_macro|repeat_dialog|raise_window|focus_pane|set_statistics_line|set_incremental_search_line|set_show_line_numbers|set_auto_indent|set_wrap_text|set_wrap_margin|set_highlight_syntax|set_make_backup_copy|set_incremental_backup|set_show_matching|set_match_syntax_based|set_overtype_mode|set_locked|set_tab_dist|set_em_tab_dist|set_use_tabs|set_fonts|set_language_mode)(?=\\s*\\()\":::Subroutine::\n\
147 Text Actions:\"<(?:self-insert|self_insert|grab-focus|grab_focus|extend-adjust|extend_adjust|extend-start|extend_start|extend-end|extend_end|secondary-adjust|secondary_adjust|secondary-or-drag-adjust|secondary_or_drag_adjust|secondary-start|secondary_start|secondary-or-drag-start|secondary_or_drag_start|process-bdrag|process_bdrag|move-destination|move_destination|move-to|move_to|move-to-or-end-drag|move_to_or_end_drag|end_drag|copy-to|copy_to|copy-to-or-end-drag|copy_to_or_end_drag|exchange|process-cancel|process_cancel|paste-clipboard|paste_clipboard|copy-clipboard|copy_clipboard|cut-clipboard|cut_clipboard|copy-primary|copy_primary|cut-primary|cut_primary|newline|newline-and-indent|newline_and_indent|newline-no-indent|newline_no_indent|delete-selection|delete_selection|delete-previous-character|delete_previous_character|delete-next-character|delete_next_character|delete-previous-word|delete_previous_word|delete-next-word|delete_next_word|delete-to-start-of-line|delete_to_start_of_line|delete-to-end-of-line|delete_to_end_of_line|forward-character|forward_character|backward-character|backward_character|key-select|key_select|process-up|process_up|process-down|process_down|process-shift-up|process_shift_up|process-shift-down|process_shift_down|process-home|process_home|forward-word|forward_word|backward-word|backward_word|forward-paragraph|forward_paragraph|backward-paragraph|backward_paragraph|beginning-of-line|beginning_of_line|end-of-line|end_of_line|beginning-of-file|beginning_of_file|end-of-file|end_of_file|next-page|next_page|previous-page|previous_page|page-left|page_left|page-right|page_right|toggle-overstrike|toggle_overstrike|scroll-up|scroll_up|scroll-down|scroll_down|scroll_left|scroll_right|scroll-to-line|scroll_to_line|select-all|select_all|deselect-all|deselect_all|focusIn|focusOut|process-return|process_return|process-tab|process_tab|insert-string|insert_string|mouse_pan)(?=\\s*\\()\":::Subroutine::\n\
148 Macro Hooks:\"<(?:(?:pre|post)_(?:open|save)|cursor_moved|modified|(?:losing_)?focus)_hook(?=\\s*\\()\":::Subroutine1::\n\
149 diff --quilt old/doc/help.etx new/doc/help.etx
150 --- old/doc/help.etx
151 +++ new/doc/help.etx
152 @@ -2689,6 +2689,11 @@ Macro Subroutines
153 Returns the contents of the clipboard as a macro string. Returns empty
154 string on error.
156 +**define( name, body [, "override"] )**
157 + Defines a new function with name ~name~ and the macro code in ~body~.
158 + If the ~"override"~ option is given the new symbol overrides previously
159 + defined functions.
161 **dialog( message, btn_1_label, btn_2_label, ... )**
162 Pop up a dialog for querying and presenting information to the user. First
163 argument is a string to show in the message area of the dialog.
164 diff --quilt old/source/parse.y new/source/parse.y
165 --- old/source/parse.y
166 +++ new/source/parse.y
167 @@ -951,7 +951,7 @@ static int yylex(void)
168 if (!strcmp(symName, "in")) return IN;
169 if (!strcmp(symName, "$args")) return ARG_LOOKUP;
170 if (!strcmp(symName, "delete") && follow_non_whitespace('(', SYMBOL, DELETE) == DELETE) return DELETE;
171 - if (!strcmp(symName, "define")) return DEFINE;
172 + if (!strcmp(symName, "define") && follow_non_whitespace('(', SYMBOL, DEFINE) == DEFINE) return DEFINE;
173 if (!strcmp(symName, "typeof")) return TYPEOF;
174 if (nextSymIsField) {
175 nextSymIsField = 0;