admin管理员组

文章数量:1278859

I am running two live scripts, let's call them main.mlx and sub.mlx. Below are MWEs.

The main.mlx:

dbstack().file
sub

The sub.mlx

dbstack().file

When running dbstack().file in a live script, a file name "LiveEditorEvaluationHelper(randomNumbers).m" is returned. If sub.mlx is run manually, it returns a different Live Editor file name than when main.mlx is run (which it should). When sub.mlx is called through main.mlx though, the same Live Editor file name is returned twice, which is obviously incorrect.

I need to be able to get the "LiveEditorEvaluationHelper(randomNumbers).m" from sub through main. I have multiple subscripts, and the "LiveEditorEvaluationHelper(randomNumbers).m" changes everytime MATLAB is restarted, so running it once and then just saving the name as a variable is very impractical. Using

f = matlab.desktop.editor.getActiveFilename

also doesn't work, since the "active file" is main.mlx. I am assuming just calling sub.mlx through main.mlx doesn't activate the script, or at the very least isn't interpreted as a function, so it isn't added on the dbstack struct, but I can't seem to find a way around this. I have seemingly looked everywhere, and can't find an answer to this. I apologize in advance if the solution to this is glaringly obvious. Thanks for your help!

--- SOME CONTEXT ---

For educational purposes, I need to write my code in Live Scripts, where I have a script to simulate physical phenomena. This is divided up into subscripts based on parts of the simulation. I need to use the Live Script to be able to explain what several functions do and how they work. Some of these functions are in subscripts, but are also used in the main script. My main goal is thus to be able to call a function that is declared in a different live script, instead of in the script itself or in a separate .m function file. Bear with me, chaos is about to ensue. Just executing the subscript in the main.mlx like

sub

doesn't allow for subscript functions to be saved in the workspace, and thus can't be called in the main script. A work-around for this is creating myFunction.m in the same folder instead, so I can call the function in main.mlx that way. However, that only statically works when myFunction.m doesn't change. That's not the case: I want to be able to alter the function code in sub.mlx (where explanations, LaTeX equations and figures are present), and then dynamically update myFunction.m in the background, so that main.mlx can now call the updated function "seemingly" from sub.mlx. The algorithm I wrote to do this works perfectly if I manually run sub.mlx. However, if I then execute sub.mlx through main.mlx, the function doesn't work anymore. Find the code below. I have a strong feeling as to why this fails.

function saveFunction(functionName)
    stack = dbstack;            % Get the current script filename and line number
    scriptName = stack(2).file; % The file where the function is called
    
    % Open the script file
    fid = fopen(scriptName, 'r');
    if fid == -1
        error('Cannot open the file: %s', scriptName);
    end
    
    % Initialize variables to track lines
    currentLine = stack(2).line; % The line where the function is called
    linesToSave = {};
    foundFunction = false;
    
    % Read the file and move upwards, starting just above the current line
    lineNumber = currentLine - 1;
    while lineNumber > 0
        % Read the current line
        lineNum = 1;
        fseek(fid, 0, 'bof'); % Reset fgetl
        while lineNum < lineNumber
            fgetl(fid); % Skip the lines until the target line
            lineNum = lineNum + 1;
        end
        tline = fgetl(fid);
        
        % Check if we found a 'function' keyword in this line
        if contains(tline, 'function')
            foundFunction = true;
            linesToSave{end+1} = tline; % Save the line with 'function'
            break; % Stop since the full function definition has been found
        end
        
        % Add the line to the linesToSave list
        linesToSave{end+1} = tline;
        
        % Decrease the line number to move upwards
        lineNumber = lineNumber - 1;
    end
    
    % Close the file
    fclose(fid);
    
    % If no function was found, raise an error
    if ~foundFunction
        error('No function definition found in the script before the call.');
    end
    
    % Save the collected lines to a text file with the functionName
    fileID = fopen(['Functions/', functionName, '.m'], 'w');
    if fileID == -1
        error('Cannot create the file: %s.m', functionName);
    end
    
    % Write the lines to the text file
    for i = length(linesToSave):-1:1
        fprintf(fileID, '%s\n', linesToSave{i});
    end
    
    % Close the output file
    fclose(fileID);
    
    disp(['Code saved successfully as Functions/', functionName, '.m']);
end

Provided a folder "Functions" already exist in the current folder and is added to the path, the function is called like

% a function in sub.mlx
function a = myFunction(b, c)
    a = b + c;
end
saveFunction('myFunction');

where it looks for the closest function above where it was called, and saves it accordingly. (Yes, I know this won't work with nested functions, that's fine.) As I said, this works beautifully when running sub.mlx. When executed through main.mlx though, the active file is main.mlx, not sub.mlx, and sub.mlx (and the actual .m file running in the background, "Live Editor Helper ...") is not added to dbstack. So, stack, scriptName and currentLine fail to deliver what they should. I have tried to alter this algorithm to make it work, but can't seem to fix it. Any help is welcome!

本文标签: