1########################################################################
2##
3## Copyright (C) 2009-2021 The Octave Project Developers
4##
5## See the file COPYRIGHT.md in the top-level directory of this
6## distribution or <https://octave.org/copyright/>.
7##
8## This file is part of Octave.
9##
10## Octave is free software: you can redistribute it and/or modify it
11## under the terms of the GNU General Public License as published by
12## the Free Software Foundation, either version 3 of the License, or
13## (at your option) any later version.
14##
15## Octave is distributed in the hope that it will be useful, but
16## WITHOUT ANY WARRANTY; without even the implied warranty of
17## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18## GNU General Public License for more details.
19##
20## You should have received a copy of the GNU General Public License
21## along with Octave; see the file COPYING.  If not, see
22## <https://www.gnu.org/licenses/>.
23##
24########################################################################
25
26## -*- texinfo -*-
27## @deftypefn {} {} which name @dots{}
28## Display the type of each @var{name}.
29##
30## If @var{name} is defined from a function file, the full name of the file is
31## also displayed.
32## @seealso{help, lookfor}
33## @end deftypefn
34
35function varargout = which (varargin)
36
37  if (nargin == 0 || ! iscellstr (varargin))
38    print_usage ();
39  endif
40
41  m = __which__ (varargin{:});
42
43  ## Check whether each name is a variable, variables take precedence over
44  ## functions in name resolution.
45  for i = 1:nargin
46    m(i).is_variable = evalin ("caller",
47                               ['exist ("' undo_string_escapes(m(i).name) '", "var")'], "");
48    if (m(i).is_variable)
49      m(i).file = "variable";
50    endif
51  endfor
52
53  if (nargout == 0)
54    for i = 1:nargin
55      if (m(i).is_variable)
56        printf ("'%s' is a variable\n", m(i).name);
57      elseif (isempty (m(i).file))
58        if (! isempty (m(i).type))
59          printf ("'%s' is a %s\n",
60                  m(i).name, m(i).type);
61        endif
62      else
63        if (isempty (m(i).type))
64          if (isfolder (m(i).file))
65            printf ("'%s' is the directory %s\n",
66                    m(i).name, m(i).file);
67          else
68            printf ("'%s' is the file %s\n",
69                    m(i).name, m(i).file);
70          endif
71        else
72          printf ("'%s' is a %s from the file %s\n",
73                  m(i).name, m(i).type, m(i).file);
74        endif
75      endif
76    endfor
77  else
78    varargout = {m.file};
79    ## Return type, instead of "", for built-in classes (bug #50541).
80    ## FIXME: remove code if __which__ is updated to return path for classes
81    idx = find (cellfun ("isempty", varargout));
82    if (idx)
83      varargout(idx) = m(idx).type;
84    endif
85  endif
86
87endfunction
88
89
90%!test
91%! str = which ("ls");
92%! assert (str(end-17:end), fullfile ("miscellaneous", "ls.m"));
93%!test
94%! str = which ("fftw");
95%! assert (str(end-7:end), "fftw.oct");
96%!test
97%! str = which ("inputParser");
98%! assert (str, "built-in function");
99%!test
100%! x = 3;
101%! str = which ("x");
102%! assert (str, "variable");
103
104%!assert (which ("__NO_SUCH_NAME__"), "")
105
106%!test
107%! str = which ("fftw");
108%! assert (str(end-7:end), "fftw.oct");
109%! fftw = 12;
110%! str = which ("fftw");
111%! assert (str, "variable");
112%! clear fftw;
113%! str = which ("fftw");
114%! assert (str(end-7:end), "fftw.oct");
115
116%!error which ()
117%!error which (1)
118
119