Mercurial > octave
diff libinterp/corefcn/help.cc @ 23721:b2d55b52ee51
new class to manage help system and associated variables
* help.h, help.cc (help_system): New class. Handle
built_in_docstrings_file, doc_cache_file, info_file, info_program,
makeinfo_program, suppress_verbose_help_message, and texi_macros_file
variables. Move most static and global functions inside class.
Change all uses.
* interpreter.h, interpreter.cc (interpreter::m_help_system):
New member variable.
(interpreter::get_help_system): New function.
* interpreter-private.h, interpreter-private.cc (__get_help_system__):
New function.
* defaults.h, defaults.cc (Vbuilt_in_docstrings_file, VEXEC_PATH,
VIMAGE_PATH): Delete.
(config::prepend_octave_home, config::prepend_octave_exec_home):
Define here instead of as static functions in defaults.cc.
(init_defaults): Now static.
(set_default_info_file, set_default_info_prog,
set_default_texi_macros_file, set_default_doc_cache_file,
set_built_in_docstrings_file, install_defaults):
Delete.
* toplev.cc (F__octave_config_info__): Don't include "infofile"
in the struct.
* octave.cc (application::init): Don't call install_defaults.
* documentation-dock-widget.h, documentation-dock-widget.cc
(documentation_dock_widget::load_info_file): New slot.
* main-window.cc (main_window::main_window):
Connect m_interpreter::octave_ready_signal to
doc_browser_window::load_info_file.
* octave-gui.cc (gui_application::gui_application): Don't call
install_defaults here.
* webinfo.h, webinfo.cc (webinfo::load_info_file): New function to set
file for info browser after interpreter is ready instead of doing that
in the webinfo constructor.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Thu, 29 Jun 2017 20:16:54 -0400 |
parents | b9378eff6d13 |
children | 980f39c3ab90 |
line wrap: on
line diff
--- a/libinterp/corefcn/help.cc Thu Jun 29 16:44:47 2017 -0400 +++ b/libinterp/corefcn/help.cc Thu Jun 29 20:16:54 2017 -0400 @@ -70,29 +70,7 @@ #include "variables.h" #include "version.h" -// Name of the doc cache file specified on the command line. -// (--doc-cache-file file) -std::string Vdoc_cache_file; - -// Name of the file containing local Texinfo macros that are prepended -// to doc strings before processing. -// (--texi-macros-file) -std::string Vtexi_macros_file; - -// Name of the info file specified on command line. -// (--info-file file) -std::string Vinfo_file; - -// Name of the info reader we'd like to use. -// (--info-program program) -std::string Vinfo_program; - -// Name of the makeinfo program to run. -static std::string Vmakeinfo_program = "makeinfo"; - -// If TRUE, don't print additional help message in help and usage -// functions. -static bool Vsuppress_verbose_help_message = false; +#include "default-defs.h" const static char * const operators[] = { @@ -146,105 +124,6 @@ const static string_vector operator_names (operators); -// Return a vector of all functions from this file, -// for use in command line auto-completion. -static string_vector -local_functions (void) -{ - string_vector retval; - - octave::call_stack& cs = octave::__get_call_stack__ ("local_functions"); - - octave_user_code *curr_fcn = cs.caller_user_code (); - - if (! curr_fcn) - return retval; - - // All subfunctions are listed in the top-level function of this file. - while (curr_fcn->is_subfunction ()) - { - octave::symbol_table::scope *pscope = curr_fcn->parent_fcn_scope (); - curr_fcn = pscope->function (); - } - - // Get subfunctions. - const std::list<std::string> names = curr_fcn->subfunction_names (); - - size_t sz = names.size (); - retval.resize (sz); - - // Loop over them. - size_t i = 0; - for (const auto& nm : names) - retval(i++) = nm; - - return retval; -} - -// FIXME: It's not likely that this does the right thing now. - -string_vector -make_name_list (void) -{ - const static string_vector keywords = Fiskeyword ()(0).string_vector_value (); - const static int key_len = keywords.numel (); - - octave::symbol_table& symtab = octave::__get_symbol_table__ ("make_name_list"); - - const string_vector bif = symtab.built_in_function_names (); - const int bif_len = bif.numel (); - - const string_vector cfl = symtab.cmdline_function_names (); - const int cfl_len = cfl.numel (); - - const string_vector lcl = symtab.variable_names (); - const int lcl_len = lcl.numel (); - - octave::load_path& lp = octave::__get_load_path__ ("make_name_list"); - - const string_vector ffl = lp.fcn_names (); - const int ffl_len = ffl.numel (); - - const string_vector afl = octave::autoloaded_functions (); - const int afl_len = afl.numel (); - - const string_vector lfl = local_functions (); - const int lfl_len = lfl.numel (); - - const int total_len - = key_len + bif_len + cfl_len + lcl_len + ffl_len + afl_len + lfl_len; - - string_vector list (total_len); - - // Put all the symbols in one big list. - - int j = 0; - int i = 0; - - for (i = 0; i < key_len; i++) - list[j++] = keywords[i]; - - for (i = 0; i < bif_len; i++) - list[j++] = bif[i]; - - for (i = 0; i < cfl_len; i++) - list[j++] = cfl[i]; - - for (i = 0; i < lcl_len; i++) - list[j++] = lcl[i]; - - for (i = 0; i < ffl_len; i++) - list[j++] = ffl[i]; - - for (i = 0; i < afl_len; i++) - list[j++] = afl[i]; - - for (i = 0; i < lfl_len; i++) - list[j++] = lfl[i]; - - return list; -} - static bool looks_like_html (const std::string& msg) { @@ -271,264 +150,578 @@ return (p2 != std::string::npos); } -static bool -raw_help_from_symbol_table (const std::string& nm, std::string& h, - std::string& w, bool& symbol_found) +// FIXME: Are we sure this function always does the right thing? +static inline bool +file_is_in_dir (const std::string filename, const std::string dir) { - bool retval = false; - - octave::symbol_table& symtab = octave::__get_symbol_table__ ("raw_help_from_symbol_table"); - - octave_value val = symtab.find_function (nm); - - if (val.is_defined ()) + if (filename.find (dir) == 0) { - octave_function *fcn = val.function_value (); - - if (fcn) - { - symbol_found = true; - - h = fcn->doc_string (); - - retval = true; + const int dir_len = dir.size (); + const int filename_len = filename.size (); + const int max_allowed_seps = + (octave::sys::file_ops::is_dir_sep (dir[dir_len-1]) ? 0 : 1); - w = fcn->fcn_file_name (); - - if (w.empty ()) - w = fcn->is_user_function () - ? "command-line function" : "built-in function"; - } - } - - return retval; -} + int num_seps = 0; + for (int i = dir_len; i < filename_len; i++) + if (octave::sys::file_ops::is_dir_sep (filename[i])) + num_seps++; -static bool -raw_help_from_file (const std::string& nm, std::string& h, - std::string& file, bool& symbol_found) -{ - bool retval = false; - - h = octave::get_help_from_file (nm, symbol_found, file); - - if (h.length () > 0) - retval = true; - - return retval; + return (num_seps <= max_allowed_seps); + } + else + return false; } -static bool -raw_help_from_docstrings_file (const std::string& nm, std::string& h, - bool& symbol_found) +namespace octave { - typedef std::pair<std::streampos, std::streamoff> txt_limits_type; - typedef std::map<std::string, txt_limits_type> help_txt_map_type; + octave_value + help_system::built_in_docstrings_file (const octave_value_list& args, + int nargout) + { + return set_internal_variable (m_built_in_docstrings_file, args, nargout, + "built_in_docstrings_file", false); + } + + octave_value + help_system::doc_cache_file (const octave_value_list& args, int nargout) + { + return set_internal_variable (m_doc_cache_file, args, nargout, + "doc_cache_file", false); + } + + octave_value + help_system::info_file (const octave_value_list& args, int nargout) + { + return set_internal_variable (m_info_file, args, nargout, + "info_file", false); + } + + octave_value + help_system::info_program (const octave_value_list& args, int nargout) + { + return set_internal_variable (m_info_program, args, nargout, + "info_program", false); + } - static help_txt_map_type help_txt_map; - static bool initialized = false; + octave_value + help_system::makeinfo_program (const octave_value_list& args, int nargout) + { + return set_internal_variable (m_makeinfo_program, args, nargout, + "makeinfo_program", false); + } + + octave_value + help_system::suppress_verbose_help_message (const octave_value_list& args, + int nargout) + { + return set_internal_variable (m_suppress_verbose_help_message, args, + nargout, "suppress_verbose_help_message"); + } - h = ""; - symbol_found = false; + octave_value + help_system::texi_macros_file (const octave_value_list& args, int nargout) + { + return set_internal_variable (m_texi_macros_file, args, nargout, + "texi_macros_file", false); + } + + std::string + help_system::raw_help (const std::string& nm, bool& symbol_found) const + { + std::string h; + std::string w; + std::string f; + + bool found; - // FIXME: Should we cache the timestamp of the file and reload the - // offsets if it changes? Or just warn about that? Or just ignore - // it, and assume it won't change? + found = raw_help_from_symbol_table (nm, h, w, symbol_found); + + if (! found) + found = raw_help_from_file (nm, h, f, symbol_found); + + bool external_doc = h.compare (0, 12, "external-doc") == 0; + + if (! found || external_doc) + { + std::string tmp_nm = nm; + + if (external_doc && h.length () > 12 && h[12] == ':') + tmp_nm = h.substr (13); - if (! initialized) - { - std::string fname = Vbuilt_in_docstrings_file; + raw_help_from_docstrings_file (tmp_nm, h, symbol_found); + } + + return h; + } + + std::string help_system::which (const std::string& name, + std::string& type) const + { + std::string file; + + type = ""; + + symbol_table& symtab = m_interpreter.get_symbol_table (); + + octave_value val = symtab.find_function (name); - std::ifstream file (fname.c_str (), std::ios::in | std::ios::binary); + if (name.find_first_of ('.') == std::string::npos) + { + if (val.is_defined ()) + { + octave_function *fcn = val.function_value (); + + if (fcn) + { + file = fcn->fcn_file_name (); - if (! file) - error ("failed to open docstrings file: %s", fname.c_str ()); + if (file.empty ()) + { + if (fcn->is_user_function ()) + type = "command-line function"; + else + { + file = fcn->src_file_name (); + type = "built-in function"; + } + } + else + type = val.is_user_script () + ? std::string ("script") : std::string ("function"); + } + } + else + { + // We might find a file that contains only a doc string. - // Ignore header; - file.ignore (std::numeric_limits<std::streamsize>::max(), 0x1d); + load_path& lp = m_interpreter.get_load_path (); - if (file.eof ()) - error ("invalid built-in-docstrings file!"); + file = lp.find_fcn_file (name); + } + } + else + { + // File query. + + load_path& lp = m_interpreter.get_load_path (); + + // For compatibility: "file." queries "file". + if (name.size () > 1 && name[name.size () - 1] == '.') + file = lp.find_file (name.substr (0, name.size () - 1)); + else + file = lp.find_file (name); + + file = sys::env::make_absolute (file); + } + + return file; + } + + std::string help_system::which (const std::string& name) const + { + std::string type; + + return which (name, type); + } - // FIXME: eliminate fixed buffer size. - size_t bufsize = 1000; - OCTAVE_LOCAL_BUFFER (char, buf, bufsize); + string_vector help_system::make_name_list (void) const + { + const static string_vector keywords + = Fiskeyword ()(0).string_vector_value (); + + const static int key_len = keywords.numel (); + + symbol_table& symtab = m_interpreter.get_symbol_table (); + + const string_vector bif = symtab.built_in_function_names (); + const int bif_len = bif.numel (); + + const string_vector cfl = symtab.cmdline_function_names (); + const int cfl_len = cfl.numel (); + + const string_vector lcl = symtab.variable_names (); + const int lcl_len = lcl.numel (); + + load_path& lp = m_interpreter.get_load_path (); + + const string_vector ffl = lp.fcn_names (); + const int ffl_len = ffl.numel (); + + const string_vector afl = autoloaded_functions (); + const int afl_len = afl.numel (); + + const string_vector lfl = local_functions (); + const int lfl_len = lfl.numel (); + + const int total_len + = key_len + bif_len + cfl_len + lcl_len + ffl_len + afl_len + lfl_len; + + string_vector list (total_len); + + // Put all the symbols in one big list. - while (! file.eof ()) - { - std::string name; - int i = 0; - int c; - while (file && (c = file.get ()) != std::istream::traits_type::eof ()) - { - if (c == '\n' || c == '\r') - { - buf[i] = '\0'; - name = buf; - break; - } - else - buf[i++] = c; - } + int j = 0; + int i = 0; + + for (i = 0; i < key_len; i++) + list[j++] = keywords[i]; + + for (i = 0; i < bif_len; i++) + list[j++] = bif[i]; + + for (i = 0; i < cfl_len; i++) + list[j++] = cfl[i]; + + for (i = 0; i < lcl_len; i++) + list[j++] = lcl[i]; + + for (i = 0; i < ffl_len; i++) + list[j++] = ffl[i]; + + for (i = 0; i < afl_len; i++) + list[j++] = afl[i]; + + for (i = 0; i < lfl_len; i++) + list[j++] = lfl[i]; + + return list; + } + + void help_system::get_help_text (const std::string& name, std::string& text, + std::string& format) const + { + bool symbol_found = false; + text = raw_help (name, symbol_found); - // Skip @c FILENAME which is part of current DOCSTRINGS - // syntax. This may disappear if a specific format for - // docstring files is developed. - while (file - && (c = file.get ()) != std::istream::traits_type::eof () - && c != '\n' && c != '\r') - ; // skip text + format = "Not found"; + if (symbol_found) + { + size_t idx = -1; + if (text.empty ()) + { + format = "Not documented"; + } + else if (looks_like_texinfo (text, idx)) + { + format = "texinfo"; + text.erase (0, idx); + } + else if (looks_like_html (text)) + { + format = "html"; + } + else + { + format = "plain text"; + } + } + } + + void help_system::get_help_text_from_file (const std::string& fname, + std::string& text, + std::string& format) const + { + bool symbol_found = false; + + std::string f; + + raw_help_from_file (fname, text, f, symbol_found); - // skip newline characters - while (file - && (c = file.get ()) != std::istream::traits_type::eof () - && c == '\n' && c == '\r') - ; // skip text + format = "Not found"; + if (symbol_found) + { + size_t idx = -1; + if (text.empty ()) + { + format = "Not documented"; + } + else if (looks_like_texinfo (text, idx)) + { + format = "texinfo"; + text.erase (0, idx); + } + else if (looks_like_html (text)) + { + format = "html"; + } + else + { + format = "plain text"; + } + } + } + + std::string help_system::init_built_in_docstrings_file (void) + { + std::string df = sys::env::getenv ("OCTAVE_BUILT_IN_DOCSTRINGS_FILE"); + + std::string dir_sep = sys::file_ops::dir_sep_str (); + + if (df.empty ()) + df = config::oct_etc_dir () + dir_sep + "built-in-docstrings"; - file.unget (); + return df; + } + + std::string help_system::init_doc_cache_file (void) + { + std::string def_file = config::prepend_octave_home (OCTAVE_DOC_CACHE_FILE); + + std::string env_file = sys::env::getenv ("OCTAVE_DOC_CACHE_FILE"); + + return (env_file.empty () ? def_file : env_file); + } + + std::string help_system::init_info_file (void) + { + std::string std_info_file = config::prepend_octave_home (OCTAVE_INFOFILE); + + std::string oct_info_file = sys::env::getenv ("OCTAVE_INFO_FILE"); - // Position of beginning of help text. - std::streampos beg = file.tellg (); + return (oct_info_file.empty () ? std_info_file : oct_info_file); + } + + std::string help_system::init_info_program (void) + { + std::string info_prog = sys::env::getenv ("OCTAVE_INFO_PROGRAM"); - // Skip help text. - file.ignore (std::numeric_limits<std::streamsize>::max(), 0x1d); + if (info_prog.empty ()) + info_prog = "info"; + + return info_prog; + } + + std::string help_system::init_texi_macros_file (void) + { + std::string def_file + = config::prepend_octave_home (OCTAVE_TEXI_MACROS_FILE); - // Position of end of help text. - std::streamoff len; + std::string env_file = sys::env::getenv ("OCTAVE_TEXI_MACROS_FILE"); + + return (env_file.empty () ? def_file : env_file); + } + + // Return a vector of all functions from this file, + // for use in command line auto-completion. + string_vector help_system::local_functions (void) const + { + string_vector retval; + + call_stack& cs = m_interpreter.get_call_stack (); + + octave_user_code *curr_fcn = cs.caller_user_code (); + + if (! curr_fcn) + return retval; + + // All subfunctions are listed in the top-level function of this file. + while (curr_fcn->is_subfunction ()) + { + symbol_table::scope *pscope = curr_fcn->parent_fcn_scope (); + curr_fcn = pscope->function (); + } + + // Get subfunctions. + const std::list<std::string> names = curr_fcn->subfunction_names (); + + size_t sz = names.size (); + retval.resize (sz); + + // Loop over them. + size_t i = 0; + for (const auto& nm : names) + retval(i++) = nm; - if (! file.eof ()) - len = file.tellg () - beg - 1; - else - { - file.seekg (0, file.end); - len = file.tellg () - beg - 1; - file.setstate (file.eofbit); // reset eof flag - } + return retval; + } + + bool help_system::raw_help_from_symbol_table (const std::string& nm, + std::string& h, std::string& w, + bool& symbol_found) const + { + bool retval = false; + + symbol_table& symtab = m_interpreter.get_symbol_table (); + + octave_value val = symtab.find_function (nm); + + if (val.is_defined ()) + { + octave_function *fcn = val.function_value (); - help_txt_map[name] = txt_limits_type (beg, len); - } + if (fcn) + { + symbol_found = true; + + h = fcn->doc_string (); + + retval = true; - initialized = true; - } + w = fcn->fcn_file_name (); + + if (w.empty ()) + w = fcn->is_user_function () + ? "command-line function" : "built-in function"; + } + } + + return retval; + } - help_txt_map_type::const_iterator it = help_txt_map.find (nm); + bool help_system::raw_help_from_file (const std::string& nm, + std::string& h, std::string& file, + bool& symbol_found) const + { + bool retval = false; + + h = octave::get_help_from_file (nm, symbol_found, file); + + if (h.length () > 0) + retval = true; + + return retval; + } - if (it != help_txt_map.end ()) - { - txt_limits_type txt_limits = it->second; + bool + help_system::raw_help_from_docstrings_file (const std::string& nm, + std::string& h, + bool& symbol_found) const + { + typedef std::pair<std::streampos, std::streamoff> txt_limits_type; + typedef std::map<std::string, txt_limits_type> help_txt_map_type; + + static help_txt_map_type help_txt_map; + static bool initialized = false; + + h = ""; + symbol_found = false; + + // FIXME: Should we cache the timestamp of the file and reload the + // offsets if it changes? Or just warn about that? Or just ignore + // it, and assume it won't change? - std::streampos beg = txt_limits.first; - std::streamoff len = txt_limits.second; + if (! initialized) + { + std::ifstream file (m_built_in_docstrings_file.c_str (), + std::ios::in | std::ios::binary); - std::string fname = Vbuilt_in_docstrings_file; + if (! file) + error ("failed to open docstrings file: %s", + m_built_in_docstrings_file.c_str ()); + + // Ignore header; + file.ignore (std::numeric_limits<std::streamsize>::max(), 0x1d); + + if (file.eof ()) + error ("invalid built-in-docstrings file!"); - std::ifstream file (fname.c_str (), std::ios::in | std::ios::binary); + // FIXME: eliminate fixed buffer size. + size_t bufsize = 1000; + OCTAVE_LOCAL_BUFFER (char, buf, bufsize); - if (! file) - error ("failed to open docstrings file: %s", fname.c_str ()); + while (! file.eof ()) + { + std::string name; + int i = 0; + int c; + while (file && (c = file.get ()) != std::istream::traits_type::eof ()) + { + if (c == '\n' || c == '\r') + { + buf[i] = '\0'; + name = buf; + break; + } + else + buf[i++] = c; + } - file.seekg (beg); + // Skip @c FILENAME which is part of current DOCSTRINGS + // syntax. This may disappear if a specific format for + // docstring files is developed. + while (file + && (c = file.get ()) != std::istream::traits_type::eof () + && c != '\n' && c != '\r') + ; // skip text + + // skip newline characters + while (file + && (c = file.get ()) != std::istream::traits_type::eof () + && c == '\n' && c == '\r') + ; // skip text + + file.unget (); + + // Position of beginning of help text. + std::streampos beg = file.tellg (); - size_t txt_len = len; - OCTAVE_LOCAL_BUFFER (char, buf, txt_len + 1); + // Skip help text. + file.ignore (std::numeric_limits<std::streamsize>::max(), 0x1d); + + // Position of end of help text. + std::streamoff len; - file.read (buf, txt_len); + if (! file.eof ()) + len = file.tellg () - beg - 1; + else + { + file.seekg (0, file.end); + len = file.tellg () - beg - 1; + file.setstate (file.eofbit); // reset eof flag + } + + help_txt_map[name] = txt_limits_type (beg, len); + } + + initialized = true; + } - buf[txt_len] = '\0'; + help_txt_map_type::const_iterator it = help_txt_map.find (nm); + + if (it != help_txt_map.end ()) + { + txt_limits_type txt_limits = it->second; + + std::streampos beg = txt_limits.first; + std::streamoff len = txt_limits.second; - h = buf; + std::ifstream file (m_built_in_docstrings_file.c_str (), + std::ios::in | std::ios::binary); + + if (! file) + error ("failed to open docstrings file: %s", + m_built_in_docstrings_file.c_str ()); + + file.seekg (beg); + + size_t txt_len = len; + OCTAVE_LOCAL_BUFFER (char, buf, txt_len + 1); - symbol_found = true; - } + file.read (buf, txt_len); + + buf[txt_len] = '\0'; + + h = buf; + + symbol_found = true; + } - return symbol_found; + return symbol_found; + } + + // FIXME: It's not likely that this does the right thing now. + + string_vector make_name_list (void) + { + octave::help_system& help_sys + = octave::__get_help_system__ ("make_name_list"); + + return help_sys.make_name_list (); + } } -std::string -raw_help (const std::string& nm, bool& symbol_found) -{ - std::string h; - std::string w; - std::string f; - - bool found; - - found = raw_help_from_symbol_table (nm, h, w, symbol_found); - - if (! found) - found = raw_help_from_file (nm, h, f, symbol_found); - - bool external_doc = h.compare (0, 12, "external-doc") == 0; - - if (! found || external_doc) - { - std::string tmp_nm = nm; - - if (external_doc && h.length () > 12 && h[12] == ':') - tmp_nm = h.substr (13); - - raw_help_from_docstrings_file (tmp_nm, h, symbol_found); - } - - return h; -} - -DEFUN (built_in_docstrings_file, args, nargout, - doc: /* -*- texinfo -*- -@deftypefn {} {@var{val} =} built_in_docstrings_file () -@deftypefnx {} {@var{old_val} =} built_in_docstrings_file (@var{new_val}) -@deftypefnx {} {} built_in_docstrings_file (@var{new_val}, "local") -Query or set the internal variable that specifies the name of the -file containing docstrings for built-in Octave functions. - -The default value is -@file{@var{octave-home}/share/octave/@var{version}/etc/built-in-docstrings}, -in which @var{octave-home} is the root directory of the Octave installation, -and @var{version} is the Octave version number. The default value may be -overridden by the environment variable -@w{@env{OCTAVE_BUILT_IN_DOCSTRINGS_FILE}}, or the command line argument -@option{--built-in-docstrings-file FNAME}. - -Note: This variable is only used when Octave is initializing itself. -Modifying it during a running session of Octave will have no effect. -@end deftypefn */) -{ - return SET_NONEMPTY_INTERNAL_STRING_VARIABLE (built_in_docstrings_file); -} - -static void -do_get_help_text (const std::string& name, std::string& text, - std::string& format) -{ - bool symbol_found = false; - text = raw_help (name, symbol_found); - - format = "Not found"; - if (symbol_found) - { - size_t idx = -1; - if (text.empty ()) - { - format = "Not documented"; - } - else if (looks_like_texinfo (text, idx)) - { - format = "texinfo"; - text.erase (0, idx); - } - else if (looks_like_html (text)) - { - format = "html"; - } - else - { - format = "plain text"; - } - } -} - -DEFUN (get_help_text, args, , - doc: /* -*- texinfo -*- +DEFMETHOD (get_help_text, interp, args, , + doc: /* -*- texinfo -*- @deftypefn {} {[@var{text}, @var{format}] =} get_help_text (@var{name}) Return the raw help text of function @var{name}. @@ -543,49 +736,17 @@ const std::string name = args(0).xstring_value ("get_help_text: NAME must be a string"); + octave::help_system& help_sys = interp.get_help_system (); + std::string text, format; - do_get_help_text (name, text, format); + help_sys.get_help_text (name, text, format); return ovl (text, format); } -static void -do_get_help_text_from_file (const std::string& fname, std::string& text, - std::string& format) -{ - bool symbol_found = false; - - std::string f; - - raw_help_from_file (fname, text, f, symbol_found); - - format = "Not found"; - if (symbol_found) - { - size_t idx = -1; - if (text.empty ()) - { - format = "Not documented"; - } - else if (looks_like_texinfo (text, idx)) - { - format = "texinfo"; - text.erase (0, idx); - } - else if (looks_like_html (text)) - { - format = "html"; - } - else - { - format = "plain text"; - } - } -} - -DEFUN (get_help_text_from_file, args, , - doc: /* -*- texinfo -*- +DEFMETHOD (get_help_text_from_file, interp, args, , + doc: /* -*- texinfo -*- @deftypefn {} {[@var{text}, @var{format}] =} get_help_text_from_file (@var{fname}) Return the raw help text from the file @var{fname}. @@ -600,9 +761,11 @@ const std::string fname = args(0).xstring_value ("get_help_text_from_file: NAME must be a string"); + octave::help_system& help_sys = interp.get_help_system (); + std::string text, format; - do_get_help_text_from_file (fname, text, format); + help_sys.get_help_text_from_file (fname, text, format); return ovl (text, format); } @@ -708,87 +871,14 @@ %! end_unwind_protect */ -static std::string -do_which (const std::string& name, std::string& type) -{ - std::string file; - - type = ""; - - octave::symbol_table& symtab = octave::__get_symbol_table__ ("do_which"); - - octave_value val = symtab.find_function (name); - - if (name.find_first_of ('.') == std::string::npos) - { - if (val.is_defined ()) - { - octave_function *fcn = val.function_value (); - - if (fcn) - { - file = fcn->fcn_file_name (); - - if (file.empty ()) - { - if (fcn->is_user_function ()) - type = "command-line function"; - else - { - file = fcn->src_file_name (); - type = "built-in function"; - } - } - else - type = val.is_user_script () - ? std::string ("script") : std::string ("function"); - } - } - else - { - // We might find a file that contains only a doc string. - - octave::load_path& lp = octave::__get_load_path__ ("do_which"); - - file = lp.find_fcn_file (name); - } - } - else - { - // File query. - - octave::load_path& lp = octave::__get_load_path__ ("do_which"); - - // For compatibility: "file." queries "file". - if (name.size () > 1 && name[name.size () - 1] == '.') - file = lp.find_file (name.substr (0, name.size () - 1)); - else - file = lp.find_file (name); - - file = octave::sys::env::make_absolute (file); - } - - return file; -} - -std::string -do_which (const std::string& name) -{ - std::string retval; - - std::string type; - - retval = do_which (name, type); - - return retval; -} - -DEFUN (__which__, args, , - doc: /* -*- texinfo -*- +DEFMETHOD (__which__, interp, args, , + doc: /* -*- texinfo -*- @deftypefn {} {} __which__ (@var{name}, @dots{}) Undocumented internal function. @end deftypefn */) { + octave::help_system& help_sys = interp.get_help_system (); + string_vector argv = args.make_argv (); int nargin = argv.numel (); @@ -805,7 +895,7 @@ std::string type; - std::string file = do_which (name, type); + std::string file = help_sys.which (name, type); names(i) = name; files(i) = file; @@ -819,34 +909,12 @@ return ovl (m); } -// FIXME: Are we sure this function always does the right thing? -inline bool -file_is_in_dir (const std::string filename, const std::string dir) -{ - if (filename.find (dir) == 0) - { - const int dir_len = dir.size (); - const int filename_len = filename.size (); - const int max_allowed_seps = - (octave::sys::file_ops::is_dir_sep (dir[dir_len-1]) ? 0 : 1); - - int num_seps = 0; - for (int i = dir_len; i < filename_len; i++) - if (octave::sys::file_ops::is_dir_sep (filename[i])) - num_seps++; - - return (num_seps <= max_allowed_seps); - } - else - return false; -} - // Return a cell array of strings containing the names of all // functions available in DIRECTORY. If no directory is given, search // the current path. -DEFUN (__list_functions__, args, , - doc: /* -*- texinfo -*- +DEFMETHOD (__list_functions__, interp, args, , + doc: /* -*- texinfo -*- @deftypefn {} {@var{retval} =} __list_functions__ () @deftypefnx {} {@var{retval} =} __list_functions__ (@var{directory}) Return a list of all functions (.m and .oct functions) in the load path. @@ -858,7 +926,7 @@ { octave_value retval; - octave::load_path& lp = octave::__get_load_path__ ("__list_functions__"); + octave::load_path& lp = interp.get_load_path (); if (args.length () == 0) { @@ -884,8 +952,33 @@ return retval; } -DEFUN (doc_cache_file, args, nargout, - doc: /* -*- texinfo -*- +DEFMETHOD (built_in_docstrings_file, interp, args, nargout, + doc: /* -*- texinfo -*- +@deftypefn {} {@var{val} =} built_in_docstrings_file () +@deftypefnx {} {@var{old_val} =} built_in_docstrings_file (@var{new_val}) +@deftypefnx {} {} built_in_docstrings_file (@var{new_val}, "local") +Query or set the internal variable that specifies the name of the +file containing docstrings for built-in Octave functions. + +The default value is +@file{@var{octave-home}/share/octave/@var{version}/etc/built-in-docstrings}, +in which @var{octave-home} is the root directory of the Octave installation, +and @var{version} is the Octave version number. The default value may be +overridden by the environment variable +@w{@env{OCTAVE_BUILT_IN_DOCSTRINGS_FILE}}, or the command line argument +@option{--built-in-docstrings-file FNAME}. + +Note: This variable is only used when Octave is initializing itself. +Modifying it during a running session of Octave will have no effect. +@end deftypefn */) +{ + octave::help_system& help_sys = interp.get_help_system (); + + return help_sys.built_in_docstrings_file (args, nargout); +} + +DEFMETHOD (doc_cache_file, interp, args, nargout, + doc: /* -*- texinfo -*- @deftypefn {} {@var{val} =} doc_cache_file () @deftypefnx {} {@var{old_val} =} doc_cache_file (@var{new_val}) @deftypefnx {} {} doc_cache_file (@var{new_val}, "local") @@ -908,11 +1001,108 @@ @seealso{lookfor} @end deftypefn */) { - return SET_NONEMPTY_INTERNAL_STRING_VARIABLE (doc_cache_file); + octave::help_system& help_sys = interp.get_help_system (); + + return help_sys.doc_cache_file (args, nargout); +} + +DEFMETHOD (info_file, interp, args, nargout, + doc: /* -*- texinfo -*- +@deftypefn {} {@var{val} =} info_file () +@deftypefnx {} {@var{old_val} =} info_file (@var{new_val}) +@deftypefnx {} {} info_file (@var{new_val}, "local") +Query or set the internal variable that specifies the name of the +Octave info file. + +The default value is +@file{@var{octave-home}/info/octave.info}, in +which @var{octave-home} is the root directory of the Octave installation. +The default value may be overridden by the environment variable +@w{@env{OCTAVE_INFO_FILE}}, or the command line argument +@option{--info-file FNAME}. + +When called from inside a function with the @qcode{"local"} option, the +variable is changed locally for the function and any subroutines it calls. +The original variable value is restored when exiting the function. +@seealso{info_program, doc, help, makeinfo_program} +@end deftypefn */) +{ + octave::help_system& help_sys = interp.get_help_system (); + + return help_sys.info_file (args, nargout); } -DEFUN (texi_macros_file, args, nargout, - doc: /* -*- texinfo -*- +DEFMETHOD (info_program, interp, args, nargout, + doc: /* -*- texinfo -*- +@deftypefn {} {@var{val} =} info_program () +@deftypefnx {} {@var{old_val} =} info_program (@var{new_val}) +@deftypefnx {} {} info_program (@var{new_val}, "local") +Query or set the internal variable that specifies the name of the +info program to run. + +The default value is +@file{@var{octave-home}/libexec/octave/@var{version}/exec/@var{arch}/info} +in which @var{octave-home} is the root directory of the Octave installation, +@var{version} is the Octave version number, and @var{arch} is the system +type (for example, @code{i686-pc-linux-gnu}). The default value may be +overridden by the environment variable +@w{@env{OCTAVE_INFO_PROGRAM}}, or the command line argument +@option{--info-program NAME}. + +When called from inside a function with the @qcode{"local"} option, the +variable is changed locally for the function and any subroutines it calls. +The original variable value is restored when exiting the function. +@seealso{info_file, doc, help, makeinfo_program} +@end deftypefn */) +{ + octave::help_system& help_sys = interp.get_help_system (); + + return help_sys.info_program (args, nargout); +} + +DEFMETHOD (makeinfo_program, interp, args, nargout, + doc: /* -*- texinfo -*- +@deftypefn {} {@var{val} =} makeinfo_program () +@deftypefnx {} {@var{old_val} =} makeinfo_program (@var{new_val}) +@deftypefnx {} {} makeinfo_program (@var{new_val}, "local") +Query or set the internal variable that specifies the name of the +program that Octave runs to format help text containing +Texinfo markup commands. + +The default value is @code{makeinfo}. + +When called from inside a function with the @qcode{"local"} option, the +variable is changed locally for the function and any subroutines it calls. +The original variable value is restored when exiting the function. +@seealso{texi_macros_file, info_file, info_program, doc, help} +@end deftypefn */) +{ + octave::help_system& help_sys = interp.get_help_system (); + + return help_sys.makeinfo_program (args, nargout); +} + +DEFMETHOD (suppress_verbose_help_message, interp, args, nargout, + doc: /* -*- texinfo -*- +@deftypefn {} {@var{val} =} suppress_verbose_help_message () +@deftypefnx {} {@var{old_val} =} suppress_verbose_help_message (@var{new_val}) +@deftypefnx {} {} suppress_verbose_help_message (@var{new_val}, "local") +Query or set the internal variable that controls whether Octave +will add additional help information to the end of the output from +the @code{help} command and usage messages for built-in commands. + +When called from inside a function with the @qcode{"local"} option, the +variable is changed locally for the function and any subroutines it calls. +The original variable value is restored when exiting the function. +@end deftypefn */) +{ + octave::help_system& help_sys = interp.get_help_system (); + + return help_sys.suppress_verbose_help_message (args, nargout); +} + +DEFMETHOD (texi_macros_file, interp, args, nargout, + doc: /* -*- texinfo -*- @deftypefn {} {@var{val} =} texi_macros_file () @deftypefnx {} {@var{old_val} =} texi_macros_file (@var{new_val}) @deftypefnx {} {} texi_macros_file (@var{new_val}, "local") @@ -934,92 +1124,7 @@ @seealso{makeinfo_program} @end deftypefn */) { - return SET_NONEMPTY_INTERNAL_STRING_VARIABLE (texi_macros_file); -} - -DEFUN (info_file, args, nargout, - doc: /* -*- texinfo -*- -@deftypefn {} {@var{val} =} info_file () -@deftypefnx {} {@var{old_val} =} info_file (@var{new_val}) -@deftypefnx {} {} info_file (@var{new_val}, "local") -Query or set the internal variable that specifies the name of the -Octave info file. - -The default value is -@file{@var{octave-home}/info/octave.info}, in -which @var{octave-home} is the root directory of the Octave installation. -The default value may be overridden by the environment variable -@w{@env{OCTAVE_INFO_FILE}}, or the command line argument -@option{--info-file FNAME}. - -When called from inside a function with the @qcode{"local"} option, the -variable is changed locally for the function and any subroutines it calls. -The original variable value is restored when exiting the function. -@seealso{info_program, doc, help, makeinfo_program} -@end deftypefn */) -{ - return SET_NONEMPTY_INTERNAL_STRING_VARIABLE (info_file); -} - -DEFUN (info_program, args, nargout, - doc: /* -*- texinfo -*- -@deftypefn {} {@var{val} =} info_program () -@deftypefnx {} {@var{old_val} =} info_program (@var{new_val}) -@deftypefnx {} {} info_program (@var{new_val}, "local") -Query or set the internal variable that specifies the name of the -info program to run. - -The default value is -@file{@var{octave-home}/libexec/octave/@var{version}/exec/@var{arch}/info} -in which @var{octave-home} is the root directory of the Octave installation, -@var{version} is the Octave version number, and @var{arch} is the system -type (for example, @code{i686-pc-linux-gnu}). The default value may be -overridden by the environment variable -@w{@env{OCTAVE_INFO_PROGRAM}}, or the command line argument -@option{--info-program NAME}. + octave::help_system& help_sys = interp.get_help_system (); -When called from inside a function with the @qcode{"local"} option, the -variable is changed locally for the function and any subroutines it calls. -The original variable value is restored when exiting the function. -@seealso{info_file, doc, help, makeinfo_program} -@end deftypefn */) -{ - return SET_NONEMPTY_INTERNAL_STRING_VARIABLE (info_program); + return help_sys.texi_macros_file (args, nargout); } - -DEFUN (makeinfo_program, args, nargout, - doc: /* -*- texinfo -*- -@deftypefn {} {@var{val} =} makeinfo_program () -@deftypefnx {} {@var{old_val} =} makeinfo_program (@var{new_val}) -@deftypefnx {} {} makeinfo_program (@var{new_val}, "local") -Query or set the internal variable that specifies the name of the -program that Octave runs to format help text containing -Texinfo markup commands. - -The default value is @code{makeinfo}. - -When called from inside a function with the @qcode{"local"} option, the -variable is changed locally for the function and any subroutines it calls. -The original variable value is restored when exiting the function. -@seealso{texi_macros_file, info_file, info_program, doc, help} -@end deftypefn */) -{ - return SET_NONEMPTY_INTERNAL_STRING_VARIABLE (makeinfo_program); -} - -DEFUN (suppress_verbose_help_message, args, nargout, - doc: /* -*- texinfo -*- -@deftypefn {} {@var{val} =} suppress_verbose_help_message () -@deftypefnx {} {@var{old_val} =} suppress_verbose_help_message (@var{new_val}) -@deftypefnx {} {} suppress_verbose_help_message (@var{new_val}, "local") -Query or set the internal variable that controls whether Octave -will add additional help information to the end of the output from -the @code{help} command and usage messages for built-in commands. - -When called from inside a function with the @qcode{"local"} option, the -variable is changed locally for the function and any subroutines it calls. -The original variable value is restored when exiting the function. -@end deftypefn */) -{ - return SET_INTERNAL_VARIABLE (suppress_verbose_help_message); -}