Programmatically save all dirty files in MatLab - matlab

Frequently I make the mistake of running my main.m when several files in the editor are dirty.
It would be nice if I could have a command at the start of my main.m that just automatically saves every dirty file.
Save currently running script in Matlab gives an answer with a clue for saving the currently active file, but is there a way to do this for ALL files?

You can use the com.mathworks.mlservices.MLEditorservice object to access the editor and save all dirty files.
service = com.mathworks.mlservices.MLEditorServices;
% Get a vector of all open editors
editors = service.getEditorApplication.getOpenEditors();
% For each editor, if it is dirty, save it
for k = 0:(editors.size - 1)
editor = editors.get(k);
if editor.isDirty()
editor.save();
end
end
Rather than blindly saving all files, you could modify this slightly so that you could pass a list of functions (your dependencies) and just save those.
function saveAll(varargin)
% Convert all filenames to their full file paths
filenames = cellfun(#which, varargin, 'uniformoutput', false);
service = com.mathworks.mlservices.MLEditorServices;
% Get a vector of all open editors
editors = service.getEditorApplication.getOpenEditors();
% For each editor, if it is dirty, save it
for k = 0:(editors.size - 1)
editor = editors.get(k);
% Check if the file in this editor is in our list of filenames
% and that it's dirty prior to saving it
if ismember(char(editor.getLongName()), filenames) && editor.isDirty()
editor.save();
end
end
end
And this could be called with multiple function names (as strings)
saveAll('myfunc', 'myotherfunc')

Related

MATLAB error using "diary"

I'm learning MATLAB and for my homework am supposed to use the diary feature to save a file from the command window. I used the following code,
%% 2.21
clc
clear
diary( 'degrees.dat' )
columnOne = linspace(0, 180, 8);
columnTwo = columnOne .* (pi / 180);
D_to_R = [columnOne', columnTwo']
diary off
clc
clear
load ( 'degrees.dat' )`
and got the error:
Error using load
Number of columns on line 3 of ASCII file
degrees.dat must be the same as previous
lines.
I put the above code in the editor window but tried putting it directly in the command window and it didn't make a difference. The code up until loading the saved file seems to work fine and I can't see a difference in number of columns like the error indicates.
Any ideas?
You are using diary correctly. However, your use of load is incorrect, and most likely unneeded based on the problem at hand. You've shown that you can save a file with 'diary'.
If you want to show the contents of your diary as stored in the file degrees.dat in the command window you can type, into the command window:
type degrees.dat or type('degrees.dat').
Similarly, if you want to open it in the edit window you can use
edit('degrees.dat') or edit degrees.dat

Why am I getting this error when selecting files with uigetfile?

I used uigetfile to select multiple images. When I select the images and push the open button or press the enter key everything is okay. But when I instead select the images and double click on the selected images, I get this error:
Cell contents reference from a non-cell array object.
Error in Picketfence>insertpb_Callback (line 141)
file = fullfile(PathName,FileNames{i});
Here's my code:
c={'*.*', 'All Files(*.*)';'*.jpeg','figure (*.jpg)';'*.tif',...
'figure (*.tif)'};
[FileNames,PathName] = uigetfile(c, 'Select Images','MultiSelect','on');
if char(FileNames)
nfiles = length(FileNames);
handles.profile = zeros(1024,1024);
for i = 1:nfiles
file = fullfile(PathName,FileNames{i});
handles.profile = handles.profile+im2double(imread(file));
end
end
Why am I getting this error and how can I fix it?
The problem is that you can't select multiple files by double-click. When you select your files, then double-click on one of them, what's actually happening is that you are selecting only the one you double-clicked on. In other words, the first click of the double-click selects just that one, clearing the others.
When the GUI closes and returns to your code, you only have a single file selected, so FileNames isn't a cell array, just a character string. This is why the cell content indexing with {} fails.
A few more points about your code...
Your conditional check if char(FileNames) is wrong. The char function doesn't return logical (i.e. boolean) values. It converts things to character arrays. As per the documentation for uigetfile, the outputs will be zero when the selection is cancelled or the GUI closed, so the appropriate check in your case would be:
if ~isequal(FileNames, 0)
% Do your processing here...
else
% Nothing was selected; take some other action
end
You may want to account for the possibility of only 1 file being selected, thus having FileNames be a character array. The simplest way to do this is to first check if FileNames is a character array using ischar, and if so encapsulate it in a 1 element cell array (since your code expects cell arrays):
if ischar(FileNames)
FileNames = {FileNames};
end
Then you can do all your processing as you have it written above.

Diary Matlab :: Latest messages on top of the text file instead of append to bottom of file

The diary function works well for logging purposes in my application, but instead of latest messages appearing on top of the text file ( this is the way I need it) it appends to older messages.
Any method to pre-append the messages rather than append to older messages in the text file or workarounds ?
Flipping the order should be done in the UI, here no HDD interaction is involved which will make it much faster.
At some point you need to open the logfile and initialize your data structure:
fid = fopen('fgetl.m');
lines = {}
Now read only the new lines. Repeat this cyclic:
tline = fgetl(fid);
new_line=false;
while ischar(tline)
lines{end+1} = fgetl(fid);
new_line=true
end
To display I recommend to display only the last n (choose a value) lines in your UI to avoid slowing down when the log grows:
if new_line
reversed=lines(end:-1:max(numel(lines)-n+1,1));
%update your UI here with the text in reversed
end
Finally, at the end of your program you need to close the file:
fclose(fid);

I Want Users Browse The File, But It Affects to My Script

I'm doing with MATLAB.
I have a file named 'cobat'. Cobat is a *txt file, tab delimited, consisted of 3 coloumns, so it's a table. I load it manually into this script:
I want users browse their own file. How can I do it? Is this code correct:
[filename pathname] = uigetfile(('.txt'), 'Browse Your File')
Here are my problems:
I think it is only for text file, not tab delimited (table). I think I have to use uitable, but I don't understand how to implement it, because the file (cobat) should be loaded.
And, if it has been implemented, I can't write 'cobat' in my script, like this:
[g c] = kmeans(cobat,k,'dist','SqEuclidean'); y = [cobat g]
Then I have to change 'cobat' to what name?
Thank you.
You are on the right track. After locating the file you need to load it:
load([pathname filesep filename])
If file name is cobat (or cobat.txt), it will create a matrix called cobat in the workspace with the content of the file.

How do you retrieve the selected text in MATLAB?

MATLAB has several selection-sensitive capabilities. For example, if you select some text and press F9, it evaluates your selection. (Unless you've remapped your keyboard settings.)
I'd like to be able to replicate this functionality with for a shortcut. So, for example, I want to click a shortcut that displays the current selection. My shortcut callback would be disp(GetSelection()).
But what goes into GetSelection?
Thanks to #Yair Altman's undocumented Matlab, I was able to figure out the java commands to make this work.
Put this in a shortcut (or a function that is called by the shortcut):
%# find the text area in the command window
jDesktop = com.mathworks.mde.desk.MLDesktop.getInstance;
try
cmdWin = jDesktop.getClient('Command Window');
jTextArea = cmdWin.getComponent(0).getViewport.getComponent(0);
catch
commandwindow;
jTextArea = jDesktop.getMainFrame.getFocusOwner;
end
%# read the current selection
jTxt = jTextArea.getSelectedText;
%# turn into Matlab text
currentSelection = jTxt.toCharArray'; %'
%# display
disp(currentSelection)
I don't believe there is any way to control or read the selection from the Matlab text editor, there is no mention of such an API on the Mathworks website (at least from a quick search on Google). If you want this functionality to enable more advanced text editing, then you might want to consider setting the .m file editor to an external editor (http://www.mathworks.com/access/helpdesk/help/techdoc/matlab_env/brxijcd.html). It may be possible to read the selection from a UIcontrol in a custom GUI, but I don't think this is what you want.
In case you want to use something like this but with text highlighted in the editor rather than in the command window.
I use the following code in order to be able to quickly check the nnz() of a variable, although you can change the code in the nested try-catch to whatever you need.
Lastly, I created a shortcut with this code in the top right of Matlab, which I access quickly by pressing Alt-1.
try
activeEditor = matlab.desktop.editor.getActive;
currentSelection = activeEditor.SelectedText;
try
eval(sprintf('val = nnz(%s);',currentSelection))
disp(sprintf('>> nnz(%s) = %s',currentSelection,num2str(val)))
catch ex
disp(ex.message)
end
catch ex
disp(ex.message)
end