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.
11 source/highlightData.c | 2 -
12 source/macro.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++++
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 @@ -440,10 +440,13 @@ static int dictsaveMS(WindowInfo *window
20 static int dictappendMS(WindowInfo *window, DataValue *argList, int nArgs,
21 DataValue *result, char **errMsg);
22 static int dictiselementMS(WindowInfo *window, DataValue *argList, int nArgs,
23 DataValue *result, char **errMsg);
25 +static int defineMS(WindowInfo *window, DataValue *argList, int nArgs,
26 + DataValue *result, char **errMsg);
28 /* Built-in subroutines and variables for the macro language */
29 static const BuiltInSubrName MacroSubrs[] = {
30 { "length", lengthMS },
31 { "get_range", getRangeMS },
32 { "t_print", tPrintMS },
33 @@ -506,10 +509,11 @@ static const BuiltInSubrName MacroSubrs[
34 { "dict_insert", dictinsertMS },
35 { "dict_complete", dictcompleteMS },
36 { "dict_save", dictsaveMS },
37 { "dict_append", dictappendMS },
38 { "dict_is_element", dictiselementMS },
39 + { "define", defineMS },
40 { NULL, NULL } /* sentinel */
43 static const BuiltInSubrName SpecialVars[] = {
44 { "$cursor", cursorMV },
45 @@ -3606,10 +3610,103 @@ static int callMS(WindowInfo *window, Da
48 return OverlayRoutineFromSymbol(sym, nArgs, 1);
52 + * define(func_name, func_body[, "override"])
54 +static int defineMS(WindowInfo *window, DataValue *argList, int nArgs,
55 + DataValue *result, char **errMsg)
57 + char stringStorage[3][TYPE_INT_STR_SIZE(int)];
60 + char *bodysave = NULL;
61 + char *stoppedAt = NULL;
63 + char *override = NULL;
68 + if (nArgs < 2 || nArgs > 3) {
69 + return wrongNArgsErr(errMsg);
71 + if (!readStringArg(argList[0], &name, stringStorage[0], errMsg)) {
74 + if (!readStringArg(argList[1], &body, stringStorage[1], errMsg)) {
78 + if (!readStringArg(argList[2], &override, stringStorage[2], errMsg)) {
81 + if (strcmp(override, "override")) {
82 + *errMsg = "Unknown parameter for subroutine %s";
87 + /* check function name */
88 + if (strlen(name) > MAX_SYM_LEN ||
89 + (!isalpha((unsigned char)name[0]) && !name[0] != '$')) {
90 + *errMsg = "subroutine name is not a valid identifier";
94 + while (isalnum((unsigned char)*namePtr) || *namePtr == '_')
97 + *errMsg = "subroutine name is not a valid identifier";
101 + /* add a terminating newline */
102 + bodysave = XtMalloc(strlen(body) + 2);
104 + *errMsg = "Internal error";
107 + strcpy(bodysave, body);
108 + strcat(bodysave, "\n");
110 + /* Parse the macro and report errors if it fails */
111 + prog = ParseMacro(bodysave, errMsg, &stoppedAt, False, name);
113 + ParseError(window->macroCmdData ? window->shell : NULL,
114 + bodysave, stoppedAt, name, *errMsg);
120 + sym = LookupSymbol(name);
124 + *errMsg = "Try to override existing function.";
127 + if (sym->type != MACRO_FUNCTION_SYM) {
129 + *errMsg = "Try to override a non macro function.";
132 + FreeProgram(sym->value.val.prog);
133 + sym->value.val.prog = prog;
136 + subrPtr.tag = NO_TAG;
137 + subrPtr.val.prog = prog;
138 + sym = InstallSymbol(name, MACRO_FUNCTION_SYM, subrPtr);
145 static int listDialogMS(WindowInfo *window, DataValue *argList, int nArgs,
146 DataValue *result, char **errMsg)
148 macroCmdInfo *cmdData;
149 diff --quilt old/source/highlightData.c new/source/highlightData.c
150 --- old/source/highlightData.c
151 +++ new/source/highlightData.c
152 @@ -549,11 +549,11 @@ static char *DefaultPatternSets[] = {
153 README:\"NEdit Macro syntax highlighting patterns, version 2.6, maintainer Thorsten Haude, nedit at thorstenhau.de\":::Flag::D\n\
154 Comment:\"#\":\"$\"::Comment::\n\
155 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\
156 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\
157 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\
158 - Built-in Subrs:\"<(?: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|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\
159 + Built-in Subrs:\"<(?: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|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\
160 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\
161 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\
162 Macro Hooks:\"<(?:(?:pre|post)_(?:open|save)|cursor_moved|modified|(?:losing_)?focus)_hook(?=\\s*\\()\":::Subroutine1::\n\
163 Keyword:\"<(?:break|continue|define|delete|else|for|if|in|return|typeof|while)>\":::Keyword::\n\
164 Braces:\"[{}\\[\\]]\":::Keyword::\n\
165 diff --quilt old/doc/help.etx new/doc/help.etx
168 @@ -2688,10 +2688,15 @@ Macro Subroutines
170 **clipboard_to_string()**
171 Returns the contents of the clipboard as a macro string. Returns empty
174 +**define( name, body [, "override"] )**
175 + Defines a new function with name ~name~ and the macro code in ~body~.
176 + If the ~"override"~ option is given the new symbol overrides previously
179 **dialog( message, btn_1_label, btn_2_label, ... )**
180 Pop up a dialog for querying and presenting information to the user. First
181 argument is a string to show in the message area of the dialog.
182 Additional optional arguments represent labels for buttons to appear along
183 the bottom of the dialog. Returns the number of the button pressed (the
184 diff --quilt old/source/parse.y new/source/parse.y
185 --- old/source/parse.y
186 +++ new/source/parse.y
187 @@ -875,11 +875,11 @@ static int yylex(void)
188 if (!strcmp(symName, "continue")) return CONTINUE;
189 if (!strcmp(symName, "return")) return RETURN;
190 if (!strcmp(symName, "in")) return IN;
191 if (!strcmp(symName, "$args")) return ARG_LOOKUP;
192 if (!strcmp(symName, "delete") && follow_non_whitespace('(', SYMBOL, DELETE) == DELETE) return DELETE;
193 - if (!strcmp(symName, "define")) return DEFINE;
194 + if (!strcmp(symName, "define") && follow_non_whitespace('(', SYMBOL, DEFINE) == DEFINE) return DEFINE;
195 if (!strcmp(symName, "typeof")) return TYPEOF;
196 if (nextSymIsField) {
198 yylval.sym = InstallStringConstSymbol(symName);