Mercurial > hg > octave-lyh
changeset 16399:f9a737fd8829
allow command-line edit function to use GUI editor
* file-editor-interface.h
(file_editor_interface::handle_edit_file_request): New pure virtual function.
* file-editor.h, file-editor.cc
(file_editor::handle_edit_file_request): New function.
* octave-event-listener.h (octave_event_listenter::edit_file): New
pure virtual function.
* octave-qt-event-listener.h, octave-qt-event-listener.cc
(octave_qt_event_listener::edit_file): New function.
(octave_qt_event_listener::edit_file_signal): New signal.
* main-window.h, main-window.cc
(main_window::handle_edit_file_request): New function.
(main_window::construct): Connect edit_file_signal to
handle_edit_file_request.
* __execute_edit_hook__.cc: New file. Provide
Fadd_edit_hook, Fremove_edit_hook, and F__execute_edit_hook__
functions for the interpreter.
* libinterp/corefcn/module.mk (COREFCN_SRC): Include it in the list.
* octave-link.h, octave-link.cc (octave_link::edit_file,
octave_link::do_edit_file): New functions.
* octave-main-thread.cc (edit_hook_fcn): New function.
(octave_main_thread::run): Install it as an edit_hook function.
* miscellaneous/edit.m (do_edit): New subfunction. Allow edit request
to be intercepted by edit_hook function.
(edit): Use it to uniformly handle starting the editor.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Sat, 30 Mar 2013 10:57:15 -0400 |
parents | 48b3d172042d |
children | 424463a80134 |
files | libgui/src/m-editor/file-editor-interface.h libgui/src/m-editor/file-editor.cc libgui/src/m-editor/file-editor.h libgui/src/main-window.cc libgui/src/main-window.h libgui/src/octave-adapter/octave-event-listener.h libgui/src/octave-adapter/octave-link.cc libgui/src/octave-adapter/octave-link.h libgui/src/octave-adapter/octave-main-thread.cc libgui/src/octave-qt-event-listener.cc libgui/src/octave-qt-event-listener.h libinterp/corefcn/__execute_edit_hook__.cc libinterp/corefcn/module.mk scripts/miscellaneous/edit.m |
diffstat | 14 files changed, 252 insertions(+), 19 deletions(-) [+] |
line wrap: on
line diff
--- a/libgui/src/m-editor/file-editor-interface.h +++ b/libgui/src/m-editor/file-editor-interface.h @@ -56,6 +56,9 @@ virtual void handle_update_dbstop_marker_request (bool insert, const QString& file, int line) = 0; + + virtual void handle_edit_file_request (const QString& file) = 0; + virtual void set_focus () = 0; public slots:
--- a/libgui/src/m-editor/file-editor.cc +++ b/libgui/src/m-editor/file-editor.cc @@ -335,6 +335,12 @@ } void +file_editor::handle_edit_file_request (const QString& file) +{ + request_open_file (file); +} + +void file_editor::request_undo () { emit fetab_undo (_tab_widget->currentWidget ());
--- a/libgui/src/m-editor/file-editor.h +++ b/libgui/src/m-editor/file-editor.h @@ -135,6 +135,7 @@ void handle_delete_debugger_pointer_request (const QString& file, int line); void handle_update_dbstop_marker_request (bool insert, const QString& file, int line); + void handle_edit_file_request (const QString& file); /** Tells the editor to react on changed settings. */ void notice_settings ();
--- a/libgui/src/main-window.cc +++ b/libgui/src/main-window.cc @@ -536,6 +536,14 @@ } void +main_window::handle_edit_file_request (const QString& file) +{ +#ifdef HAVE_QSCINTILLA + _file_editor->handle_edit_file_request (file); +#endif +} + +void main_window::debug_continue () { octave_link::post_event (this, &main_window::debug_continue_callback); @@ -1203,6 +1211,11 @@ SIGNAL (update_dbstop_marker_signal (bool, const QString&, int)), this, SLOT (handle_update_dbstop_marker_request (bool, const QString&, int))); + + connect (_octave_qt_event_listener, + SIGNAL (edit_file_signal (const QString&)), + this, + SLOT (handle_edit_file_request(const QString&))); } void
--- a/libgui/src/main-window.h +++ b/libgui/src/main-window.h @@ -121,6 +121,7 @@ void handle_insert_debugger_pointer_request (const QString& file, int line); void handle_delete_debugger_pointer_request (const QString& file, int line); void handle_update_dbstop_marker_request (bool insert, const QString& file, int line); + void handle_edit_file_request (const QString& file); void debug_continue (); void debug_step_into (); void debug_step_over ();
--- a/libgui/src/octave-adapter/octave-event-listener.h +++ b/libgui/src/octave-adapter/octave-event-listener.h @@ -49,6 +49,8 @@ virtual void update_dbstop_marker (bool insert, const std::string& file, int line) = 0; + virtual void edit_file (const std::string& file) = 0; + virtual void about_to_exit () = 0; virtual void entered_debug_mode () = 0;
--- a/libgui/src/octave-adapter/octave-link.cc +++ b/libgui/src/octave-adapter/octave-link.cc @@ -283,6 +283,29 @@ } } +void +octave_link::do_edit_file (const octave_value_list& args) +{ + if (event_listener) + { + if (args.length () == 1) + { + std::string file = args(0).string_value (); + + if (! error_state) + { + event_listener->edit_file (file); + do_process_events (); + + } + else + ::error ("expecting file name in edit file callback"); + } + else + ::error ("invalid call to edit file callback"); + } +} + bool octave_link::instance_ok (void) {
--- a/libgui/src/octave-adapter/octave-link.h +++ b/libgui/src/octave-adapter/octave-link.h @@ -165,6 +165,13 @@ instance->do_update_breakpoint_hook_fcn (insert, args); } + static void + edit_file (const octave_value_list& args) + { + if (instance_ok ()) + instance->do_edit_file (args); + } + private: static octave_link *instance; @@ -236,6 +243,8 @@ void do_exit_debugger_event_hook_fcn (const octave_value_list& args); void do_update_breakpoint_hook_fcn (bool insert, const octave_value_list& args); + + void do_edit_file (const octave_value_list& args); }; #endif // OCTAVELINK_H
--- a/libgui/src/octave-adapter/octave-main-thread.cc +++ b/libgui/src/octave-adapter/octave-main-thread.cc @@ -95,6 +95,16 @@ return retval; } +static octave_value_list +edit_hook_fcn (const octave_value_list& args, int) +{ + octave_value_list retval; + + octave_link::edit_file (args); + + return retval; +} + octave_main_thread::octave_main_thread () : QThread () { } @@ -134,6 +144,10 @@ octave_value dbclear_fcn_handle (new octave_fcn_handle (dbclear_fcn)); Fadd_dbclear_hook (dbclear_fcn_handle); + octave_value edit_fcn (new octave_builtin (edit_hook_fcn)); + octave_value edit_fcn_handle (new octave_fcn_handle (edit_fcn)); + Fadd_edit_hook (edit_fcn_handle); + // Prime the history list. octave_link::update_history ();
--- a/libgui/src/octave-qt-event-listener.cc +++ b/libgui/src/octave-qt-event-listener.cc @@ -77,6 +77,12 @@ } void +octave_qt_event_listener::edit_file (const std::string& file) +{ + emit edit_file_signal (QString::fromStdString (file)); +} + +void octave_qt_event_listener::about_to_exit () { qApp->quit ();
--- a/libgui/src/octave-qt-event-listener.h +++ b/libgui/src/octave-qt-event-listener.h @@ -40,6 +40,7 @@ void insert_debugger_pointer (const std::string& file, int line); void delete_debugger_pointer (const std::string& file, int line); void update_dbstop_marker (bool insert, const std::string& file, int line); + void edit_file (const std::string& file); void about_to_exit (); void entered_debug_mode (); @@ -52,6 +53,7 @@ void insert_debugger_pointer_signal (const QString& file, int line); void delete_debugger_pointer_signal (const QString& file, int line); void update_dbstop_marker_signal (bool insert, const QString& file, int line); + void edit_file_signal (const QString& file); void entered_debug_mode_signal (); void quit_debug_mode_signal (); };
new file mode 100644 --- /dev/null +++ b/libinterp/corefcn/__execute_edit_hook__.cc @@ -0,0 +1,143 @@ +/* + +Copyright (C) 2013 John W. Eaton + +This file is part of Octave. + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3 of the License, or (at +your option) any later version. + +Octave is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Octave; see the file COPYING. If not, see +<http://www.gnu.org/licenses/>. + +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "defun.h" +#include "error.h" +#include "defun.h" +#include "hook-fcn.h" +#include "oct-obj.h" + +static hook_function_list edit_hook_functions; + +DEFUN (add_edit_hook, args, , + "-*- texinfo -*-\n\ +@deftypefn {Built-in Function} {@var{id} =} add_edit_hook (@var{fcn})\n\ +@deftypefnx {Built-in Function} {@var{id} =} add_edit_hook (@var{fcn}, @var{data})\n\ +Add the named function or function handle @var{fcn} to the list of functions to call\n\ +to handle editing files. The function should have the form\n\ +\n\ +@example\n\ +@var{fcn} (@var{file}, @var{data})\n\ +@end example\n\ +\n\ +If @var{data} is omitted, Octave calls the function without one argument.\n\ +\n\ +The returned identifier may be used to remove the function handle from\n\ +the list of input hook functions.\n\ +@seealso{remove_edit_hook}\n\ +@end deftypefn") +{ + octave_value retval; + + int nargin = args.length (); + + if (nargin == 1 || nargin == 2) + { + octave_value user_data; + + if (nargin == 2) + user_data = args(1); + + hook_function hook_fcn (args(0), user_data); + + if (! error_state) + { + edit_hook_functions.insert (hook_fcn.id (), hook_fcn); + + retval = hook_fcn.id (); + } + else + error ("add_edit_hook: expecting string as first arg"); + } + else + print_usage (); + + return retval; +} + +DEFUN (remove_edit_hook, args, , + "-*- texinfo -*-\n\ +@deftypefn {Built-in Function} {} remove_edit_hook (@var{name})\n\ +@deftypefnx {Built-in Function} {} remove_input_event_hook (@var{fcn_id})\n\ +Remove the named function or function handle with the given identifier\n\ +from the list of functions to call to handle editing files.\n\ +@seealso{add_edit_hook}\n\ +@end deftypefn") +{ + octave_value_list retval; + + int nargin = args.length (); + + if (nargin == 1 || nargin == 2) + { + std::string hook_fcn_id = args(0).string_value (); + + bool warn = (nargin < 2); + + if (! error_state) + { + hook_function_list::iterator p + = edit_hook_functions.find (hook_fcn_id); + + if (p != edit_hook_functions.end ()) + edit_hook_functions.erase (p); + else if (warn) + warning ("remove_edit_hook: %s not found in list", + hook_fcn_id.c_str ()); + } + else + error ("remove_edit_hook: argument not valid as a hook function name or id"); + } + else + print_usage (); + + return retval; +} + +DEFUN (__execute_edit_hook__, args, , + "-*- texinfo -*-\n\ +@deftypefn {Built-in Function} {@var{status} =} __execute_edit_hook__ (@var{file})\n\ +Undocumented internal function.\n\ +@end deftypefn") +{ + octave_value retval; + + if (edit_hook_functions.empty ()) + retval = false; + else + { + edit_hook_functions.run (args); + + retval = true; + } + + return retval; +} + +/* +## No test needed for internal helper function. +%!assert (1) +*/
--- a/libinterp/corefcn/module.mk +++ b/libinterp/corefcn/module.mk @@ -27,6 +27,7 @@ COREFCN_SRC = \ corefcn/__contourc__.cc \ corefcn/__dispatch__.cc \ + corefcn/__execute_edit_hook__.cc \ corefcn/__lin_interpn__.cc \ corefcn/__pchip_deriv__.cc \ corefcn/__qp__.cc \
--- a/scripts/miscellaneous/edit.m +++ b/scripts/miscellaneous/edit.m @@ -241,13 +241,16 @@ ## Start the editor without a file if no file is given. if (nargin < 1) - if (exist (FUNCTION.HOME, "dir") == 7 && (isunix () || ! ispc ())) - system (cstrcat ("cd \"", FUNCTION.HOME, "\" ; ", - sprintf (undo_string_escapes (FUNCTION.EDITOR), "")), - [], FUNCTION.MODE); + if (exist (FUNCTION.HOME, "dir") == 7) + curr_dir = pwd (); + unwind_protect + chdir (FUNCTION.HOME); + do_edit (FUNCTION.EDITOR, "", FUNCTION.MODE); + unwind_protect_cleanup + chdir (curr_dir); + end_unwind_protect else - system (sprintf (undo_string_escapes (FUNCTION.EDITOR), ""), - [], FUNCTION.MODE); + do_edit (FUNCTION.EDITOR, "", FUNCTION.MODE); endif return; endif @@ -329,9 +332,7 @@ ## If the file exists, then edit it. if (FUNCTION.EDITINPLACE) ## Edit in place even if it is protected. - system (sprintf (undo_string_escapes (FUNCTION.EDITOR), - cstrcat ("\"", fileandpath, "\"")), - [], FUNCTION.MODE); + do_edit (FUNCTION.EDITOR, fileandpath, FUNCTION.MODE); return; else ## If the file is modifiable in place then edit it, otherwise make @@ -347,9 +348,7 @@ else fclose (fid); endif - system (sprintf (undo_string_escapes (FUNCTION.EDITOR), - cstrcat ("\"", fileandpath, "\"")), - [], FUNCTION.MODE); + do_edit (FUNCTION.EDITOR, fileandpath, FUNCTION.MODE); return; endif endif @@ -364,9 +363,7 @@ case {"cc", "m"} 0; otherwise - system (sprintf (undo_string_escapes (FUNCTION.EDITOR), - cstrcat ("\"", fileandpath, "\"")), - [], FUNCTION.MODE); + do_edit (FUNCTION.EDITOR, fileandpath, FUNCTION.MODE); return; endswitch @@ -515,10 +512,7 @@ fputs (fid, text); fclose (fid); - ## Finally we are ready to edit it! - system (sprintf (undo_string_escapes (FUNCTION.EDITOR), - cstrcat ("\"", fileandpath, "\"")), - [], FUNCTION.MODE); + do_edit (FUNCTION.EDITOR, fileandpath, FUNCTION.MODE); endif @@ -564,6 +558,21 @@ endfunction +function do_edit (editor, file, mode) + + ## Give the hook function a chance. If that fails, fall back + ## on running an editor with the system function. + + status = __execute_edit_hook__ (file); + + if (! status) + system (sprintf (undo_string_escapes (editor), + cstrcat ("\"", file, "\"")), + [], mode); + endif + +endfunction + %!test %! s.editor = edit ("get", "editor");