How to get 'Live Editor Evaluation Helper' .m file name from live script through another live script?

I am running two live scripts, let's call them main.mlx and sub.mlx. Below are minimal working examples.
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, 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!

2 Comments

What specifically are you hoping/trying to do with this information if you can get it?
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. 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!

Sign in to comment.

Answers (1)

When sub.mlx is called through main.mlx though, the same Live Editor file name is returned twice, which is obviously incorrect.
No, what you are seeing is the automatic output of ans because you do not have a semi-colon on the call to sub
file q2174453.mlx
dbstack().file
sub
file sub.mlx
dbstack().file
Output is
ans = 'LiveEditorEvaluationHelperEeditor78579DB3_B29EA684.m'
ans = 'sub.mlx'
ans = 'LiveEditorEvaluationHelperEeditor78579DB3_B29EA684.m'
I admit to being a bit unclear as to why ans at the end is not sub.mlx since sub.mlx is being executed as-if it were a script
Anyhow, to get at the LiveEditorEvaluationHelper(randomNumbers).m file name, use dbstack(1).file

5 Comments

Hi Walter,
Thanks for your answer! I used dbstack(2).file before, and this doesn't work either, or maybe I'm doing it wrong. When using dbstack(2).file (I've tried it with and without semi-colon, both in sub and in main, both with and without disp()), I either get nothing as an output, or an error. I am really having the feeling that running a live script by writing its name in another live script, isn't interpreted as a function call and thus doesn't add it to the dbstack. Could you kindly show me a working example where running main.mlx can return both its own LiveEditorEvaluationHelper(randomNumbers).m and the one from sub.mlx? Many thanks!
It turns out that the numeric parameter to dbstack is the number of frames to omit, so to get at the second frame only you need to assign the output of dbstack to a variable and then index the variable. (In the case where you know for sure that there are exactly two levels you can dbstack(1).file directly)
file q2174453.mlx
'main is here'
dbstack().file
sub
file sub.mlx
'sub is here'
foo = dbstack;
foo(2).file
dbstack(1).file
Output is
ans = 'main is here'
ans = 'LiveEditorEvaluationHelperEeditor85515B63_925A5E4C.m'
ans = 'sub is here'
ans = 'LiveEditorEvaluationHelperEeditor85515B63_925A5E4C.m'
ans = 'LiveEditorEvaluationHelperEeditor85515B63_925A5E4C.m'
The answer you've provided still uses dbstack, and still produces the same "LiveEditorEvaluationHelperEeditor....m" when running main.mlx for both sub.mlx and main.mlx, while sub.mlx should return a different .m file. You can prove this by just running the command
dbstack().file
in both Live Scripts manually, they will return different answers. I need to get the sub.mlx Live Editor Helper .m file name through running main.mlx. I'm not sure as to how two interacting files would work in the online version of MATLAB, but running R2024b on my desktop, this still returns the Live Editor Helper .m file name of main.mlx every time. When analysing what's present in dbstack, just running
sub
is apparently not considered a function call, so it's not added to dbstack. Is there another way of getting this Live Editor Helper .m file name of a .mlx script through another .mlx script? I've tried wrapping it in
run('sub.mlx'); % With and without semi-colon
but that doesn't work either (although the run.m function is now added to dbstack when analysed).
In the case where a mlx is called from inside a mlx, as-if a function or script call, then it is not clear that LiveEditorEvaluationHelperEeditor....m is used. dbstack reflects the .mlx name in this case, whereas it reflects LiveEditorEvaluationHelperEeditor....m name for the outer mlx, so it might be that somehow the mlx is considered to be running directly.

Sign in to comment.

Categories

Find more on Scripts in Help Center and File Exchange

Products

Release

R2024b

Asked:

on 24 Feb 2025

Commented:

on 26 Feb 2025

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!