# HG changeset patch
# User Pantxo Diribarne <pantxo.diribarne@gmail.com>
# Date 1392118804 -3600
# Node ID 3e73456297359eecf1db9fd78164a9242729766a
# Parent  b0aba84cf80fb3958d696ee8e685059aeaf3c32c
Allow which to find variables (bug #37320)

* which.m removed
* __which__ (help.cc): rename "which", add nargout DEFUN argument and do the job of which.m
* do_which (help.cc): return "type = variable" when the symbol is a constant, a variable or a function variable (handle, inline, anonimous).
* move tests from which.m to help.cc and add one for the new behavior.

diff -r b0aba84cf80f -r 3e7345629735 libinterp/corefcn/help.cc
--- a/libinterp/corefcn/help.cc	Sat Feb 08 19:17:25 2014 -0500
+++ b/libinterp/corefcn/help.cc	Tue Feb 11 12:40:04 2014 +0100
@@ -1213,10 +1213,10 @@
 
   type = std::string ();
 
-  octave_value val = symbol_table::find_function (name);
-
   if (name.find_first_of ('.') == std::string::npos)
     {
+      octave_value val = symbol_table::find_function (name);
+
       if (val.is_defined ())
         {
           octave_function *fcn = val.function_value ();
@@ -1242,9 +1242,18 @@
         }
       else
         {
-          // We might find a file that contains only a doc string.
+          octave_value var = symbol_table::varval (name);
 
-          file = load_path::find_fcn_file (name);
+          if (var.is_constant () || var.is_object ()
+              || var.is_function_handle ()
+              || var.is_anonymous_function ()
+              || var.is_inline_function ())
+            {
+              type = "variable";
+            }
+          else
+            // We might find a file that contains only a doc string.
+            file = load_path::find_fcn_file (name);
         }
     }
   else
@@ -1276,13 +1285,18 @@
   return retval;
 }
 
-DEFUN (__which__, args, ,
+DEFUN (which, args, nargout,
        "-*- texinfo -*-\n\
-@deftypefn {Built-in Function} {} __which__ (@var{name}, @dots{})\n\
-Undocumented internal function.\n\
+@deftypefn {Built-in Function} {} which (@var{name}, @dots{})\n\
+@deftypefnx {Built-in Function} {[@var{file}, @dots{}] =} which (@var{name}, @dots{})\n\
+@deftypefnx {Command} {} which name @dots{}\n\
+Display the type of each @var{name} or return the file in which it \n\
+is defined. If @var{name} is defined from a\n\
+function file, the full name of the file is also displayed.\n\
+@seealso{help, lookfor, exist}\n\
 @end deftypefn")
 {
-  octave_value retval;
+  octave_value_list retval;
 
   string_vector argv = args.make_argv ("which");
 
@@ -1292,12 +1306,6 @@
 
       if (argc > 1)
         {
-          octave_map m (dim_vector (1, argc-1));
-
-          Cell names (1, argc-1);
-          Cell files (1, argc-1);
-          Cell types (1, argc-1);
-
           for (int i = 1; i < argc; i++)
             {
               std::string name = argv[i];
@@ -1306,16 +1314,32 @@
 
               std::string file = do_which (name, type);
 
-              names(i-1) = name;
-              files(i-1) = file;
-              types(i-1) = type;
+              if (nargout)
+                if (file.empty ())
+                  retval.append (type);
+                else                  
+                  retval.append (file);
+              else
+                {
+                  if (file.empty ())
+                    {
+                      if (! type.empty ())
+                        octave_stdout << "'" << name << "'" <<
+                          " is a " << type << std::endl;
+                    }
+                  else
+                    {
+                      if (type.empty ())
+                        octave_stdout << "'" << name << "'" <<
+                          " is the file " << file << std::endl;
+                      else
+                        octave_stdout << "'" << name << "'" <<
+                          " is a " << type << 
+                          " from the file " << file << std::endl;
+
+                    }
+                }
             }
-
-          m.assign ("name", names);
-          m.assign ("file", files);
-          m.assign ("type", types);
-
-          retval = m;
         }
       else
         print_usage ();
@@ -1323,6 +1347,26 @@
 
   return retval;
 }
+/*
+%!test
+%! str = which ("ls");
+%! assert (str(end-17:end), strcat ("miscellaneous", filesep (), "ls.m"));
+%!test
+%! str = which ("amd");
+%! assert (str(end-6:end), "amd.oct");
+%!test
+%! assert (which ("_NO_SUCH_NAME_"), "")
+%!test
+%! a = 1;
+%! b = @ishandle;
+%! c = @(x) x;
+%! d = inline ("x"); 
+%! [aa, bb, cc, dd] = which ("a", "b", "c", "d");
+%! assert (aa, "variable")
+%! assert (bb, "variable")
+%! assert (cc, "variable")
+%! assert (dd, "variable")
+*/
 
 // FIXME: Are we sure this function always does the right thing?
 inline bool
diff -r b0aba84cf80f -r 3e7345629735 scripts/help/which.m
--- a/scripts/help/which.m	Sat Feb 08 19:17:25 2014 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-## Copyright (C) 2009-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/>.
-
-## -*- texinfo -*-
-## @deftypefn {Command} {} which name @dots{}
-## Display the type of each @var{name}.  If @var{name} is defined from a
-## function file, the full name of the file is also displayed.
-## @seealso{help, lookfor}
-## @end deftypefn
-
-function varargout = which (varargin)
-
-  if (nargin > 0 && iscellstr (varargin))
-    m = __which__ (varargin{:});
-
-    if (nargout == 0)
-      for i = 1:nargin
-        if (isempty (m(i).file))
-          if (! isempty (m(i).type))
-            printf ("'%s' is a %s\n",
-                    m(i).name, m(i).type);
-          endif
-        else
-          if (isempty (m(i).type))
-            printf ("'%s' is the file %s\n",
-                    m(i).name, m(i).file);
-          else
-            printf ("'%s' is a %s from the file %s\n",
-                    m(i).name, m(i).type, m(i).file);
-          endif
-        endif
-      endfor
-    else
-      varargout = {m.file};
-    endif
-  else
-    print_usage ();
-  endif
-
-endfunction
-
-
-%!test
-%! str = which ("ls");
-%! assert (str(end-17:end), strcat ("miscellaneous", filesep (), "ls.m"));
-%!test
-%! str = which ("amd");
-%! assert (str(end-6:end), "amd.oct");
-
-%!assert (which ("_NO_SUCH_NAME_"), "")
-
