time | Calls | line |
---|
| | 1 | function disp(t,bold,indent,fullChar,nestedLevel)
|
| | 2 | %DISP Display a table.
|
| | 3 | % DISP(T) prints the table T, including variable names and row names (if
|
| | 4 | % present), without printing the table name. In all other ways it's the
|
| | 5 | % same as leaving the semicolon off an expression.
|
| | 6 | %
|
| | 7 | % For numeric or categorical variables that are 2-dimensional and have 3 or
|
| | 8 | % fewer columns, DISP prints the actual data using either short g, long g,
|
| | 9 | % or bank format, depending on the current command line setting. Otherwise,
|
| | 10 | % DISP prints the size and type of each table element.
|
| | 11 | %
|
| | 12 | % For character variables that are 2-dimensional and 10 or fewer characters
|
| | 13 | % wide, DISP prints quoted strings. Otherwise, DISP prints the size and
|
| | 14 | % type of each table element.
|
| | 15 | %
|
| | 16 | % For cell variables that are 2-dimensional and have 3 or fewer columns,
|
| | 17 | % DISP prints the contents of each cell (or its size and type if too large).
|
| | 18 | % Otherwise, DISP prints the size of each tabble element.
|
| | 19 | %
|
| | 20 | % For other types of variables, DISP prints the size and type of each
|
| | 21 | % table element.
|
| | 22 | %
|
| | 23 | % See also TABLE, DISPLAY, FORMAT.
|
| | 24 |
|
| | 25 | % Copyright 2012-2019 The MathWorks, Inc.
|
| | 26 |
|
< 0.001 | 8 | 27 | if nargin < 2, bold = true; end
|
< 0.001 | 8 | 28 | if nargin < 3, indent = 4; end
|
< 0.001 | 8 | 29 | if nargin < 4, fullChar = false; end
|
< 0.001 | 8 | 30 | if nargin < 5, nestedLevel = 1; end
|
< 0.001 | 8 | 31 | between = 4;
|
< 0.001 | 8 | 32 | betweenColSpaces = 2;
|
< 0.001 | 8 | 33 | maxNumVarColsToDisp = 5;
|
< 0.001 | 8 | 34 | maxCharWidthToDisp = 10;
|
| | 35 |
|
| | 36 | % Follow the cmd window's format settings as possible
|
< 0.001 | 8 | 37 | isLoose = strcmp(matlab.internal.display.formatSpacing,'loose');
|
< 0.001 | 8 | 38 | if isLoose
|
< 0.001 | 8 | 39 | looseline = newline;
|
| | 40 | else
|
| | 41 | looseline = '';
|
< 0.001 | 8 | 42 | end
|
0.002 | 8 | 43 | [dblFmt,snglFmt] = getFloatFormats();
|
| | 44 |
|
0.001 | 8 | 45 | bold = matlab.internal.display.isHot() && bold;
|
< 0.001 | 8 | 46 | strongBegin = '';strongEnd = '';
|
< 0.001 | 8 | 47 | if bold
|
0.002 | 8 | 48 | strongBegin = getString(message('MATLAB:table:localizedStrings:StrongBegin'));
|
0.001 | 8 | 49 | strongEnd = getString(message('MATLAB:table:localizedStrings:StrongEnd'));
|
< 0.001 | 8 | 50 | end
|
| | 51 |
|
< 0.001 | 8 | 52 | lostWidth = zeros(t.rowDim.length,1);
|
0.001 | 8 | 53 | marginChars = nSpaces(indent);
|
0.001 | 8 | 54 | if (t.rowDim.length > 0) && (t.varDim.length > 0)
|
< 0.001 | 8 | 55 | if t.rowDim.hasLabels
|
0.003 | 8 | 56 | rownameChars = string(t.rowDim.textLabels());
|
< 0.001 | 8 | 57 | for i=1:t.rowDim.length
|
0.009 | 800 | 58 | rownameChars{i} = matlab.internal.display.truncateLine(rownameChars{i});
|
< 0.001 | 800 | 59 | end
|
0.016 | 8 | 60 | [rownameChars,rownameWidth,lostWidth] = alignTabularContents(rownameChars,lostWidth);
|
< 0.001 | 8 | 61 | if t.dispRowLabelsHeader
|
| | 62 | rowDimName = boldifyLabels(string(t.metaDim.labels{1}),bold,strongBegin,strongEnd);
|
| | 63 | rowDimNameWidth = ceil(vectorizedWrappedLength(rowDimName));
|
| | 64 | if rownameWidth < rowDimNameWidth
|
| | 65 | rownameChars = rownameChars + nSpaces(rowDimNameWidth-rownameWidth);
|
| | 66 | rownameWidth = rowDimNameWidth;
|
| | 67 | end
|
< 0.001 | 8 | 68 | end
|
0.005 | 8 | 69 | rownameChars = boldifyLabels(rownameChars,bold,strongBegin,strongEnd);
|
0.001 | 8 | 70 | marginChars = marginChars + rownameChars + nSpaces(between);
|
< 0.001 | 8 | 71 | end
|
| | 72 |
|
| | 73 | % Boldify variable names and figure out their wrapped length.
|
< 0.001 | 8 | 74 | varNames = string(t.varDim.labels);
|
| | 75 | % Replace LF with "knuckle" tab with "arrow", and CR with "backarrow".
|
| | 76 | % This also truncates long lines, but is irrelevant here.
|
| | 77 | % Replaces hyperlinks with no display text with ''.
|
< 0.001 | 8 | 78 | for iv = 1:numel(varNames)
|
0.002 | 56 | 79 | varNames(iv) = matlab.internal.display.truncateLine(varNames(iv),10000);
|
< 0.001 | 56 | 80 | end
|
< 0.001 | 8 | 81 | varNameOrigNumChars = strlength(varNames);
|
< 0.001 | 8 | 82 | varNameDispWidths = varNameOrigNumChars;
|
0.004 | 8 | 83 | [varNames, liesAboutWidth] = boldifyLabels(varNames,bold,strongBegin,strongEnd);
|
0.002 | 8 | 84 | for idx = 1:numel(varNames)
|
0.001 | 56 | 85 | liesAboutWidth(idx) = liesAboutWidth(idx) || any(varNames{idx} > char(128));
|
0.001 | 56 | 86 | end
|
0.002 | 8 | 87 | varNameDispWidths(liesAboutWidth) = vectorizedWrappedLength(varNames(liesAboutWidth));
|
< 0.001 | 8 | 88 | varNameDispWidths = ceil(varNameDispWidths);
|
| | 89 |
|
< 0.001 | 8 | 90 | varDispWidths = zeros(1,t.varDim.length);
|
0.001 | 8 | 91 | ulDispWidths = zeros(1,t.varDim.length);
|
0.001 | 8 | 92 | numNestedVars = zeros(1,t.varDim.length);
|
0.001 | 8 | 93 | nestedVarnameStrs = strings(1,t.varDim.length);
|
< 0.001 | 8 | 94 | haveNestedTable = false;
|
| | 95 |
|
0.001 | 8 | 96 | tblChars = strings(t.rowDim.length,t.varDim.length);
|
0.001 | 8 | 97 | for ivar = 1:t.varDim.length
|
0.001 | 56 | 98 | var = t.data{ivar};
|
0.001 | 56 | 99 | varname = varNames(ivar);
|
| | 100 |
|
< 0.001 | 56 | 101 | if ischar(var)
|
| | 102 | if ismatrix(var) && (fullChar || (size(var,2) <= maxCharWidthToDisp))
|
| | 103 | % Display individual strings for a char variable that is 2D and no
|
| | 104 | % more than 10 chars.
|
| | 105 | varStr = string(var);
|
| | 106 | else
|
| | 107 | % Otherwise, display a description of the chars.
|
| | 108 | varStr = getInfoDisplay(var);
|
| | 109 | end
|
| | 110 | [varStr,maxVarLen,lostWidth] = alignTabularContents(varStr,lostWidth);
|
< 0.001 | 56 | 111 | else
|
| | 112 | % Display the individual data if the var is 2D and no more than 5 columns.
|
< 0.001 | 56 | 113 | if ~isempty(var) && ismatrix(var) && (size(var,2) <= maxNumVarColsToDisp)
|
0.004 | 56 | 114 | if isnumeric(var) && ~isenum(var)
|
< 0.001 | 56 | 115 | if isa(var,'double')
|
0.029 | 56 | 116 | varChars = num2str(var,dblFmt);
|
| | 117 | elseif isfloat(var) % single, or fallback for any other floating point type
|
| | 118 | varChars = num2str(var,snglFmt);
|
| | 119 | elseif isa(var,'uint8') || isa(var,'uint16') || isa(var,'uint32') || isa(var,'uint64')
|
| | 120 | varChars = num2str(var,'%u ');
|
| | 121 | elseif isinteger(var) % standard signed integers, or fallback for any other integer type
|
| | 122 | varChars = num2str(var,'%d ');
|
| | 123 | else % fallback for anything numeric that fails isfloat or isinteger
|
| | 124 | varChars = num2str(var);
|
< 0.001 | 56 | 125 | end
|
0.002 | 56 | 126 | varStr = string(varChars);
|
0.002 | 56 | 127 | maxVarLen = max(strlength(varStr));
|
| | 128 | elseif islogical(var)
|
| | 129 | % Display the logical values using meaningful names.
|
| | 130 | tf = ["false" "true "];
|
| | 131 | s = reshape(tf(1+var),size(var));
|
| | 132 | varStr = s.join(nSpaces(betweenColSpaces),2);
|
| | 133 | maxVarLen = max(strlength(varStr));
|
| | 134 | elseif isa(var,'categorical') || isa(var,'datetime') || isa(var,'duration') || isa(var,'calendarDuration')
|
| | 135 | if isa(var,'categorical')
|
| | 136 | checkChars = categories(var);
|
| | 137 | padSide = 'right';
|
| | 138 | else
|
| | 139 | checkChars = {var.Format};
|
| | 140 | padSide = 'left';
|
| | 141 | end
|
| | 142 |
|
| | 143 | % Convert values to a string array. String is a data
|
| | 144 | % conversion, so missing values need to be handled
|
| | 145 | % specially.
|
| | 146 | varStr = string(var);
|
| | 147 | miss = var(1); miss(1) = missing; miss = char(miss);
|
| | 148 | varStr(ismissing(varStr)) = miss;
|
| | 149 |
|
| | 150 | tagged = containsRegexp(checkChars,'<a\s+href\s*=|<strong>');
|
| | 151 | if any(any(char(checkChars) > 127)) || any(tagged(:))
|
| | 152 | % Align the var data display accounting for wide chars
|
| | 153 | % or markup in a category name or a date/time format.
|
| | 154 | [varStr, ~, ~] = alignTabularContents(varStr);
|
| | 155 | varStr = varStr.join(nSpaces(betweenColSpaces),2);
|
| | 156 | [varStr,maxVarLen,lostWidth] = alignTabularContents(varStr,lostWidth);
|
| | 157 | else
|
| | 158 | % Otherwise, no wide chars or markup, just pad to equal
|
| | 159 | % number of chars.
|
| | 160 | varStr = pad(varStr,padSide,' ');
|
| | 161 | varStr = varStr.join(nSpaces(betweenColSpaces),2);
|
| | 162 | maxVarLen = max(strlength(varStr));
|
| | 163 | end
|
| | 164 | elseif isstring(var)
|
| | 165 | if isscalar(var) && ~ismissing(var)
|
| | 166 | % Scalar string displays specially, which is not what we
|
| | 167 | % want inside a table. Truncate long text, replace LF
|
| | 168 | % with "knuckle", tab with "arrow", and CR with "backarrow".
|
| | 169 | var = matlab.internal.display.truncateLine(var{1},10000);
|
| | 170 | % Scalar strings display without quotes, add them to the
|
| | 171 | % string itself.
|
| | 172 | var = '"' + string(var) + '"';
|
| | 173 | end
|
| | 174 | varStr = getStrOutput(var);
|
| | 175 | [varStr,maxVarLen,lostWidth] = alignTabularContents(varStr,lostWidth);
|
| | 176 | elseif iscell(var)
|
| | 177 | if isscalar(var) && ischar(var{1}) && ~isempty(var{1})
|
| | 178 | % One-row char displays specially, which is not what we
|
| | 179 | % want inside a table. Truncate long text, replace LF with
|
| | 180 | % "knuckle", tab with "arrow", and CR with "backarrow".
|
| | 181 | % But avoid truncateLine on empty char; it turns 1x0 into
|
| | 182 | % '', a 0x0.
|
| | 183 | var = {matlab.internal.display.truncateLine(var{1},10000)};
|
| | 184 | end
|
| | 185 | varStr = getStrOutput(var);
|
| | 186 | [varStr,maxVarLen,lostWidth] = alignTabularContents(varStr,lostWidth);
|
| | 187 | elseif isenum(var)
|
| | 188 | % Convert enum values to strings. value names don't contain
|
| | 189 | % wide chars or markup, just pad to equal number of chars.
|
| | 190 | varStr = pad(getStrOutput(var),' ');
|
| | 191 | maxVarLen = max(strlength(varStr));
|
| | 192 | elseif isa(var,'tabular') && (nestedLevel == 1)
|
| | 193 | haveNestedTable = true;
|
| | 194 | % Get the nested table's disp, bold per caller, no indent, and
|
| | 195 | % whatever char disp setting our caller gave us. Tell the nested
|
| | 196 | % table that it's one level deeper than we are.
|
| | 197 | varChars = evalc('disp(var,bold,0,fullChar,nestedLevel+1)');
|
| | 198 | assert(sum(varChars==newline) == t.rowDim.length+2+2*isLoose) % a table's disp should never have embedded newlines
|
| | 199 | varStr = splitlines(string(varChars));
|
| | 200 |
|
| | 201 | % Save the first line of the nested table's display, that's
|
| | 202 | % its var names, then chop off the first two lines and any
|
| | 203 | % trailing blank lines, leaving just the data display.
|
| | 204 | nestedVarnameStrs(ivar) = varStr(1);
|
| | 205 | numNestedVars(ivar) = var.varDim.length + (var.rowDim.hasLabels && var.dispRowLabelsHeader);
|
| | 206 | varStr(1:2) = [];
|
| | 207 | varStr(varStr == "") = [];
|
| | 208 |
|
| | 209 | % Find the maximum width of the nested table's data display.
|
| | 210 | % This accounts for any wide chars in the nested table's
|
| | 211 | % data or row names. It does not explicitly account for the
|
| | 212 | % width of the nested table's var names, which will become
|
| | 213 | % an extra header line for the outer table. But tabular/disp
|
| | 214 | % creates (approx) equal-length lines of text for the nested
|
| | 215 | % table, including its var names header line, so their width
|
| | 216 | % need not be accounted for separately.
|
| | 217 | [varStr,maxVarLen,lostWidth] = alignTabularContents(varStr,lostWidth);
|
| | 218 | else
|
| | 219 | % Display a description of each table element.
|
| | 220 | varStr = getInfoDisplay(var);
|
| | 221 | maxVarLen = max(strlength(varStr));
|
< 0.001 | 56 | 222 | end
|
| | 223 |
|
| | 224 | % Either the variable is not 2D, or it's empty, or it's too wide
|
| | 225 | % to show. Display a description of each table element.
|
| | 226 | else
|
| | 227 | varStr = getInfoDisplay(var);
|
| | 228 | maxVarLen = max(strlength(varStr));
|
< 0.001 | 56 | 229 | end
|
< 0.001 | 56 | 230 | end
|
| | 231 |
|
< 0.001 | 56 | 232 | if maxVarLen < varNameDispWidths(ivar)
|
| | 233 | % If the var name is wider than the var's data display, pad the
|
| | 234 | % latter with spaces to center the data under the varname. Need to
|
| | 235 | % do this explicitly, because while each line has (approx) the same
|
| | 236 | % display width, they may have different numbers of chars due to wide
|
| | 237 | % chars and markup, and pad requires a common target width.
|
| | 238 | varDataPad = varNameDispWidths(ivar) - maxVarLen;
|
| | 239 | numRightSpaces = ceil(varDataPad/2);
|
| | 240 | numLeftSpaces = varDataPad - numRightSpaces;
|
| | 241 | varStr = nSpaces(numLeftSpaces) + varStr + nSpaces(numRightSpaces);
|
| | 242 | maxVarLen = varNameDispWidths(ivar);
|
< 0.001 | 56 | 243 | end
|
< 0.001 | 56 | 244 | varDispWidths(ivar) = maxVarLen;
|
< 0.001 | 56 | 245 | ulDispWidths(ivar) = maxVarLen;
|
| | 246 |
|
| | 247 |
|
< 0.001 | 56 | 248 | tblChars(:,ivar) = varStr;
|
< 0.001 | 56 | 249 | end
|
0.009 | 8 | 250 | [varChars,nestedVarChars,underlines] = getVarNamesDispLines();
|
< 0.001 | 8 | 251 | disp(char(varChars));
|
< 0.001 | 8 | 252 | if haveNestedTable, disp(char(nestedVarChars)); end
|
0.020 | 8 | 253 | disp(char(underlines));
|
0.002 | 8 | 254 | tblChars = marginChars + tblChars.join(' ',2);
|
< 0.001 | 8 | 255 | for row = 1:t.rowDim.length
|
0.009 | 800 | 256 | disp(char(tblChars(row,:)));
|
< 0.001 | 800 | 257 | end
|
< 0.001 | 8 | 258 | fprintf(looseline);
|
< 0.001 | 8 | 259 | end
|
| | 260 |
|
| | 261 | %-----------------------------------------------------------------------
|
| | 262 | function [varnames,nestedVarnames,underlines] = getVarNamesDispLines()
|
| | 263 |
|
| | 264 | varStrs = strings(1,t.varDim.length);
|
| | 265 | ulStrs = strings(1,t.varDim.length);
|
| | 266 | if haveNestedTable, nestedVarnameDispWidths = ceil(vectorizedWrappedLength(nestedVarnameStrs)); end
|
| | 267 |
|
| | 268 | for ii = 1:t.varDim.length
|
| | 269 | varname = varNames(ii);
|
| | 270 | % Use the wider of varDispWidth and varNamesDispWidth to
|
| | 271 | % determine the header width and pad to the varDispWidth if
|
| | 272 | % necessary. However, when padding, this number has to be
|
| | 273 | % adjusted to account for the fact that the number of
|
| | 274 | % characters in the char vector for the varname do not
|
| | 275 | % correspond to the display width, due to:
|
| | 276 | % * Strong tags
|
| | 277 | % * Hyperlinks (and thus no strong tags)
|
| | 278 | % * Wide characters
|
| | 279 | % * Narrow characters or wide-displaying characters that don't
|
| | 280 | % report to be wide (nothing to be done about those).
|
| | 281 |
|
| | 282 | % Pad out variable names if necessary to match the data display
|
| | 283 | % width. Varnames have already been made bold.
|
| | 284 | varnameNumCharsToDisp = strlength(varname) + (varDispWidths(ii) - varNameDispWidths(ii));
|
| | 285 | varStrs(ii) = pad(varname, ... % wrap tightly with strong tags
|
| | 286 | varnameNumCharsToDisp,'both',' ');
|
| | 287 | if haveNestedTable
|
| | 288 | % Pad the nested var names out to the full data display width,
|
| | 289 | % accounting for bold markup tags around each nested name.
|
| | 290 | nestedVarnameStrs(ii) = pad(nestedVarnameStrs(ii), ...
|
| | 291 | strlength(nestedVarnameStrs(ii)) + (varDispWidths(ii) - nestedVarnameDispWidths(ii)),'both',' ');
|
| | 292 | end
|
| | 293 | % Create underlines under each variable name to the full data
|
| | 294 | % display width.
|
| | 295 | ulStrs(ii) = nUnder(ulDispWidths(ii));
|
| | 296 | end
|
| | 297 |
|
| | 298 | if t.dispRowLabelsHeader
|
| | 299 | % Need to print the name of the rowDim; add it to the beginning
|
| | 300 | % of the array
|
| | 301 | ulStrs = [nUnder(rownameWidth), ulStrs];
|
| | 302 | varStrs = [pad(rowDimName, ... % wrap tightly with strong tags
|
| | 303 | strlength(rowDimName) + (rownameWidth - rowDimNameWidth),'both',' '), varStrs];
|
| | 304 | nestedVarnameStrs = [nSpaces(rownameWidth), nestedVarnameStrs];
|
| | 305 | end
|
| | 306 |
|
| | 307 | % Join all the variable names and underlines with spaces.
|
| | 308 | spacesBetween = string(nSpaces(between));
|
| | 309 | if ~t.dispRowLabelsHeader && t.rowDim.hasLabels
|
| | 310 | % table doesn't print a header (dimname) for rownames, but we
|
| | 311 | % still have to account for the width with additional spaces.
|
| | 312 | leadingSpaces = nSpaces(indent + rownameWidth + between);
|
| | 313 | else
|
| | 314 | % timetables always wind up here, and tables without rownames
|
| | 315 | leadingSpaces = nSpaces(indent);
|
| | 316 | end
|
| | 317 |
|
| | 318 | varnames = leadingSpaces + join(varStrs,spacesBetween);
|
| | 319 | nestedVarnames = leadingSpaces + join(nestedVarnameStrs,spacesBetween);
|
| | 320 | underlines = leadingSpaces + join(strongBegin + ulStrs + strongEnd, spacesBetween) + looseline;
|
| | 321 | end
|
| | 322 |
|
< 0.001 | 8 | 323 | end % main function
|
Other subfunctions in this file are not included in this listing.