Mercurial > hg > octave-nkf
comparison scripts/help/type.m @ 17399:a1fa416c7c4a
type.m: Fix function for filenames without extension (bug #39922).
* scripts/help/type.m: Redo docstring to describe that 'type' works
on ordinary files and variables, as well as functions. Display
file even if name does not have an extension. Add more %!tests.
author | Rik <rik@octave.org> |
---|---|
date | Mon, 09 Sep 2013 20:20:14 -0700 |
parents | 1c89599167a6 |
children | fedcd3717ebc |
comparison
equal
deleted
inserted
replaced
17398:67c6fc2b9f63 | 17399:a1fa416c7c4a |
---|---|
17 ## <http://www.gnu.org/licenses/>. | 17 ## <http://www.gnu.org/licenses/>. |
18 | 18 |
19 ## -*- texinfo -*- | 19 ## -*- texinfo -*- |
20 ## @deftypefn {Command} {} type @var{name} @dots{} | 20 ## @deftypefn {Command} {} type @var{name} @dots{} |
21 ## @deftypefnx {Command} {} type -q @var{name} @dots{} | 21 ## @deftypefnx {Command} {} type -q @var{name} @dots{} |
22 ## @deftypefnx {Function File} {dfns =} type ("@var{name}", @dots{}) | 22 ## @deftypefnx {Function File} {text =} type ("@var{name}", @dots{}) |
23 ## Display the definition of each @var{name} that refers to a function. | 23 ## Display the contents of @var{name} which may be a file, function (m-file), |
24 ## variable, operator, or keyword. | |
24 ## | 25 ## |
25 ## Normally also displays whether each @var{name} is user-defined or built-in; | 26 ## @code{type} normally prepends a header line describing the category |
26 ## the @option{-q} option suppresses this behavior. | 27 ## of @var{name} such as function or variable; The @option{-q} option |
28 ## suppresses this behavior. | |
27 ## | 29 ## |
28 ## If an output argument is requested nothing is displayed. Instead, a cell | 30 ## If no output variable is used the contents are displayed on screen. |
29 ## array of strings is returned, where each element corresponds to the | 31 ## Otherwise, a cell array of strings is returned, where each element |
30 ## definition of each requested function. | 32 ## corresponds to the contents of each requested function. |
31 ## @end deftypefn | 33 ## @end deftypefn |
32 | 34 |
33 function retval = type (varargin) | 35 function text = type (varargin) |
34 ## Parse input | 36 |
35 if (nargin == 0) | 37 if (nargin == 0) |
36 error ("type: not enough input arguments"); | 38 print_usage (); |
37 endif | 39 elseif (! iscellstr (varargin)) |
38 | |
39 if (!iscellstr (varargin)) | |
40 error ("type: input arguments must be strings"); | 40 error ("type: input arguments must be strings"); |
41 endif | 41 endif |
42 | 42 |
43 quiet = false; | 43 quiet = false; |
44 idx = strcmpi (varargin, "-q") | strcmpi (varargin, "-quiet"); | 44 idx = strcmpi (varargin, "-q") | strcmpi (varargin, "-quiet"); |
45 if (any (idx)) | 45 if (any (idx)) |
46 quiet = true; | 46 quiet = true; |
47 varargin (idx) = []; | 47 varargin(idx) = []; |
48 endif | 48 endif |
49 | 49 |
50 if (nargout > 0) | 50 if (nargout > 0) |
51 retval = cell (size (varargin)); | 51 text = cell (size (varargin)); |
52 endif | 52 endif |
53 | 53 |
54 for n = 1:length (varargin) | 54 for n = 1:length (varargin) |
55 name = varargin {n}; | 55 name = varargin{n}; |
56 | 56 |
57 ## Find function and get its code | 57 ## Find function and get its code |
58 text = ""; | 58 txt = ""; |
59 cmd = sprintf ("exist ('%s')", name); | 59 cmd = sprintf ("exist ('%s')", name); |
60 e = evalin ("caller", cmd); | 60 e = evalin ("caller", cmd); |
61 if (e == 1) | 61 if (e == 1) |
62 ## Variable | 62 ## Variable |
63 cmd = sprintf ("disp (%s);", name); | 63 cmd = sprintf ("disp (%s);", name); |
64 desc = evalin ("caller", cmd); | 64 desc = evalin ("caller", cmd); |
65 if (quiet) | 65 if (quiet) |
66 text = desc; | 66 txt = desc; |
67 else | 67 else |
68 text = sprintf ("%s is a variable\n%s", name, desc); | 68 txt = sprintf ("%s is a variable\n%s", name, desc); |
69 endif | 69 endif |
70 elseif (e == 2) | 70 elseif (e == 2) |
71 ## m-file or ordinary file | 71 ## m-file or ordinary file |
72 file = which (name); | 72 file = which (name); |
73 if (isempty (file)) | 73 if (length (file) > 2) |
74 ext = file(end-1:end); | |
75 endif | |
76 if (isempty (file) || ! strcmpi (ext, ".m")) | |
74 ## 'name' is an ordinary file, and not a function name. | 77 ## 'name' is an ordinary file, and not a function name. |
75 ## FIXME: Should we just print it anyway? | 78 file = file_in_loadpath (name); |
76 error ("type: '%s' undefined\n", name); | 79 quiet = true; |
77 endif | 80 endif |
78 | 81 |
79 ## Read the file | 82 ## Read the file |
80 fid = fopen (file, "r"); | 83 fid = fopen (file, "r"); |
81 if (fid < 0) | 84 if (fid < 0) |
83 endif | 86 endif |
84 contents = char (fread (fid).'); | 87 contents = char (fread (fid).'); |
85 fclose (fid); | 88 fclose (fid); |
86 | 89 |
87 if (quiet) | 90 if (quiet) |
88 text = contents; | 91 txt = contents; |
89 else | 92 else |
90 text = sprintf ("%s is the user-defined function defined from: %s\n\n%s", | 93 txt = sprintf ("%s is the user-defined function defined from: %s\n\n%s", |
91 name, file, contents); | 94 name, file, contents); |
92 endif | 95 endif |
93 elseif (e == 3) | 96 elseif (e == 3) |
94 text = sprintf ("%s is a dynamically-linked function", name); | 97 txt = sprintf ("%s is a dynamically-linked function", name); |
95 elseif (e == 5) | 98 elseif (e == 5) |
96 text = sprintf ("%s is a built-in function", name); | 99 txt = sprintf ("%s is a built-in function", name); |
97 elseif (any (strcmp (__operators__ (), name))) | 100 elseif (any (strcmp (__operators__ (), name))) |
98 text = sprintf ("%s is an operator", name); | 101 txt = sprintf ("%s is an operator", name); |
99 elseif (any (strcmp (__keywords__ (), name))) | 102 elseif (any (strcmp (__keywords__ (), name))) |
100 text = sprintf ("%s is a keyword", name); | 103 txt = sprintf ("%s is a keyword", name); |
101 else | 104 else |
102 error ("type: '%s' undefined\n", name); | 105 error ("type: '%s' undefined\n", name); |
103 endif | 106 endif |
104 | 107 |
105 ## Should we return the text or print if | |
106 if (nargout == 0) | 108 if (nargout == 0) |
107 disp (text); | 109 disp (txt); |
108 else | 110 else |
109 retval {n} = text; | 111 text{n} = txt; |
110 endif | 112 endif |
111 endfor | 113 endfor |
112 endfunction | 114 endfunction |
113 | 115 |
114 | 116 |
115 %!test | 117 %!test |
116 %! var = 1; | 118 %! var = 1; |
117 %! typestr = type ("var"); | 119 %! text = type ("var"); |
118 %! typestr = typestr{1}(1:17); | 120 %! typestr = text{1}(1:17); |
119 %! assert (typestr, "var is a variable"); | 121 %! assert (typestr, "var is a variable"); |
122 | |
123 %!test | |
124 %! text = type ("ls"); | |
125 %! typestr = text{1}(1:31); | |
126 %! assert (typestr, "ls is the user-defined function"); | |
127 | |
128 %!test | |
129 %! text = type ("ls", "-q"); | |
130 %! typestr = text{1}(1:21); | |
131 %! assert (typestr, "## Copyright (C) 2006"); | |
120 | 132 |
121 %!assert (type ("amd"){1}, "amd is a dynamically-linked function") | 133 %!assert (type ("amd"){1}, "amd is a dynamically-linked function") |
122 %!assert (type ("cat"){1}, "cat is a built-in function") | 134 %!assert (type ("cat"){1}, "cat is a built-in function") |
123 %!assert (type ("+"){1}, "+ is an operator") | 135 %!assert (type ("+"){1}, "+ is an operator") |
124 %!assert (type ("end"){1}, "end is a keyword") | 136 %!assert (type ("end"){1}, "end is a keyword") |
125 %!error (type ('NO_NAME')) | 137 |
138 %!error type () | |
139 %!error <'__NO_NAME__' undefined> type ('__NO_NAME__') | |
126 | 140 |
127 |