function [varargout] = message(varargin)
%
%MESSAGE Displays a message in the command window. This is an alternative
% to WARNING, avoiding the automatic text "Warning: ", and also
% allowing for more flexible formatting, based on FPRINTF.
%
%Usage:
%
% MESSAGE('MSG') is equivalent to FPRINTF(1,'MSG')
%
% MESSAGE('MSG', a1, a2, ...) is equivalent to FPRINTF(1,'MSG', a1, a2...)
%
%
%
% MESSAGE('ON') turns on MESSAGE (default). When MESSAGE is ON,
% messages can still be suppressed with DISABLE (see below).
%
% MESSAGE('OFF') suppresses all messages, regardless of ENABLE
% state of MSGID (see below).
%
% MESSAGE('CLEAR') clears all MESSAGE memory.
%
%
%
% MESSAGE('ENABLE', 'MSGID') enables messages with identifier MSGID. MSGID
% can be a string or a cell array of strings.
%
% MESSAGE('DISABLE', 'MSGID') suppresses messages with identifier MSGID.
% MSGID can be a string or a cell array of strings.
%
%
%
% MESSAGE('MSGID', 'MSG') allows for suppressing according to the enabled state
% of MSGID.
%
% [STATE,MSGID] = MESSAGE('QUERY') returns the current enabled states of all
% MSGIDs as well as the MSGID names in a cell array.
%
% [STATE,MSGID] = MESSAGE('QUERY', 'MSGID') returns the current enabled states
% of the user specified MSGIDs. If MSGID is cellstr, a vector indicating
% the states is returned.
%
%
%
%
%Examples:
%
% 1. >> message('Hello')
% Hello
%
% 2. >> message('Level 1','Hello') %behaves identically to FPRINTF
% Level 1
%
% 3. >> message('Level 1 %s','Hello')
% Level 1 Hello
%
% 4. >> message('enable',{'Level 1','Level 2'})
% >> message('Level 1','Hello')
% Hello
%
% 5. >> message('enable','Level 1')
% >> message('off')
% >> message('Level 1','Hello') %no output returned
% >> state = message('query','Level 1')
% state =
% 1
%
%Notes:
%1. MESSAGE stores a structural array called "message" as application data
% of the command window. Be careful when working with command window app data.
%
%2. All keywords are case insensitive.
% ('on' , 'off' , 'enable', 'disable', 'clear' , 'query')
%
%3. Note from Example 5 above that setting "message('off')" does not affect
%the enabled state of individual MSGIDs. This functionality allows the
%user to toggle ON and OFF without bookkeeping of the MSGID
%enabled states.
%
% 4. Note from Example 2 above that if a MSGID has not been defined, MESSAGE will
% behave exactly like FPRINTF, ignoring extra arguments if not specified in
% the first string argument, as shown in Example 3.
% See also WARNING, FPRINTF
%
%
%
%Author:
%
% Todd C Pataky (0todd0@gmail.com) 14-June-2006
%Programming notes:
%1. The app data stored in the command window is of the following format:
% message.on = 1;
% message.msgid = {'a','aaa','b','c'}
% message.enabled = [1 0 1 1];
%%%%%%%%%%%%%%%%
%PRELIMINARY ERROR CHECKS
%%%%%%%%%%%%%%%%
if nargin==0
error('No message or command.')
end
x1 = varargin{1};
if ~isstr(x1)
error('First input argument must be a string.')
end
if ~isequal(upper(x1),'QUERY') & (nargout > 0)
error('Too many output arguments. Output only given when using "QUERY".')
end
if nargout > 2
error('Too many output arguments. Maximum of 2 outputs allowed when using "QUERY".')
end
%%%%%%%%%%%%%%%%
%INITIALIZE MESSAGE STRUCTURE (if not yet initialized)
%%%%%%%%%%%%%%%%
M = getappdata(0,'message');
if isempty(M)
M.on = 1;
M.msgid = {};
M.enabled = [];
setappdata(0,'message',M);
end
%%%%%%%%%%%%%%%%
%1. ON / OFF
%%%%%%%%%%%%%%%%
if ismember(upper(x1),{'ON','OFF'})
if nargin>1
error('Too many input arguments. Only one argument permitted when using %s.',upper(x1))
end
state = strmatch(upper(x1),{'OFF','ON'}) - 1;
M.on = state;
setappdata(0,'message',M);
return
end
%%%%%%%%%%%%%%%%
%2. ENABLE / DISABLE
%%%%%%%%%%%%%%%%
if ismember(upper(x1),{'ENABLE','DISABLE'})
if nargin~=2
error('Must use 2 input arguments when using %s',upper(x1))
end
x2 = varargin{2};
if ~( isstr(x2) | iscellstr(x2) )
error('MSGID must be a string or a cell array of strings.')
end
if isstr(x2)
x2 = {x2};
end
x2=x2(:)';
state = strmatch(upper(x1),{'DISABLE','ENABLE'}) - 1;
%change state of MSGIDs that already exist
[ismem,ind] = ismember(x2,M.msgid);
ind = ind(ind>0);
M.enabled(ind) = state;
%add MSGIDs that do not yet exist
x2 = x2(~ismem);
M.msgid = [M.msgid x2];
M.enabled = [ M.enabled state*ones(1,length(x2)) ];
setappdata(0,'message',M);
return
end
%%%%%%%%%%%%%%%%
%3. CLEAR
%%%%%%%%%%%%%%%%
if isequal(upper(x1),'CLEAR')
if nargin==1
if isappdata(0,'message')
rmappdata(0,'message')
end
return
else error('Too many input arguments. No extra arguments permitted when using "CLEAR".')
end
end
%%%%%%%%%%%%%%%%
%4. QUERY
%%%%%%%%%%%%%%%%
if isequal(upper(x1),'QUERY')
if nargin==1
varargout{1} = M.enabled;
varargout{2} = M.msgid;
return
end
if nargin~=2
error('Must use two arguments when using "QUERY".')
end
x2 = varargin{2};
if ~( isstr(x2) | iscellstr(x2) )
error('MSGID must be a string or a cell array of strings.')
end
if isstr(x2)
x2 = {x2};
end
x2=x2(:)';
[found,ind] = ismember(x2,M.msgid);
if ~all(found)
f = find(ind==0);
error( 'QUERY error: MSGID "%s" not found' , x2{f(1)} );
end
varargout{1} = M.enabled(ind);
varargout{2} = M.msgid(ind);
return
end
%%%%%%%%%%%%%%%%
%5. MSGID as first argument
%%%%%%%%%%%%%%%%
if ~M.on
return
end
if ismember(x1,M.msgid)
if nargin == 1
error('MSGID: %s found. When MSGID is the first argumet, must include at least one additional argument.')
end
x2 = varargin{2};
if ~isstr(x2)
error('MSGID: %s found. When MSGID is the first argumet, a message string must be the second.')
end
[dmy,ind] = ismember(x1,M.msgid);
enabled = M.enabled(ind);
if enabled
if nargin > 2
p = varargin(3:end);
else p = [];
end
hereWriteMessage(x2,p) %see subfunction below
else return
end
return
end
%%%%%%%%%%%%%%%%
%6. MSG as first argument
%%%%%%%%%%%%%%%%
if nargin == 1
p = [];
else p = varargin(2:end);
end
hereWriteMessage(x1,p) %see subfunction below
function hereWriteMessage(s,P)
%
%Write the text s to the command window.
s2 = ',';
for k=1:length(P)
p = P{k};
if isnumeric(p)
if length(p)>1
error('Each paramater must have only one element.')
end
s2 = [s2,num2str(p),','];
elseif isstr(p)
s2 = [s2,char(39),p,char(39),','];
else error('Only numerics or strings may be submitted as parameters.')
end
end
s2 = s2(1:end-1);
eval(['fprintf(',char(39),s,char(39),s2,');']);