File Exchange

image thumbnail

EditorMacro - assign a macro to a keyboard key-stroke in the Matlab Editor and Command Window

version 1.3.0.0 (11.4 KB) by Yair Altman
EditorMacro assigns a macro or action to requested key-binding in the Matlab Editor & Command Window

2 Downloads

Updated 31 Jan 2011

View Version History

View License

Syntax:
[bindingsList, actionsList] = EditorMacro(keystroke, macro, macroType)
[bindingsList, actionsList] = EditorMacro(bindingsList)

Description:
EditorMacro assigns the specified MACRO to the requested keyboard KEYSTROKE, within the context of the Matlab Editor and Command Window.

KEYSTROKE is a string representation of the keyboard combination. Special modifiers (Alt, Ctrl or Control, Shift, Meta, AltGraph) are recognized and should be separated with a space, dash (-), plus (+) or comma (,). If KEYSTROKE was already defined, then it will be updated (overridden).

MACRO should be in one of Matlab's standard callback formats: 'string', @FunctionHandle or {@FunctionHandle,arg1,...}, or any of several hundred built-in editor action-names - read MACROTYPE below for a full description. To remove a KEYSTROKE-MACRO definition, simply enter an empty MACRO ([], {} or '').

MACROTYPE is an optional input argument specifying the type of action that MACRO is expected to do:

- 'text' (=default value) indicates that if the MACRO is a:
1. 'string': this string will be inserted as-is into the current
editor caret position (or replace selected editor text).
Multi-line strings can be set using embedded \n's.
2. @FunctionHandle - the specified function will be invoked
and is expected to return a string which will then be inserted
into the editor document as expained above.
3. {@FunctionHandle,arg1,...} - like #2, but the function will
be called with the specified args.

- 'run' indicates that MACRO should be invoked as a Matlab
command, just like any regular Matlab callback. The
accepted MACRO formats and function input args are
exactly like for 'text' above, except that no output
string is expected and no text insertion/replacement
will be done, useful for non-textual actions.

In addition, this MACROTYPE accepts all available
(built-in) editor action names. Valid action names can
be listed by requesting the ACTIONSLIST output arg.

BINDINGSLIST = EditorMacro returns the list of currently-defined KEYSTROKE bindings as a 4-columned cell array:{keystroke,macro,type,class}. The class information indicates a built-in action ('editor menu action', 'editor native action', 'cmdwin native action' or 'cmdwin menu action') or a user-defined action ('text' or 'user-defined macro').

BINDINGSLIST = EditorMacro(KEYSTROKE) returns the bindings list for the specified KEYSTROKE as a 4-columned cell array: {keystroke, macro, type, class}.

BINDINGSLIST = EditorMacro(KEYSTROKE,MACRO) returns the bindings list after defining a specific KEYSTROKE-MACRO binding.

EditorMacro(BINDINGSLIST) can be used to set a bunch of key bindings using a single command. BINDINGSLIST is the cell array returned from a previous invocation of EditorMacro, or by manual construction.

[BINDINGSLIST, ACTIONSLIST] = EditorMacro(...) returns in ACTIONSLIST a 3-columned cell array of all available built-in actions and currently-associated key-biding(s): {actionName, keyBinding(s), class}.

Usage Examples:
bindingsList = EditorMacro; % get list of current key-bindings
bindingsList = EditorMacro('ctrl r'); % get list of bindings for <Ctrl>-R
[bindings,actions] = EditorMacro; % get list of available built-in action-names
EditorMacro('Ctrl Shift C', '%%% Main comment %%%\n% \n% \n% \n');
EditorMacro('Alt-x', 'try\n % Main code here\ncatch\n % Exception handling here\nend');
EditorMacro('Ctrl-Alt C', @myCallbackFunction); % myCallbackFunction returns a string to insert
EditorMacro('Alt control t', @(a,b)datestr(now), 'text'); % insert current timestamp
EditorMacro('Shift-Control d', {@computeDiameter,3.14159}, 'run');
EditorMacro('Alt L', 'to-lower-case', 'run') % Built-in action: convert text to lowercase
EditorMacro('ctrl D','open-selection','run') % Override default Command-Window action (=delete) to behave as in the Editor (=open selected file)

