Following my EditorMacro post a couple of weeks ago, which showed how to assign a keyboard macro to the integrated Matlab Editor, several people have asked me whether it is possible to assign a macro to non-textual actions, in addition to the text insertion/replacement which EditorMacro supports.
The quick answer is yes, with some careful programming. Instead of specifying the end result, I will use this opportunity to illustrate how Java objects (not just the editor) can be inspected for their supported actions/properties.
Our first step is to get the requested Java reference handle. This can be done via the Matlab Command Window (interested readers can look at the EditorMacro.m source code, specifically at its getJEditor() function). However, a much easier way is to assign some macro using EditorMacro and then simply place a breakpoint in EditorMacro’s keyPressedCallback() callback function. Then press an arrow key (or any other key) in the editor, and wait for the breakpoint focus to arrive (don’t forget to clear the breakpoint…). From here on, all our actions will be done in the Command Window.
We now have a variable called jEditorPane, which is a reference to a Java object of type javahandle_withcallbacks. com.mathworks.mde.editor.EditorSyntaxTextPane (in Matlab 7 – it’s something similar in Matlab 6). This is a Matlab wrapper for the basic Java object, used for accessing the callback hooks, as explained in a previous post. In our case we are not interested in this wrapper but in its wrapped object, which is retrieved via Matlab’s built-in java function (java(jEditorPane) or jEditorPane.java). The inspection itself is done using Matlab’s standard tools (inspect, methodsview etc.) or via my UIINSPECT utility. I suggest using UIINSPECT, which displays all the information of the standard tools and lots extra, but I’m of course biased…
Without diving into all the UIINSPECT options (I shall do this in a dedicated post), we see the supported methods/actions on the left, and properties on the right. It is true that none of them are documented, but many are self-explanatory. For example, the cut()/copy()/paste() methods or the caretPosition/caretColor properties. Any combination of these methods and properties can be used in a user-defined macro.
Let’s do a simple example, setting the <Ctrl-E> combination to a macro moving to the end-of-line (unix-style – equivalent to <End> on Windows), and <Ctrl-Shift-E> to a similar macro doing the same while also selecting the text (like <Shift-End> on Windows). We shall even use the same macro code, by simply checking in the eventData whether the <Shift> key is depressed:
function EOL_Macro(hDocument,eventData) % Find the position of the next EOL mark currentPos = hDocument.getCaretPosition; docLength = hDocument.getLength; textToEOF = char(hDocument.getTextStartEnd(currentPos,docLength)); nextEOLPos = currentPos+find(textToEOF<=13,1)-1; % next CR/LF pos if isempty(nextEOLPos) % no EOL found (=> move to end-of-file) nextEOLPos = docLength; end % Do action based on whether <Shift> was pressed or not %get(eventData); if eventData.isShiftDown % Select to EOL hDocument.moveCaretPosition(nextEOLPos); else % Move to EOL (without selection) hDocument.setCaretPosition(nextEOLPos); end end % EOL_Macro
…and now let’s activate this macro in the Matlab Command Window:
>> macros = EditorMacro('ctrl-e',@EOL_Macro,'run'); >> macros = EditorMacro('ctrl-shift-e',@EOL_Macro,'run') macros = 'ctrl alt pressed T' @(a,b)datestr(now) 'text' 'ctrl pressed E' @EOL_Macro 'run' 'shift ctrl pressed E' @EOL_Macro 'run'
Please do explore all the possible actions/properties exposed by the jEditorPane object. Probably the worst that could happen (and very rarely) is that you’ll crash Matlab and need to restart it – no biggy. If you find an interesting macro combination, please post it to the File Excahnge, and/or let us all know by placing a comment below.