Code covered by the BSD License  

Highlights from
FSplit

image thumbnail
from FSplit by Stead Kiger
FSPLIT splits a multifunction m-file into many single function m-files

FSplit(varargin)
function FSplit(varargin)
% FSPLIT splits a multifunction m-file into many single function m-files
%
% FSPLIT(SOURCEFILE) reads the multifunction m-file SOURCEFILE and writes a
% new m-file for each function in SOURCEFILE into the current directory,
% splitting the SOURCEFILE by functions.  If no path is specified for the
% source file, it is read from the current directory or from the Matlab
% path, in that order.
%
% FSPLIT(SOURCEFILE, TARGETDIR) writes the individual functions in
% SOURCEFILE into the directory TARGETDIR.
% 
%
%   Example:  
%
%       >> FSplit('ver.m','.\test')
%       FSplit reading file C:\MATLAB\toolbox\matlab\general\ver.m
%       
%       Writing function ver.m ... finished
%       Writing function fixarg.m ... finished
%       Writing function LocParseContentsFile.m ... finished
%       Writing function LocDisplayMatlabInformation.m ... finished
%       Writing function sort_toolbox_list.m ... finished
%       Writing function display_toolbox_list.m ... finished
%       Writing function remove_unwanted_entries.m ... finished
%       Writing function disp_single_toolbox.m ... finished
%       Writing function LocCleanDate.m ... finished
%       
%       FSplit finished.
% 

%
% Author:         Stead Kiger, Ph.D.
%                 Department of Radiation Oncology
%                 Beth Israel Deaconess Medical Center
%                 Harvard Medical School
% Last Modified:  December 21, 2006
%
% Copyright (C) 2006 Stead Kiger, Ph.D.
%
% This program is distributed under the terms of the BSD license, available
% at http://www.opensource.org/.


stdIO=1;

% Assign the source file and target directory
sourceFile=varargin{1};
[pathStr,fileName,ext,versn] = fileparts(sourceFile);
if nargin==1,
    targetDir=pwd;
elseif nargin==2,
    targetDir=varargin{2};
else
    error('Wrong number of arguments');
end


% If no path was specfied for the source file, check that the source file
% exists in the current directory.  If not, use which(sourceFile) to
% determine whether it exists somewhere in the Matlab path.
if isempty(pathStr),
    if ~exist(fullfile(pwd,sourceFile),'file'),
        % look for the m-file in the Matlab path using which
        foundFile=which(sourceFile);
        if isempty(foundFile),
            error('The source file %s could not be found.');
        else
            sourceFile=foundFile;
        end
    end
end

% Check that the target directory exists and if not, create it
if exist(targetDir,'dir')==7,
    % the target directory exists
else
    % try to create the target directory
    [success,msg,msgID] = mkdir(targetDir);
    if ~success,
        display(msg)
        error('Could not create target directory %s.',targetDir)
    end
end

% Open the source file for reading
outFID=-1;
srcFID=fopen(sourceFile,'rt');
if srcFID==-1,
    error('The source file %s could not be opened.',sourceFile)
else
    outFileIsOpen=false;
    fprintf(stdIO,'%s reading file %s\n\n',mfilename, sourceFile)

    % Read the source file until its end is reached
    while ~feof(srcFID),
        lineStr=fgetl(srcFID);

        % Look for occurences of 'function', which of course denotes a new
        % function
        if ~isempty(regexpi(lineStr, 'function ', 'start')),
            
            % check for line continuation (...)
            contIdx=regexpi(lineStr, '\.\.\.', 'start');
            if ~isempty(contIdx),
                srcFilePos=ftell(srcFID); % position before more reads
                syntaxDef=[];
                contLineStr=lineStr;
                
                % read until there are no more line continuations, building
                % up the syntax definition line so that we can determine
                % the function name
                while ~isempty(contIdx),  
                    syntaxDef=[syntaxDef contLineStr(1:contIdx-1)];
                    contLineStr=fgetl(srcFID);
                    contIdx=regexpi(contLineStr, '\.\.\.', 'start');
                end
                syntaxDef=[syntaxDef contLineStr]; % add final line
                [newFunName]=GetFunctionName(syntaxDef);
                
                % reset the file position to just after we read the first
                % continuation line
                status=fseek(srcFID, srcFilePos, 'bof');
            else
                [newFunName]=GetFunctionName(lineStr);
            end
            if ~isempty(newFunName),
                % Close the current m-file
                if outFileIsOpen,
                    fclose(outFID);
                    fprintf(stdIO,'finished\n')
                end

                % Open a new m-file for the new function
                outFileSpec=fullfile(targetDir,[newFunName '.m']);
                if exist(outFileSpec,'file'),
                    error('Output file %s already exists',outFileSpec)
                else
                    outFID=fopen(outFileSpec,'wt');
                    outFileIsOpen=true;
                    count=fprintf(outFID,'%s\n',lineStr);
                    fprintf(stdIO,'Writing function %s ... ',[newFunName '.m'])
                end
            end

        else
            if outFileIsOpen,
                count=fprintf(outFID,'%s\n',lineStr);
            end
        end
    end
    fprintf(stdIO,'finished\n')  % finished writing the last function
    if outFID~=-1,
        fclose(outFID);
    end
    fprintf(stdIO,'\n%s finished.\n\n',mfilename)
end

end


function [newFunName]=GetFunctionName(lineStr)
% GETNEWFUNCTIONNAME extracts the function name from a syntax definition line
%
% [newFunName]=GetFunctionName(lineStr) analyzes a possible syntax
% definition line to find a function name.  It ignores commented syntax
% definition lines, i.e., behind a % sign.  If no function name is found,
% newFunName is returned empty.
%
% The possibilities for syntax definition lines are:
%
%    function foo
%    function a = foo
%    function [a,b,c, ...] = foo
%    function [a,b,c, ...] = foo(x,y,z, ...)


% first check that it is not actually a comment
fcnIdx=strfind(lower(lineStr),'function ');
pctIdx=strfind(lineStr,'%');
if ~isempty(pctIdx),
    if pctIdx < fcnIdx,
        newFunName=[];
        return
    end
    % Delete the comment
    lineStr=lineStr(1:pctIdx-1);
end

% Delete the word function
lineStr=lineStr(fcnIdx+9:end);

% look for an equals sign
eqIdx=strfind(lineStr,'=');
if ~isempty(eqIdx),
    % Delete all characters to the left of (and including) the equals sign
    lineStr=lineStr(eqIdx+1:end);
end

% Look for a left parenthesis
ltParenIdx=strfind(lineStr,'(');
if ~isempty(ltParenIdx),
    % Delete all characters to the right of the parenthesis (inclusive)
    lineStr=lineStr(1:ltParenIdx-1);
end

% Deblank both sides of what is hopefully the remaining function name
newFunName=strtrim(lineStr);

end

Contact us at files@mathworks.com