A few known limitations (=TODO for future versions) are listed within the file's help section.

Bugs and suggestions:
EditorMacro was tested on Matlab 6.0 (R12) through 7.7(R2008b).

Note: Unfortunately, my Matlab 6 computer crashed since the first version so I can no longer test EditorMacro on Matlab 6, so if you find problems please email me directly.

Please send bugs to Yair Altman (altmany at gmail dot com)

Warning:
This code heavily relies on undocumented and unsupported
Matlab functionality. It works on Matlab 6 & 7+, but use at
your own risk!

A technical description of the implementation can be found at: http://UndocumentedMatlab.com/blog/EditorMacro/

Cite As

Yair Altman (2020). EditorMacro - assign a macro to a keyboard key-stroke in the Matlab Editor and Command Window (https://www.mathworks.com/matlabcentral/fileexchange/24615-editormacro-assign-a-macro-to-a-keyboard-key-stroke-in-the-matlab-editor-and-command-window), MATLAB Central File Exchange. Retrieved .

Comments and Ratings (26)

Can some one help to get and set the context menu for matlab editor ?

sfreeman

Still excellent code from Yair!
I did some more Version tests on Yigal's code, which works also in some 8.x Versions (using Options: EditorMacro('Ctrl Alt H', @someFcn, 'text') ):

R2006b/7.3 - fail
R2005b/7.5 - fail
R2006a/7.6 - fail
R2010bSP1/7.11.1 pass
R2012b/8.0 pass
R2013b/8.2 fail
R2014a/8.3 pass
R2016a/9.0 pass
R2016b/9.1 pass
R2017b/9.3 pass

Here is what I use currently for the getEditorPane function:

%% Get EditorPane
function hEditorPane = getEditorPane(jDocPane)

nVersion = sscanf(version,'%d.');
if nVersion(1) == 6
% Matlab 6 (no tests done)
hEditorPane = getDescendent(jDocPane,[0,0,0,0]);
if isa(hEditorPane,'com.mathworks.mwt.MWButton') % edge case
hEditorPane = getDescendent(jDocPane,[0,1,0,0]);
end

elseif nVersion(1) == 7 || (nVersion(1)==8 && nVersion(2)<2)
try
% Matlab 7 (tested in R2010bSP1/7.11.1, R2012b/8.0; failed in
% R2006b/7.3, R2007b/7.5, R2008a/7.6, R2013b/8.2)
jSyntaxTextPaneView = getDescendent(jDocPane,[0,0,1,0,0,0,0]);
if isa(jSyntaxTextPaneView,'com.mathworks.widgets.SyntaxTextPaneMultiView$1')
hEditorPane(1) = handle(getDescendent(jSyntaxTextPaneView.getComponent(1),[1,0,0]),'CallbackProperties');
hEditorPane(2) = handle(getDescendent(jSyntaxTextPaneView.getComponent(2),[1,0,0]),'CallbackProperties');
else
jEditorPane = getDescendent(jSyntaxTextPaneView,[1,0,0]);
hEditorPane = handle(jEditorPane,'CallbackProperties');
end
catch ME
fprintf(2,'Correct implementation for EditorMacro:getEditorPane is missing!');
rethrow(ME);
end

else
try
% Matlab 8.3 and above (tested in R2014a/8.3, R2016a/9.0,
% R2016b/9.1, R2017b/9.3; failed in R2013b/8.2)
if isa(jDocPane,'com.mathworks.widgets.desk.DTDocumentTabs') % We picked the wrong document.
jDocPane=jDocPane.getParent.getComponent(1);
end
jSyntaxTextPaneView = getDescendent(jDocPane,[0,1,0,0,0,0,1,0,0]);
hEditorPane = handle(jSyntaxTextPaneView,'CallbackProperties');
catch ME
fprintf(2,'Correct implementation for EditorMacro:getEditorPane is missing!');
rethrow(ME);
end
end

Yigal Shenkman

@Devin, I believe you have a small bug - the line
if isa(jDocPane,'com.mathworks.widgets.desk.DTDocumentTabs')
should be followed only by updating jDocPane, and jSyntaxTextPaneView, hEditorPane should be set anyway.
this is what the code should be:

function hEditorPane = getEditorPane(jDocPane)
ver=version;
if str2double(ver(1))==9
if isa(jDocPane,'com.mathworks.widgets.desk.DTDocumentTabs') %We picked the wrong document.
jDocPane=jDocPane.getParent.getComponent(1);
end
jSyntaxTextPaneView = getDescendent(jDocPane,[0,1,0,0,0,0,1,0,0]);
hEditorPane = handle(jSyntaxTextPaneView,'CallbackProperties');
else
try

% Matlab 7 TODO: good for ML 7.1-7.7: need to check other versions
jSyntaxTextPaneView = getDescendent(jDocPane,[0,0,1,0,0,0,0]);
if isa(jSyntaxTextPaneView,'com.mathworks.widgets.SyntaxTextPaneMultiView$1')
hEditorPane(1) = handle(getDescendent(jSyntaxTextPaneView.getComponent(1),[1,0,0]),'CallbackProperties');
hEditorPane(2) = handle(getDescendent(jSyntaxTextPaneView.getComponent(2),[1,0,0]),'CallbackProperties');
else
jEditorPane = getDescendent(jSyntaxTextPaneView,[1,0,0]);
hEditorPane = handle(jEditorPane,'CallbackProperties');
end
catch
% Matlab 6
hEditorPane = getDescendent(jDocPane,[0,0,0,0]);
if isa(hEditorPane,'com.mathworks.mwt.MWButton') % edge case
hEditorPane = getDescendent(jDocPane,[0,1,0,0]);
end
end
end

Devin O

A fix for R2016a (possibly earlier?), at least for adding a macro, is to replace the function hEditorPane with the below:
______________
function hEditorPane = getEditorPane(jDocPane)
ver=version;
if str2double(ver(1))==9
if isa(jDocPane,'com.mathworks.widgets.desk.DTDocumentTabs') %We picked the wrong document.
jDocPane=jDocPane.getParent.getComponent(1);
jSyntaxTextPaneView = getDescendent(jDocPane,[0,1,0,0,0,0,1,0,0]);
hEditorPane = handle(jSyntaxTextPaneView,'CallbackProperties');
end
else
try

% Matlab 7 TODO: good for ML 7.1-7.7: need to check other versions
jSyntaxTextPaneView = getDescendent(jDocPane,[0,0,1,0,0,0,0]);
if isa(jSyntaxTextPaneView,'com.mathworks.widgets.SyntaxTextPaneMultiView$1')
hEditorPane(1) = handle(getDescendent(jSyntaxTextPaneView.getComponent(1),[1,0,0]),'CallbackProperties');
hEditorPane(2) = handle(getDescendent(jSyntaxTextPaneView.getComponent(2),[1,0,0]),'CallbackProperties');
else
jEditorPane = getDescendent(jSyntaxTextPaneView,[1,0,0]);
hEditorPane = handle(jEditorPane,'CallbackProperties');
end
catch
% Matlab 6
hEditorPane = getDescendent(jDocPane,[0,0,0,0]);
if isa(hEditorPane,'com.mathworks.mwt.MWButton') % edge case
hEditorPane = getDescendent(jDocPane,[0,1,0,0]);
end
end
end
___________

I'm not certain about earlier releases, but one may try replacing the line.
if str2double(ver(1))==9
with
if str2double(ver(1))>7

Boris Capitanu

+1 for 2014b compatibility
Thank you!

Xavier

I've been considering moving over to an external editor for a while and just came across this tool, which seems to provide all the functionality I'm looking for... except it does not appear to be supported in 2014b.
Does anyone know of an alternative?

Thierry Dalon

On Windows the accelerators using meta or AltGraph seem not to work.

Yair Altman

@Jim - not anytime soon I'm afraid...

Jim Hokanson

@Yair
Any plans to update this code to work with Matlab 8?

Thierry Dalon

EditorMacro('ctrl D','open-selection','run') as in example
throw an error with Matlab >=8.

alessandro

it does what it promises, though too bad you can use this only when your cursor is on the editor and command window. I would have liked to assign a key shortcut to close all figures ("close all" command)

Cesare

Btillian! Will you really release a version with Multi-keystroke bindings? That would be awsome!

Yair Altman

@Nicolas - please contact me via email (altmany at gmail dot com) - I would be happy to show you how to do this, for a small fee to cover my time and expertise.

Nicolas

Great work,
is there a way to get access to the array whose name was highlighted?

eg. I want to be able to display the selected image:

function DisplayImage(hDocument,eventData)
.
.
.
figure;
imshow(TheImageMatrix,[]);
end

Thanks
N

Doesn't work for me.
Fails when try to get the properties from the com variable (which does not exist in my matlab 6.5.1, release 13)

David Gittins

Yair, possible workaround for the issue I mention. I commented out line 205:

% Also instrument the CW to catch user keystrokes
%set(jCmdWin, 'KeyPressedCallback', {@keyPressedCallback,jEditor,appdata,jCmdWin});

Now the tab-complete in the command window seems to work as normal, and I can still use the macros in the editor. I can't use the macros at the command window but that is fine for me because I only need them in the editor.

Maybe you could add an "editor only" option.

HTH

David Gittins

Yair, this is brilliant and exactly what I am looking for...

...but I can't use it! As soon as I bind any macros, tab completion for variables stops working in the command window. It just shows "No Completions Found". Tab-completion for files continues to work.

I think "Les" found the same issue:
http://www.mathworks.com/matlabcentral/fileexchange/25217-intelligent-code-completion-for-matlab

I am running R2010a on CentOS.

D

David Gittins

Andrey Pudeyev

Great work, just the very thing I missed in a matlab interface - a customizable macro.

Summarizing the examples of posted here, i propose the following solution for exception management:
-----------
function trycatch(hDocument,eventData)
% Get Selected text in current editor
selectedText = char(hDocument.getSelectedText);

modifiedText = ['try' char(13) selectedText char(13) 'catch' char(13) 'keyboard' char(13) 'end'];

% Update selection in current editor
hDocument.replaceSelection(modifiedText);
--------------

This will allow quickly put the selected text block inside try-catch construction

Andrey Pudeyev

Yair Altman

For those interested, a set of EditorMacro macro functions has been submitted by Perttu Ranta-aho. The submission is called "TextTools" and can be found here: http://www.mathworks.com/matlabcentral/fileexchange/25122

Ustun Ozgur

EditorMacro('Alt-x', 'try\n % Main code here\ncatch\n % Exception handling here\nend');

does not work in OS X with Matlab R2008b.

EditorMacro('Meta x', 'try\n % Main code here\ncatch\n % Exception handling here\nend');

works however.

Julien

Excellent work indeed, thank you very much for sharing this very useful and powerful function.
For users which would be interested in modifying selected text and not inserting new text at caret position, you can use the jEditorPane methods "getSelectedText" and "replaceSelection".
For example, if you want to transform selected text in current editor to upper case characters, you can do as follow :
---------------------------------------------------------------------------
function Upper_Macro(hDocument,eventData)
% Get Selected text in current editor
selectedText = char(hDocument.getSelectedText);
if isempty(selectedText)
return;
end
% Modify selected text to upper case character
modifiedText = upper(selectedText);
% Update selection in current editor
hDocument.replaceSelection(modifiedText);
---------------------------------------------------------------------------
And simply run in the command window :
>>macros = EditorMacro('ctrl-u',@Upper_Macro,'run');
---------------------------------------------------------------------------
Thank you again Yair !

Qun HAN

WOW!

Jackson Shen

I have tried again today. It "magically" works.
Yes, it does with with the Matlab R2008A.
I must say I love this feature.

Jackson Shen

Exellent Work. It works with R2009A (Trial).
Brillian Features! (not for me at moment).
Unfornuately, it does not work with my R2008A.

MATLAB Release Compatibility
Created with R12
Compatible with any release
Platform Compatibility
Windows macOS Linux

Community Treasure Hunt

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

Start Hunting!