完成。
我会在FEX上发布这个内容,审核通过后,我会在这里放置一个链接。
编辑1 他们批准了我的提交,可以在这里或直接从我的GitHub中找到。 我将从这篇文章中删除代码。(实际上,我会留下它,因为那样会把答案变成仅有链接的回复,正如Andy Clifton所指出的那样。)
我只在R2010a上测试过这个内容,在那里它通过了所有的单元测试。但是经验表明,MATLAB可能会在不同版本之间做出非常不同的事情,所以如果您发现问题,得到奇怪的错误等,请告诉我,这样我就可以进行修复。
目前,这是1.0版本:
function varargout = toggleToolbox(varargin)
msgId = mfilename();
storefile = fullfile(fileparts(mfilename('fullpath')), ...
'toolbox_states.mat');
tb_name_map = get_tb_name_map();
restoremode = false;
querymode = false;
toolbox = 'all';
state = 'on';
permanent = 'temporary';
switch nargin
case 0
querymode = true;
case 1
if isstruct(varargin{1})
restoremode = true;
state = 'restore';
toolbox_states = varargin{1};
assert(nargout == 0,...
[msgId ':argoutcount_error'], ...
'%s for single input argument does not have any output arguments.',...
mfilename);
assert(isfield(toolbox_states, 'path') && ...
all(isfield(toolbox_states, tb_name_map(:,1))),...
[msgId ':invalid_tbstates_structure'], ...
'Input argument does not appear to be a structure generated by %s.',...
mfilename);
elseif ischar(varargin{1})
if strcmpi(varargin{1}, 'names')
varargout{1} = tb_name_map;
return;
else
querymode = true;
toolbox = varargin{1};
state = 'query';
end
end
case 2
toolbox = varargin{1};
state = varargin{2};
querymode = strcmpi(state, 'query');
case 3
toolbox = varargin{1};
state = varargin{2};
querymode = strcmpi(state, 'query');
if ~querymode
permanent = varargin{3};
else
warning([msgId ':permanence_na_in_querymode'],...
'Permanency flag ignored for ''query'' mode.');
end
otherwise
error([msgId ':argincount_error'],...
'Too many input arguments.');
end
paths = regexp(path, pathsep, 'split');
if ~restoremode
if exist(storefile,'file')==2
S = load(storefile);
toolbox_states = S.toolbox_states;
clear S;
else
toolbox_states = struct('path', {paths});
for ii = 1:size(tb_name_map,1)
toolbox_states.(tb_name_map{ii,1}) = true; end
end
end
assert(iscellstr(toolbox) || ischar(toolbox),...
[msgId ':argument_error'], [...
'Toolboxes must be given as a string (single toolbox) or a cell array of ',...
'strings (multiple toolboxes).']);
if ~restoremode
assert(ischar(state) && any(strcmpi(state, {'on' 'off' 'query'})),...
[msgId ':argument_error'],...
'State must be a string equal to ''on'', ''off'' or ''query''.');
end
assert(ischar(permanent) && any(strcmpi(permanent, {'permanent', 'temporary'})),...
[msgId ':argument_error'],...
'Permanency must be indicated via string ''perpanent'' or ''temporary''.');
if isempty(toolbox) || any(strcmpi(toolbox, 'all'))
toolbox = tb_name_map(:,1);
else
if ~iscell(toolbox)
toolbox = {toolbox}; end
tb_name_map_i = cellfun(@lower, tb_name_map, 'UniformOutput', false);
toolbox_i = cellfun(@lower, toolbox, 'UniformOutput', false);
dirs = ismember(toolbox_i, tb_name_map_i(:,1));
[isname,names] = ismember(toolbox_i, tb_name_map_i(:,2));
assert(all(dirs | isname),...
[msgId ':unknown_toolbox'],...
'Toolbox: ''%s'' does not seem to be installed.',...
toolbox{find( ~(dirs | isname), 1, 'first')});
toolbox(isname) = tb_name_map(names(isname),1);
end
if querymode
if isempty(toolbox)
save(storefile, 'toolbox_states');
varargout{1} = toolbox_states;
else
for ii = 1:numel(toolbox)
toolbox_state.(toolbox{ii}) = toolbox_states.(toolbox{ii}); end
varargout{1} = toolbox_state;
end
return;
end
toolbox_states_out = toolbox_states;
switch lower(state)
case 'off'
for ii = 1:numel(toolbox)
tb = toolbox{ii};
if isfield(toolbox_states, tb) && ~toolbox_states.(tb)
warning([msgId ':toolbox_already_switched_off'],...
'Toolbox ''%s'' already switched off; ignoring.',...
tb);
else
toolbox_states.(tb) = false;
inds = ~cellfun('isempty', strfind(paths, fullfile(matlabroot, 'toolbox', tb)));
rmpath(paths{inds});
end
end
case {'on' 'restore'}
switched = false;
for ii = 1:numel(toolbox)
tb = toolbox{ii};
if ~isfield(toolbox_states, toolbox{ii})
warning([msgId ':toolbox_not_switched_off'],...
'Toolbox ''%s'' was not switched off; ignoring.',...
tb);
else
switched = true;
end
toolbox_states.(tb) = true;
end
if switched
newPaths = ~ismember(paths, toolbox_states.path);
if ~any(newPaths)
path( sprintf('%s;', toolbox_states.path{1:end-1}),...
toolbox_states.path{end} );
paths = toolbox_states.path;
else
warning([msgId ':new_paths_added'],[ ...
'New directories have been added to the path between consecutive ',...
'''on''/''off'' calls to %s. The path will be restored to that prior to ',...
'the first ''off'' call to %s, which will effectively remove these ',...
'new directories from the path.'],...
mfilename, mfilename);
end
toolboxes = fieldnames(toolbox_states);
toolboxes = toolboxes(~strcmp(toolboxes, 'path'));
for jj = 1:numel(toolboxes)
tb = toolboxes{jj};
if ~toolbox_states.(tb)
inds = ~cellfun('isempty', strfind(paths, fullfile(matlabroot, 'toolbox', tb)));
rmpath(paths{inds});
end
end
end
end
save(storefile, 'toolbox_states');
switch lower(permanent)
case 'temporary'
case 'permanent'
savepath();
end
if ~restoremode
varargout{1} = toolbox_states_out; end
end
function tb_name_map = get_tb_name_map()
persistent tb_map
if isempty(tb_map)
disp('First call; collecting toolbox information. Please wait...');
paths = regexp(path, pathsep, 'split');
tbs = dir(fullfile(matlabroot, 'toolbox'));
tbs = tbs(3:end);
tb_dirnames = {tbs.name}';
S(numel(tb_dirnames)) = struct('Name', '',...
'Version', '',...
'Release', '',...
'Date', '');
for ii = 1:numel(tb_dirnames)
tb_dirname = tb_dirnames{ii};
tb_dir = fullfile(matlabroot, 'toolbox', tb_dirname);
inds = ~cellfun('isempty', ...
strfind(paths, tb_dir));
if ~any(inds)
addpath(genpath(tb_dir)); end
tb_version = ver(tb_dirname);
if ~isempty(tb_version)
S(ii) = tb_version; end
end
tb_fullnames = {S.Name}';
tb_slice = ~cellfun('isempty', tb_fullnames);
tb_fullnames = tb_fullnames(tb_slice);
tb_dirnames = tb_dirnames (tb_slice);
tb_map = [tb_dirnames tb_fullnames];
path(sprintf('%s;', paths{1:end-1}), paths{end});
end
tb_name_map = tb_map;
end