Run a specific section of a cell from the command line in Matlab?

I navigate through the various cells in Matlab manually in a script (let's call it foo.m):

%%
%Code for cell 1

%%
%Code for cell 2

From the Matlab command line, I would like to be able to selectively run the code in cell 2. The documentation contains only instructions for how to do this interactively (for example, place the cursor in the appropriate cell, then blah blah). I need something for the command line, so I can do something like foo.runCell (1) to run the code in cell 1 above.

If this is not done, I just break the cells into separate scripts / functions. This is less convenient since I am in the “chopping prototype very fast” mode, so now I want everything in one file.

+4
source share
3 answers

Dev-iL provided a good answer using java etc. I will present an alternative here that does not use java or an editor, but reads a file and parses statements upon request.

To do this, it has a prerequisite for saving the file (which, in my opinion, is not a prerequisite for running cells / code blocks in interactive mode).

In any case, I thought it was a "dodgy" question, and I thought that I would add an answer.

Here is my script (cellScript.m) that contains blocks of code (Note. I gave each block a name after "%%":

%Note: for this method your NOT allowed to put comments at the end of lines
%% cellA
disp ( 'running cell A' ); 
disp ( 'finished cell A' );
%% cellB
disp ( 'running cell B' );
disp ( 'finished cell B' );
%% cellC
disp ( 'running cell C' );
for ii=1:100
  aa(ii) = randi(1);
end
% cells can have comments
disp ( 'past 1st coment' );
   % cells comments can be indented
disp ( 'past indented comment' );

  %{
   block 
   comment
  %}
disp ( 'past block comment' );

% cells can have comments
% multiple lines of comments
  % not lined up
%
%and empty

disp ( 'past multiple lines of comments' );

disp ( 'finished cell C' );
%% cellD
disp ( 'running cell D' );

disp ( 'finished cell D' );
%% cellE
disp ( 'running cell E' );
disp ( 'finished cell E' );

I created a class that does the job (I called it cellRunner.m)

classdef cellRunner < handle
  properties ( SetAccess = private )
    fileName
    fileInfo
    cellInfo
    cellNames = {};
  end
  methods 
    function obj = cellRunner ( file ) % constructor
      if nargin == 0                        
        obj.fileName = 'cellScript.m';      % default file for testing
      else
        obj.fileName = file;                % store user file
      end
      obj.parseFile();                      % read the file into memory
    end
    function obj = parseFile ( obj )
      if ~isempty ( obj.fileInfo )                        % on parsing check to see if its been parsed before
        if isequal ( obj.fileInfo, dir ( obj.fileName ) ) % Check date stamp (has cell file been modified
%           disp ( 'file not changed - reading skipped' );  % if not skip
%           reading 
          return
        end
      end
      obj.fileInfo = dir ( obj.fileName );                % store file info
      fid = fopen ( obj.fileName );                       % open file for reading
      if fid ~= -1
        index = 0;                                        % this is the index of each cell
        inCell = false;                                   % has it found a cell to start reading
        lines = cell(0);                                  
        while ( true )
          line = fgetl ( fid );                           % read the line in the file
          if line == -1; break; end                       % check for the end of the file
          sLine = strtrim ( line );                       % trim any white space
          if length ( sLine ) > 2 && strcmp ( sLine(1:2), '%%' ) % check to see if its the start of a cell
            if index > 0                                  % Store the last cell data                
              obj.cellInfo{index} = lines;                % in class to run when required
            end
            index = index + 1;                            % increment the index
            obj.cellNames{index} = strtrim ( sLine(3:end) ); % save the name of the cell
            lines = cell(0);                              % re-initialise the lines var
            inCell = true;                                % the start of the cells have been found
          elseif inCell                                   % if reading a cell array
            lines{end+1} = line;                          % add each line to the lines var
          end          
        end
        if index > 0                                      % make sure and save the last cell when finished reading
          obj.cellInfo{index} = lines;
        end
        fclose ( fid );
      else
        error ( 'cellRunner:fileError', 'unable to read file' );
      end
    end
    function obj = runCell ( obj, arg )
      % obj.runCell ( 'cellName' );
      % obj.runCell ( index );
      obj.parseFile();                                    % check that the file hasn't been changed
      if ischar ( arg )                                   % if user provided a char then search for it
        index = strcmp ( arg, obj.cellNames );            % find the index
        if ~any ( index )                                 % check it was found
          error ( 'cellRunner:notFound', '%s not found', arg ); 
        end
      else
        index = arg;                                      % if index is an integer (not checked - assumed if not char)
        if index < 1 || index > length ( obj.cellInfo )   % check integer is valid
          error ( 'cellRunner:notFound', 'Index %d not found', arg );
        end
      end
      commands = obj.cellInfo{index}{1};                  % start to build the command to execute.
      inBlock = false;
      for ii=2:length(obj.cellInfo{index})                % loop around - ignoring any commented lines.
        nextLine = strtrim ( obj.cellInfo{index}{ii} ); 
        if inBlock
          if length ( nextLine ) == 2 && strcmp ( nextLine, '%}' );
            inBlock = false;
          end
          continue
        end
        if length ( nextLine ) == 2 && strcmp ( nextLine, '%{' );
          inBlock = true;
          continue
        end
        if length ( nextLine ) >= 1 && strcmp ( nextLine(1), '%' )
          continue;
        end
        commands = sprintf ( '%s;%s', commands, obj.cellInfo{index}{ii} ); % build a parge string to eval
      end
      evalin('base',commands);                            % eval the expression in the base workspace.
    end
  end
end

Then the code is used as follows:

obj.cellRunner();
% Individual cells can be run in two ways:

% By providing the name of the cell (the string after the %%)
obj.runCell ( 'cellC' );
% By providing the index
obj.runCell ( 3 );

. , .

:

whos
obj = cellRunner ( 'cellScript.m' );
obj.runCell ( 'cellC' );
running cell C
past 1st coment
past indented comment
past block comment
past multiple lines of comments
finished cell C
whos
  Name      Size             Bytes  Class         Attributes

  aa        1x100              800  double                  
  ans       1x1                112  cellRunner              
  ii        1x1                  8  double                  
  obj       1x1                112  cellRunner              

1 - ? , , - . answer 1 , value/handle.

+3

, , .

, "" (.. ). , - . , :

runCodeSectionInFile.m:

function runCodeSectionInFile(scriptFullPath,sectionNum)
%// TIP: You can use "which('scriptName')" to obtain the full path of a 
%// script on your MATLAB path.
%%% // Temporary Workaround
import java.awt.Robot;   %// part of temporary workaround
import java.awt.event.*; %// part of temporary workaround
RoboKey = Robot;         %// part of temporary workaround
RoboKey.setAutoDelay(10);%// part of temporary workaround
%% // Test if the needed components are available (optional)
if ~matlab.desktop.editor.isEditorAvailable || ...
   ~com.mathworks.mde.editor.codepad.Codepad.isCodepadEnabled
    error('MATLAB editor is N\A');
end
%% // Open and\or switch to the script file
%// Test if script is opened:
if ~matlab.desktop.editor.isOpen(scriptFullPath) 
    scriptDoc = matlab.desktop.editor.openDocument(scriptFullPath);
else %// in case the script is open, get a handle to it, and save it:
    scriptDoc = matlab.desktop.editor.findOpenDocument(scriptFullPath);
    %// Save the script before running (optional):
    scriptDoc.save;
end
scriptDoc.goToLine(0); %// Position the cursor at the beginning of the file
                       %// NOTE1: - uses zero based indexing!
jEd = com.mathworks.mlservices.MLEditorServices.getEditorApplication ...
        .openEditorForExistingFile(java.io.File(scriptFullPath));
jEd.getTextComponent.grabFocus; drawnow; %// part of temp fix
%// NOTE2: most of the above can be replaced with:
%//   EDITOROBJ = matlab.desktop.editor.openAndGoToLine(FILENAME,LINENUM);
%% // Get the Codepad and the LineManager handles:
jCm = com.mathworks.mde.editor.codepad.CodepadActionManager ...
                   .getCodepadActionManager(jEd);
jCp = jEd.getProperty('Codepad');
jLm = jCp.getLineManager(jEd.getTextComponent,jCm);
%% // Advance to the desired section
jAc = com.mathworks.mde.editor.codepad.CodepadAction.CODEPAD_NEXT_CELL;
                                           %// 'next-cell' Action

for ind1=1:sectionNum-1 %// click "advance" several times
    %// <somehowExecute(jAc) OR jCp.nextCell() >    
    RoboKey.keyPress(KeyEvent.VK_CONTROL); %// part of temporary workaround
    RoboKey.keyPress(KeyEvent.VK_DOWN);    %// part of temporary workaround
end
RoboKey.keyRelease(KeyEvent.VK_DOWN);      %// part of temporary workaround
RoboKey.keyRelease(KeyEvent.VK_CONTROL);   %// part of temporary workaround
%% Execute section - equivalent to clicking "Run Section" once

jAc = com.mathworks.mde.editor.codepad.CodepadAction.CODEPAD_EVALUATE_CELL; 
                                                 %// 'eval-cell' Action
%// <somehowExecute(jAc); OR jCp.evalCurrentCell(true) >    
RoboKey.keyPress(KeyEvent.VK_CONTROL); %// part of temporary workaround
RoboKey.keyPress(KeyEvent.VK_ENTER);   %// part of temporary workaround
RoboKey.keyRelease(KeyEvent.VK_CONTROL);   %// part of temporary workaround
%% // Close the file (optional)
jEd.close;
%% // Return focus to the command line:
com.mathworks.mde.cmdwin.CmdWin.getInstance.grabFocus;

testScript.m:

%% // This is code block one
disp('This is section one');
%% // This is code block two
disp('This is section two');
%% // This is code block three
disp('This is section three');

, , , ( cd) runCodeSectionInFile(which('testScript.m'),1). :

>> runCodeSectionInFile(which('testScript.m'),1)
This is section one
>> runCodeSectionInFile(which('testScript.m'),2)
This is section two
>> runCodeSectionInFile(which('testScript.m'),3)
This is section three

RoboKey.setAutoDelay(10); , NPE.

:

P.S. 2014b. ( ) ...

Edit1:

, Codepad TaggedLineManager. , Codepad EDT (- " ", ).

+3

To run a specific section from a file using the command line, you can use

echodemo(filename, index of section)

MATLAB Documentation

0
source

All Articles