-
Notifications
You must be signed in to change notification settings - Fork 2
/
addpath_recurse.m
194 lines (170 loc) · 8.48 KB
/
addpath_recurse.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
function addpath_recurse(strStartDir, caStrsIgnoreDirs, strXorIntAddpathMode, blnRemDirs, blnDebug)
%ADDPATH_RECURSE Adds (or removes) the specified directory and its subfolders
% addpath_recurse(strStartDir, caStrsIgnoreDirs, strXorIntAddpathMode, blnRemDirs, blnDebug)
%
% By default, all hidden directories (preceded by '.'), overloaded method directories
% (preceded by '@' and '+'), and directories named 'private' or 'CVS' are ignored.
%
% Input Variables
% ===============
% strStartDir::
% Starting directory full path name. All subdirectories (except ignore list) will be added to the path.
% By default, uses current directory.
% caStrsIgnoreDirs::
% Cell array of strings specifying directories to ignore.
% Will also ignore all subdirectories beneath these directories.
% By default, empty list. i.e. {''}.
% strXorIntAddpathMode::
% Addpath mode, either 0/1, or 'begin','end'.
% By default, prepends.
% blnRemDirs::
% Boolean, when true will run function "in reverse", and
% recursively removes directories from starting path.
% By default, false.
% blnDebug::
% Boolean, when true prints debug info.
% By default, false.
%
% Output Variables
% ================
% None. If blnDebug is specified, diagnostic information will print to the screen.
%
% Example(s)
% ==========
% (1) addpath_recurse(); %Take all defaults.
% (2) addpath_recurse('strStartDir'); %Start at 'strStartDir', take other defaults. i.e. Do addpath().
% (3) addpath_recurse('strStartDir', '', 0, true); %Start at 'strStartDir', and undo example (2). i.e. Do rmpath().
% (4) addpath_recurse('strStartDir', '', 'end', false, true); %Do example (2) again, append to path, and display debug info.
% (5) addpath_recurse('strStartDir', '', 1, true, true); %Undo example (4), and display debug info.
%
% See Also
% ========
% addpath()
%
% Developers
% ===========
% Init Name Contact
% ---- --------------- ---------------------------------------------
% AK Anthony Kendall anthony [dot] kendall [at] gmail [dot] com
% JMcD Joe Mc Donnell
%
% Modifications
% =============
% Version Date Who What
% -------- -------- ----- --------------------------------------------------------------------
% 00.00.00 20080808 AK First created.
% 20090410 JMcD Redo input argument processing/checking.
% Only do processing/checking once. Do recursion in separate function.
% 20090411 JMcD Add debugging mode to display run info.
% 20090414 AK Modified variable names, small edits to code, ignoring CSV by default
% 20091104 AK Modified an optimization for Mac compatibility,
% recursive calls to just build the string for
% addpath/rmpath rather than call it each time
%--------------------------------------------------------------------------
%Error messages.
strErrStartDirNoExist = 'Start directory does not exist ???';
strErrIgnoreDirsType = 'Ignore directories must be a string or cell array. See HELP ???';
strErrIllAddpathMode = 'Illegal value for addpath() mode. See HELP ???';
strErrIllRevRecurseRemType = 'Illegal value for reverse recurse remove, must be a logical/boolean. See HELP ??';
strErrWrongNumArg = 'Wrong number of input arguments. See HELP ???';
strAddpathErrMessage = strErrIllAddpathMode;
%Set input args defaults and/or check them.
intNumInArgs = nargin();
assert(intNumInArgs <= 5, strErrWrongNumArg);
if intNumInArgs < 1
strStartDir = pwd();
end
if intNumInArgs < 2
caStrsIgnoreDirs = {''};
end
if intNumInArgs >= 2 && ischar(caStrsIgnoreDirs)
caStrsIgnoreDirs = { caStrsIgnoreDirs };
end
if intNumInArgs < 3 || (intNumInArgs >= 3 && isempty(strXorIntAddpathMode))
strXorIntAddpathMode = 0;
end
if intNumInArgs >= 3 && ischar(strXorIntAddpathMode) %Use 0/1 internally.
strAddpathErrMessage = sprintf('Input arg addpath() mode "%s" ???\n%s', strXorIntAddpathMode, strErrIllAddpathMode);
assert(any(strcmpi(strXorIntAddpathMode, {'begin', 'end'})), strAddpathErrMessage);
strXorIntAddpathMode = strcmpi(strXorIntAddpathMode, 'end'); %When 'end' 0 sets prepend, otherwise 1 sets append.
end
if intNumInArgs < 4
blnRemDirs = false;
end
if intNumInArgs < 5
blnDebug = false;
end
if size(caStrsIgnoreDirs, 1) > 1
caStrsIgnoreDirs = caStrsIgnoreDirs'; %Transpose from column to row vector, in theory.
end
%Check input args OK, before we do the thing.
strErrStartDirNoExist = sprintf('Input arg start directory "%s" ???\n%s', strStartDir, strErrStartDirNoExist);
assert(exist(strStartDir, 'dir') > 0, strErrStartDirNoExist);
assert(iscell(caStrsIgnoreDirs), strErrIgnoreDirsType);
assert(strXorIntAddpathMode == 0 || strXorIntAddpathMode == 1, strAddpathErrMessage);
assert(islogical(blnRemDirs), strErrIllRevRecurseRemType);
assert(islogical(blnDebug), 'Debug must be logical/boolean. See HELP.');
if blnDebug
intPrintWidth = 34;
rvAddpathModes = {'prepend', 'append'};
strAddpathMode = char(rvAddpathModes{ fix(strXorIntAddpathMode) + 1});
strRevRecurseDirModes = { 'false', 'true' };
strRevRecurseDirs = char(strRevRecurseDirModes{ fix(blnRemDirs) + 1 });
strIgnoreDirs = '';
for intD = 1 : length(caStrsIgnoreDirs)
if ~isempty(strIgnoreDirs)
strIgnoreDirs = sprintf('%s, ', strIgnoreDirs);
end
strIgnoreDirs = sprintf('%s%s', strIgnoreDirs, char(caStrsIgnoreDirs{intD}));
end
strTestModeResults = sprintf('... Debug mode, start recurse addpath arguments ...');
strTestModeResults = sprintf('%s\n%*s: "%s"', strTestModeResults, intPrintWidth, 'Start directory', strStartDir);
strTestModeResults = sprintf('%s\n%*s: "%s"', strTestModeResults, intPrintWidth, 'Ignore directories', strIgnoreDirs);
strTestModeResults = sprintf('%s\n%*s: "%s"', strTestModeResults, intPrintWidth, 'addpath() mode', strAddpathMode);
strTestModeResults = sprintf('%s\n%*s: "%s"', strTestModeResults, intPrintWidth, 'Reverse recurse remove directories', strRevRecurseDirs);
disp(strTestModeResults);
end
%Don't print the MATLAB warning if remove path string is not found
if blnRemDirs, warning('off', 'MATLAB:rmpath:DirNotFound'); end
%Build the list of directories
caAddRemDirs = {};
[caAddRemDirs] = addpath_recursively(caAddRemDirs, strStartDir, caStrsIgnoreDirs, strXorIntAddpathMode, blnRemDirs,blnDebug);
%Remove or add the directory from the search path
if blnRemDirs
if blnDebug, fprintf('"%s", removing from search path ...', strStartDir); end
rmpath(caAddRemDirs{:})
else
if blnDebug, fprintf('"%s", adding to search path ...', strStartDir); end
addpath(caAddRemDirs{:}, strXorIntAddpathMode);
end
%Restore the warning state for rmpath
if blnRemDirs, warning('on', 'MATLAB:rmpath:DirNotFound'); end
end % function addpath_recurse
%--------------------------------------------------------------------------
%--------------------------------------------------------------------------
function [caAddRemDirs] = addpath_recursively(caAddRemDirs, strStartDir, caStrsIgnoreDirs, strXorIntAddpathMode, blnRemDirs, blnDebug)
%Note:Don't need to check input arguments, because caller already has.
%Add this directory to the add/remove path list
caAddRemDirs = [caAddRemDirs,strStartDir];
strFileSep = filesep();
%Get list of directories beneath the specified directory, this two-step process is faster.
if ispc
saSubDirs = dir(sprintf('%s%s%s', strStartDir, strFileSep, '*.'));
else
saSubDirs = dir(strStartDir);
end
saSubDirs = saSubDirs([saSubDirs.isdir]); %Handles files without extensions that otherwise pass through previous filter
%Loop through the directory list and recursively call this function.
for intDirIndex = 1 : length(saSubDirs)
strThisDirName = saSubDirs(intDirIndex).name;
blnIgnoreDir = any(strcmpi(strThisDirName, { 'private', 'CVS', '.', '..', caStrsIgnoreDirs{:} }));
blnDirBegins = any(strncmp(strThisDirName, {'@', '.', '+'}, 1));
if ~(blnIgnoreDir || blnDirBegins)
strThisStartDir = sprintf('%s%s%s', strStartDir, strFileSep, strThisDirName);
if blnDebug, fprintf('"%s", recursing ...', strThisStartDir); end
[caAddRemDirs] = addpath_recursively(caAddRemDirs, strThisStartDir, caStrsIgnoreDirs, strXorIntAddpathMode, blnRemDirs, blnDebug);
end
end % for each directory.
end % function addpath_recursively
%--------------------------------------------------------------------------
%__END__