diff --git a/src/ewg/ewg.e b/src/ewg/ewg.e index f0fc6fe..daa53d9 100644 --- a/src/ewg/ewg.e +++ b/src/ewg/ewg.e @@ -12,7 +12,7 @@ note class EWG inherit - EWG_KERNAL + EWG_KERNEL redefine make, process_arguments @@ -114,13 +114,14 @@ feature -- Basic Operations -- Process arguments (using the obsolete syntax) local header_file_name: STRING - l_path: PATH do - if match_long_option ("output-dir") then - if is_next_option_long_option and then has_next_option_value then - output_directory_name := next_option_value - consume_option - end + if + match_long_option ("output-dir") and then + is_next_option_long_option and then + has_next_option_value + then + output_directory_name := next_option_value + consume_option end if not match_long_option ("full-header") then @@ -150,9 +151,7 @@ feature -- Basic Operations consume_option end - create l_path.make_from_string (header_file_name) - header_file_name := l_path.entry.out - + header_file_name := (create {PATH}.make_from_string (header_file_name)).entry.out if match_long_option ("config") then if is_next_option_long_option and then has_next_option_value then diff --git a/src/ewg/ewg_command_line_parser.e b/src/ewg/ewg_command_line_parser.e index eb5d194..e9dca49 100644 --- a/src/ewg/ewg_command_line_parser.e +++ b/src/ewg/ewg_command_line_parser.e @@ -46,6 +46,37 @@ feature -- Operations feature -- Status report + has_long_option (an_option_name: STRING): BOOLEAN + -- Is there a long option on the command-line whose name is + -- `an_option_name' (note that `an_option_name' does not + -- contain the leading '--' characters)? + require + an_option_name_not_void: an_option_name /= Void + local + i: INTEGER + arg: STRING + nb: INTEGER + do + from + i := 1 + until + (i > Arguments.argument_count) or Result + loop + arg := Arguments.argument (i) + nb := an_option_name.count + 2 + if + arg.count >= nb and then + (arg.item (1) = '-' and + arg.item (2) = '-') and then + STRING_.same_string (arg.substring (3, nb), an_option_name) + then + Result := arg.count = nb or else arg.item (nb + 1) = '=' + end + + i := i + 1 + end + end + has_next_option: BOOLEAN -- Is there an unconsumed token left? do @@ -75,7 +106,7 @@ feature -- Status report do arg := next_option i := arg.index_of ('=', 1) - Result := (i >= 1 and i < arg.count) + Result := i >= 1 and i < arg.count end feature -- Access @@ -96,12 +127,10 @@ feature -- Access next_option_is_long_option: is_next_option_long_option has_next_option_value: has_next_option_value local - i: INTEGER arg: STRING do arg := next_option - i := arg.index_of ('=', 1) - Result := arg.substring (i + 1, arg.count) + Result := arg.substring (arg.index_of ('=', 1) + 1, arg.count) ensure next_option_value_not_void: Result /= Void end @@ -128,7 +157,7 @@ feature -- Matching arg.item (2) = '-') and then STRING_.same_string (arg.substring (3, nb), an_option_name) then - Result := (arg.count = nb or else arg.item (nb + 1) = '=') + Result := arg.count = nb or else arg.item (nb + 1) = '=' end end end @@ -141,40 +170,7 @@ feature {NONE} -- Implementation is_valid_option_position (i: INTEGER): BOOLEAN -- Is `i' a valid token position? do - Result := (i >= 1 and i <= Arguments.argument_count) - end - -feature -- Status report - - has_long_option (an_option_name: STRING): BOOLEAN - -- Is there a long option on the command-line whose name is - -- `an_option_name' (note that `an_option_name' does not - -- contain the leading '--' characters)? - require - an_option_name_not_void: an_option_name /= Void - local - i: INTEGER - arg: STRING - nb: INTEGER - do - from - i := 1 - until - (i > Arguments.argument_count) or Result - loop - arg := Arguments.argument (i) - nb := an_option_name.count + 2 - if - arg.count >= nb and then - (arg.item (1) = '-' and - arg.item (2) = '-') and then - STRING_.same_string (arg.substring (3, nb), an_option_name) - then - Result := (arg.count = nb or else arg.item (nb + 1) = '=') - end - - i := i + 1 - end + Result := i >= 1 and i <= Arguments.argument_count end end diff --git a/src/ewg/ewg_kernal.e b/src/ewg/ewg_kernel.e similarity index 97% rename from src/ewg/ewg_kernal.e rename to src/ewg/ewg_kernel.e index 90951ec..b1e8490 100644 --- a/src/ewg/ewg_kernal.e +++ b/src/ewg/ewg_kernel.e @@ -22,7 +22,7 @@ note deferred class - EWG_KERNAL + EWG_KERNEL inherit ANY @@ -67,7 +67,6 @@ feature -- Basic Ops: Primary file: KL_TEXT_INPUT_FILE rule: EWG_CONFIG_RULE matching_clause: EWG_CONFIG_MATCHING_CLAUSE - wrapper_clause: EWG_CONFIG_DEFAULT_WRAPPER_CLAUSE do if config_file_name /= Void then create parser.make (error_handler) @@ -82,8 +81,7 @@ feature -- Basic Ops: Primary end else create matching_clause.make - create wrapper_clause.make - create rule.make (matching_clause, wrapper_clause) + create rule.make (matching_clause, create {EWG_CONFIG_DEFAULT_WRAPPER_CLAUSE}.make) config_system.append_rule (rule) end if error_handler.has_error then @@ -310,7 +308,7 @@ feature -- Basic Ops: Sub-supporting error_handler.report_info_message (l_cmd) -- To be updated. l_index := l_result.error_output.index_of ('.', 1) - 1 - l_name := l_result.error_output.substring (1, l_index) + l_name := l_result.error_output.to_string_8.substring (1, l_index) l_name.append_string ("_cpp.h") cpp_header_file_name := l_name.twin create l_file.make_create_read_write (l_name) @@ -376,7 +374,7 @@ feature -- Execute Plugin scripts report_info_message ("[Execute pre process script]") else -- Error - report_info_message (l_result.error_output) + report_info_message (l_result.error_output.to_string_8) end else report_info_message ("Script not found " + l_script ) @@ -394,7 +392,7 @@ feature -- Execute Plugin scripts report_info_message ("[Execute post process script]") else -- Error - report_info_message (l_result.error_output) + report_info_message (l_result.error_output.to_string_8) end else report_info_message ("Script not found " + l_script ) diff --git a/wrapcui/Readme.md b/wrapcui/Readme.md index 14ccd02..3394027 100644 --- a/wrapcui/Readme.md +++ b/wrapcui/Readme.md @@ -1,4 +1,142 @@ -WrapcUI +# WrapcUI -This code depends on URI launcher a library that you will need to download at https://svn.eiffel.com/eiffelstudio/trunk/Src -To use this tool set the environment variable %EIFFEL_SRC% to the directory where you checkout the code. +## Note +> This code depends on URI launcher, a library you will need to download at https://svn.eiffel.com/eiffelstudio/trunk/Src. +> To use this tool, ensure you have set the environment variable %EIFFEL_SRC% to the directory where you have checked out the code. + +## Compiling + +The WrapC UI project consists of two targets: `wrapcui` and `test`. The `wrapcui` is the production target, where you will finalize an executable. The `test` target is dedicated to writing and executing tests against the production target code. Presently, there is but one test, which was used to prove the code that parses the wrapcui configuration "Save" file, which is just XML. + +To create a finalized executable, open the `wrapcui` target and compile (or clean compile if needed). With a successful compile, Ctrl-Shift-F7 or select `Finalize` from the `Project` menu option. The executable will be produced in the `F_code` folder under your EIFGENs folder in the project folder. Move the executable to a folder of your choice and ensure you have set a proper PATH to it for later. + +### Execution in Workbench + +If you run WrapCUI in EiffelStudio's Workbench mode, you may find that you encounter an error where the code is not creating the target output directory structure. This is a known limitation (bug perhaps). The code works in the finalized executable. + +## Using + +The UI code literally wraps the EWG code, which is the basis of the WrapC CLI project and executable. Therefore, the UI controls mimick the CLI options. When WrapCUI first opens, each of the text fields are blank (empty). From here, you have two choices. + +* Manually set each option as needed by your project. +* Open options previously set and saved as an XML-based WrapCUI configuration file (named whatever you like, with whatever extension you like). + +### Manual Option Setting + +Before setting options for full-header and output-dir, you will need to: + +* Download your target C project, which will have your target header (*.h) file. +* Create your target output directory. + +#### Full Header Option + +Manaully type the full or relative path (relative to your current directory) to your target header file. + +Alternatively, use the `...` button to set the full path using the file-open dialog that appears. + +#### Output Directory Option + +Manually type the full or relative path to your target output directory. + +Alternatively, use the `...` button to set the full path using the directory dialog that appears. + +#### C-compiler Options + +Manually enter any C compiler options as needed. + +#### Pre-process Script + +Manually enter the full or relative path to a pre-process script, as needed. + +#### Post-process Script + +Manually enter the full or relative path to a post-process script, as needed. + +#### Config XML File + +Manually type the full or relative path to a config.xml (or other name) file, as needed. + +Alternatively, use the `...` button to set the full path to a config.xml file using the file-open dialog that appears. + +## Next Steps + +Once all of the options are set, you have several steps available to you. + +* `Save` the configuration in an XML file. Do this if you desire to quickly and easily reload the configuration you've just created. +* `Clean` the output directory (delete all files and folders in it) +* `Run` WrapC with the configuration you have set up or loaded (`File->Open`) + +#### Note on Cleaning + +There is a bug in EWG we have not found yet where once you click `Run`, the code does not release its file handles. Attempting to run `Clean` after a `Run` will generate an error and the files and folders will not be deleted. In order to successfully `Clean`, you will need to ensure the configuration is `Save`d, close WrapCUI, re-open WrapCUI, `Open` the saved configuration, and then `Clean` it. +# WrapcUI + +## Note +> This code depends on URI launcher, a library you will need to download at https://svn.eiffel.com/eiffelstudio/trunk/Src. +> To use this tool, ensure you have set the environment variable %EIFFEL_SRC% to the directory where you have checked out the code. + +## Compiling + +The WrapC UI project consists of two targets: `wrapcui` and `test`. The `wrapcui` is the production target, where you will finalize an executable. The `test` target is dedicated to writing and executing tests against the production target code. Presently, there is but one test, which was used to prove the code that parses the wrapcui configuration "Save" file, which is just XML. + +To create a finalized executable, open the `wrapcui` target and compile (or clean compile if needed). With a successful compile, Ctrl-Shift-F7 or select `Finalize` from the `Project` menu option. The executable will be produced in the `F_code` folder under your EIFGENs folder in the project folder. Move the executable to a folder of your choice and ensure you have set a proper PATH to it for later. + +### Execution in Workbench + +If you run WrapCUI in EiffelStudio's Workbench mode, you may find that you encounter an error where the code is not creating the target output directory structure. This is a known limitation (bug perhaps). The code works in the finalized executable. + +## Using + +The UI code literally wraps the EWG code, which is the basis of the WrapC CLI project and executable. Therefore, the UI controls mimick the CLI options. When WrapCUI first opens, each of the text fields are blank (empty). From here, you have two choices. + +* Manually set each option as needed by your project. +* Open options previously set and saved as an XML-based WrapCUI configuration file (named whatever you like, with whatever extension you like). + +### Manual Option Setting + +Before setting options for full-header and output-dir, you will need to: + +* Download your target C project, which will have your target header (*.h) file. +* Create your target output directory. + +#### Full Header Option + +Manaully type the full or relative path (relative to your current directory) to your target header file. + +Alternatively, use the `...` button to set the full path using the file-open dialog that appears. + +#### Output Directory Option + +Manually type the full or relative path to your target output directory. + +Alternatively, use the `...` button to set the full path using the directory dialog that appears. + +#### C-compiler Options + +Manually enter any C compiler options as needed. + +#### Pre-process Script + +Manually enter the full or relative path to a pre-process script, as needed. + +#### Post-process Script + +Manually enter the full or relative path to a post-process script, as needed. + +#### Config XML File + +Manually type the full or relative path to a config.xml (or other name) file, as needed. + +Alternatively, use the `...` button to set the full path to a config.xml file using the file-open dialog that appears. + +## Next Steps + +Once all of the options are set, you have several steps available to you. + +* `Save` the configuration in an XML file. Do this if you desire to quickly and easily reload the configuration you've just created. +* `Clean` the output directory (delete all files and folders in it) +* `Run` WrapC with the configuration you have set up or loaded (`File->Open`) + +#### Note on Cleaning + +There is a bug in EWG we have not found yet where once you click `Run`, the code does not release its file handles. Attempting to run `Clean` after a `Run` will generate an error and the files and folders will not be deleted. In order to successfully `Clean`, you will need to ensure the configuration is `Save`d, close WrapCUI, re-open WrapCUI, `Open` the saved configuration, and then `Clean` it. diff --git a/wrapcui/wrapcui.ecf b/wrapcui/wrapcui.ecf index 19d6e8b..2dee559 100644 --- a/wrapcui/wrapcui.ecf +++ b/wrapcui/wrapcui.ecf @@ -23,6 +23,7 @@ + /.git$ diff --git a/wrapcui/wui_ewg.e b/wrapcui/wui_ewg.e index b2d5047..42d1d00 100644 --- a/wrapcui/wui_ewg.e +++ b/wrapcui/wui_ewg.e @@ -5,7 +5,7 @@ class WUI_EWG inherit - EWG_KERNAL + EWG_KERNEL create make_with_window @@ -33,7 +33,7 @@ feature -- Basic Ops: Sub-supporting -- `process_c_compiler_options'. do if not main_window.c_compile_textbox.text.is_empty then - compiler_options := main_window.c_compile_textbox.text + compiler_options := main_window.c_compile_textbox.text.to_string_8 report_info_message ("Set compiler options.") else report_info_message ("No compiler options.") @@ -44,13 +44,13 @@ feature -- Basic Ops: Sub-supporting -- `process_extension_scripts_options'. do if not main_window.script_pre_textbox.text.is_empty then - script_pre_process := main_window.script_pre_textbox.text + script_pre_process := main_window.script_pre_textbox.text.to_string_8 report_info_message ("Set pre-process script options.") else report_info_message ("No pre-process script options.") end if not main_window.script_post_textbox.text.is_empty then - script_post_process := main_window.script_post_textbox.text + script_post_process := main_window.script_post_textbox.text.to_string_8 report_info_message ("Set post-process script options.") else report_info_message ("No pre-process script options.") @@ -64,13 +64,13 @@ feature -- Basic Ops: Sub-supporting l_path: PATH do if not main_window.output_dir_textbox.text.is_empty then - output_directory_name := main_window.output_dir_textbox.text + output_directory_name := main_window.output_dir_textbox.text.to_string_8 report_info_message ("Set output directory option.") else report_info_message ("No output directory option.") end if not main_window.full_header_textbox.text.is_empty then - full_header_file_name := main_window.full_header_textbox.text + full_header_file_name := main_window.full_header_textbox.text.to_string_8 l_header_file_name := full_header_file_name.twin create l_path.make_from_string (l_header_file_name) @@ -82,7 +82,7 @@ feature -- Basic Ops: Sub-supporting report_info_message ("No full-header option.") end if not main_window.config_file_textbox.text.is_empty then - config_file_name := main_window.config_file_textbox.text + config_file_name := main_window.config_file_textbox.text.to_string_8 report_info_message ("Set config file option.") else report_info_message ("No config file option.") diff --git a/wrapcui/wui_main_window.e b/wrapcui/wui_main_window.e index 59a1f21..9686193 100644 --- a/wrapcui/wui_main_window.e +++ b/wrapcui/wui_main_window.e @@ -36,7 +36,7 @@ feature {NONE} -- Initialization create full_header_box create full_header_textbox - create full_header_label.make_with_text ("--full_header=<...>") + create full_header_label.make_with_text ("Full_header=<...>") full_header_label.select_actions.force (agent on_full_header_label_link_click) full_header_label.set_tooltip ("Command Line Options Help - see full-header option") create full_header_button.make_with_text_and_action ("...", agent on_full_header_click) @@ -44,7 +44,7 @@ feature {NONE} -- Initialization create output_dir_box create output_dir_textbox - create output_dir_label.make_with_text ("--output-dir=<...>") + create output_dir_label.make_with_text ("Output-dir=<...>") output_dir_label.select_actions.force (agent on_output_dir_label_link_click) output_dir_label.set_tooltip ("Command Line Options Help - see output-dir option") create output_dir_button.make_with_text_and_action ("...", agent on_output_dir_click) @@ -52,7 +52,7 @@ feature {NONE} -- Initialization create cmd_box create run_wrapc_cmd_button.make_with_text_and_action ("Run", agent on_run_wrapc_cmd_button_click) - create clean_generated_files_button.make_with_text_and_action ("Clean", agent on_clean_generated_files_button_click) + create clean_generated_files_checkbox.make_with_text ("Clean") create c_compile_box create c_compile_textbox @@ -107,8 +107,12 @@ feature {NONE} -- Initialization output_dir_box.extend (output_dir_label) output_dir_box.extend (output_dir_textbox) output_dir_box.extend (output_dir_button) + output_dir_box.extend (clean_generated_files_checkbox) + clean_generated_files_checkbox.disable_sensitive + clean_generated_files_checkbox.set_tooltip ("Clean generated files before Run.") output_dir_box.disable_item_expand (output_dir_label) output_dir_box.disable_item_expand (output_dir_button) + output_dir_box.disable_item_expand (clean_generated_files_checkbox) output_dir_box.set_border_width (3) output_dir_box.set_padding_width (3) output_dir_textbox.set_tooltip ("Directory where generated files will be placed.%NLocation of the target Eiffel application folder.") @@ -160,18 +164,13 @@ feature {NONE} -- Initialization main_box.extend (output_box) output_box.extend (output_text) - -- Clean & Run buttons + -- Run button main_box.extend (cmd_box) cmd_box.extend (create {EV_CELL}) - -- Clean - cmd_box.extend (clean_generated_files_button) - clean_generated_files_button.disable_sensitive - -- Run cmd_box.extend (run_wrapc_cmd_button) run_wrapc_cmd_button.disable_sensitive cmd_box.extend (create {EV_CELL}) cmd_box.disable_item_expand (run_wrapc_cmd_button) - cmd_box.disable_item_expand (clean_generated_files_button) cmd_box.set_border_width (3) cmd_box.set_padding_width (3) main_box.disable_item_expand (cmd_box) @@ -228,8 +227,8 @@ feature {NONE} -- GUI Actions config_file_textbox.set_text (l_file_open.file_name) end - on_clean_generated_files_button_click - -- What happens when user clicks `clean_generated_files_button'. + on_clean_generated_files_button_checked + -- What happens when user clicks `clean_generated_files_checkbox'. note design: "[ 1. Delete generated files from previous WrapC `run'. @@ -242,13 +241,10 @@ feature {NONE} -- GUI Actions l_dir: DIRECTORY l_message: STRING l_msg: EV_MESSAGE_DIALOG - l_memory: MEMORY l_file_utilities: FILE_UTILITIES do - create l_memory - l_memory.collect create l_message.make_empty - create l_config_system.make (full_header_textbox.text) + create l_config_system.make (full_header_textbox.text.to_string_8) create l_dir_structure.make (l_config_system) -- c create l_dir.make_with_name (output_dir_textbox.text + {OPERATING_ENVIRONMENT}.Directory_separator.out + l_dir_structure.config_system.directory_structure.c_directory_name) @@ -267,11 +263,11 @@ feature {NONE} -- GUI Actions l_message := "There was nothing to clean." end create l_msg.make_with_text (l_message) - l_msg.set_buttons_and_actions (<<"OK">>, <>) + l_msg.set_buttons_and_actions ({ARRAY [READABLE_STRING_GENERAL]} <<"OK">>, <>) l_msg.show_modal_to_window (Current) rescue create l_msg.make_with_text (clean_exception_msg) - l_msg.set_buttons_and_actions (<<"OK">>, <>) + l_msg.set_buttons_and_actions ({ARRAY [READABLE_STRING_GENERAL]} <<"OK">>, <>) l_msg.show_modal_to_window (Current) end @@ -282,6 +278,9 @@ feature {NONE} -- GUI Actions l_ewg: WUI_EWG l_msg: EV_MESSAGE_DIALOG do + if clean_generated_files_checkbox.is_selected then + on_clean_generated_files_button_checked + end create l_ewg.make_with_window (Current) end @@ -291,6 +290,9 @@ feature {NONE} -- GUI Actions Save your current configuration (if needed) and then re-open the app and then click Clean. Closing the app will release any open file-handles. + + NOTE: There will be an error message right after closing this dialog. + Click the "Ignore" button to continue safely. ]" on_full_header_textbox_focus_out @@ -391,9 +393,9 @@ feature {NONE} -- GUI Actions Support end if has_output_dir then - clean_generated_files_button.enable_sensitive + clean_generated_files_checkbox.enable_sensitive else - clean_generated_files_button.disable_sensitive + clean_generated_files_checkbox.disable_sensitive end end @@ -410,7 +412,7 @@ feature {NONE} -- GUI Actions Support l_path_string: STRING l_list: LIST [STRING] do - l_path_string := full_header_textbox.text.twin + l_path_string := full_header_textbox.text.to_string_8.twin l_list := l_path_string.split ({OPERATING_ENVIRONMENT}.Directory_separator) l_path_string.remove_tail (l_list [l_list.count].count + 1) create l_dir.make (l_path_string) @@ -419,14 +421,8 @@ feature {NONE} -- GUI Actions Support has_output_dir: BOOLEAN -- Does `output_dir_textbox' have directory? - local - l_dir: DIRECTORY - l_path_string: STRING - l_list: LIST [STRING] do - l_path_string := output_dir_textbox.text.twin - create l_dir.make (l_path_string) - Result := l_dir.exists + Result := (create {DIRECTORY}.make (output_dir_textbox.text.to_string_8.twin)).exists end feature {WUI_EWG} -- GUI Components @@ -444,7 +440,7 @@ feature {WUI_EWG} -- GUI Components output_dir_button: EV_BUTTON cmd_box: EV_HORIZONTAL_BOX - clean_generated_files_button, + clean_generated_files_checkbox: EV_CHECK_BUTTON run_wrapc_cmd_button: EV_BUTTON c_compile_box: EV_HORIZONTAL_BOX @@ -528,7 +524,6 @@ feature -- Menu: GUI Actions local l_file: PLAIN_TEXT_FILE l_open: EV_FILE_OPEN_DIALOG - l_factory: XML_PARSER_FACTORY l_content, l_local_part, l_local_part_content: STRING @@ -545,8 +540,7 @@ feature -- Menu: GUI Actions l_content := l_file.last_string l_file.close -- parse it - create l_factory - l_parser := l_factory.new_standard_parser + l_parser := (create {XML_PARSER_FACTORY}).new_standard_parser create l_callbacks l_parser.set_callbacks (l_callbacks) l_parser.parse_from_string (l_content) @@ -554,8 +548,8 @@ feature -- Menu: GUI Actions across l_callbacks.contents as ic loop - l_local_part := ic.item.local_part - l_local_part_content := ic.item.content + l_local_part := ic.item.local_part.to_string_8 + l_local_part_content := ic.item.content.to_string_8 if l_local_part.same_string ("config") then do_nothing elseif l_local_part.same_string ("full_header") then @@ -652,7 +646,7 @@ feature -- Menu: GUI Actions l_msg: EV_MESSAGE_DIALOG do create l_msg.make_with_text ("Eiffel Sotware WrapC-UI%NCopyright 2019 (c)") - l_msg.set_buttons_and_actions (<<"OK">>, <>) + l_msg.set_buttons_and_actions ({ARRAY [READABLE_STRING_GENERAL]} <<"OK">>, <>) l_msg.show_modal_to_window (Current) end