views:

551

answers:

6

^ is the exponential operator in MATLAB. The problem with it is that it isn't present on a lot of non-english keyboard layouts, and if you use it a lot in your work, switching between HR and EN becomes troublesome.

Is there a way to add it to MATLAB's toolbar (like in Excel, so you can use it via mouse or touchpad), or to define a custom key (for example, F12) in MATLAB to replace it?

I'm hoping for a non AHK solution, and the like.

+6  A: 

I would suggest downloading the submission EditorMacro from Yair Altman on the MathWorks File Exchange. If you ran the following code in the MATLAB Command Window (while the MATLAB Editor was open):

EditorMacro('Alt 6','^');

it would create a macro within the context of the MATLAB Editor and Command Window that would insert the string ^ at the caret position when you hit the key combination Alt+6 (which shouldn't be tied to any other macro/operation as far as I know).

Since you mention switching back and forth between a Croatian and English keyboard layout, it is probably annoying having to memorize different key combinations for the same symbols. Using EditorMacro, you could create a set of macros in the MATLAB Editor and Command Window that would allow you to use the same set of key presses for each symbol regardless of the type of keyboard you were using.

Since the macros made with EditorMacro are removed each time MATLAB is closed, you could create a startup.m file (which will be automatically run each time MATLAB is opened) to create the macros for you. The file could look something like this:

edit;                      %# Open the Editor so EditorMacro works properly
EditorMacro('Alt 5','%');  %# Create "%" macro
EditorMacro('Alt 6','^');  %# Create "^" macro
EditorMacro('Alt 7','&');  %# Create "&" macro
...

In this example, I am basically reproducing the behavior of Shift plus a number on an English keyboard using Alt instead.


And if all else fails...

You can always use the functional forms of the arithmetic operators as a last resort:

  • power(A,B) instead of the element-wise power operation A.^B
  • mpower(A,B) instead of the matrix power operation A^B

It won't be pretty, but it'll work.

gnovice
Sorry, but that's out of the question. They're nice for shorter equations, but some of these are already several rows like this ...
ldigas
@Idigas: I added a new solution that may be more to your liking. ;)
gnovice
Indeed, it is. Actually, the idea is interesting enough to be used for some other purposes as well. I won't give you an +A since it wouldn't be fair to ..., but let me at least say thanks by upping you up by a few rep points in your other answers.
ldigas
+10  A: 

In Windows (with Num Lock on), hold down Alt, type 94 on the numeric keypad, and release Alt. The ^ will be inserted at the cursor.

This is the general technique for inserting arbitrary Unicode characters in Windows, regardless of whether they're on the keyboard.

The ^ character is U+5E, which is 94 in decimal.

Andrew Janke
Wow, I'd forgotten about that trick. +1.
mtrw
Not to happy with that either ... on a laptop keyboard, without a numpad, using those combinations is a pain. I do appreciate the answer, as so it is not wrongly understood, it's just I'm still hoping someone will give some *magic* solution for it :)
ldigas
+10  A: 

Create a toolbar shortcut, give it a name, and put the following in the callback:

clipboard('copy','^')

Running this will place the exponent character ^ in your clipboard. Once you press it, do a Ctrl+V to paste it.

You can apply this idea to create a clip library of snippets accessible from MATLAB's Start menu.

Amro
Now this is interesting ... is there a way to integrate the Ctrl+V step in the shortcut as well ?
ldigas
So upon pressing it, it directly pastes it ...
ldigas
Im afraid not, it only places it in the clipboard (but then Ctrl+V is almost a reflex for me!)
Amro
Oh, well ... this is still the best solution yet. While I'm writing stuff in, I don't usually have anything valuable in the clipboard anyways ... thanks Amro !!
ldigas
+1  A: 

You could just simply use the following mathematical identity:

a^b ≡ exp(b*ln(a))

I was just about to suggest the C-style POWER(A,B) function to replace the functionality of the ^ operator, but gnovice beat me to it. I would imagine this is what the POWER(A,B) and MPOWER(A,B) functions are based on.

As you can see from the answers posted, there are many alternatives. It's a matter of taste, functionality and repetition.

Zaid
Yes, well ... matlab for starters, doesn't have ln, but log. Second, my expressions usually look like this: = (c^2/(E*h^3)) * (-(1/8)*R^2 * zetaA^2 * (2*log(zetaA)-1)) + ... (4 rows to follow). So I hardly think I'll ever be going with anything other than an operator (in terms of power function and such) ...
ldigas
not to mention numerical precision issues introduced by **log** and **exp**
Amro
+3  A: 

Which keyboard do you have that it is not on?

http://msdn.microsoft.com/en-us/goglobal/bb964651.aspx

We did a quick check after seeing this question, and could not find a keyboard without the symbol.

Talked to our MATLAB I18N team about this and put in an enhancement request.

MatlabDoug
This was stated in the original question. HR = Hungarian I imagine.
Matt Kellogg
Nevermind. Googled it, I guess it's Croation, and you can get the ^ using AltGr+3, can't you?
Matt Kellogg
Yes, it's croatian (HR = Hrvatska). @Matt - I didn't know about AltGr+3. Intesting. But why does it needs to be pressed twice ? And only then it will give two symbols ^^ ? I cannot get only one ^ on it.
ldigas
@Idigas On many of non-English keyboards such as French or Swedish, ^ and ~ are called dead key because pressing those key do not produce input until you press something else like e or o to enter ê or ô etc.
MatlabDoug
Interesting. Although, hmm, ... that kind of behaviour is an accident waiting to happen in typing, if you ask me (type ^, then something, only to see you didn't get what you wanted but either a^^c or ac). @MatlabDoug - another question, if I may? If anybody knows, you'll be the one ... how come matlab chose ^ for exponential op? In the time when it was written, "the usual" was fortran's ** (C didn't have it, I think it still doesn't). What was the reason for the change ? ** makes sense in analogy with *, also.
ldigas
In the upper comment, it should've been fortran's ** <-- two stars
ldigas
My guess is that it is shorthand for superscript. I will ask Loren or Cleve next time I see them and report back if there is a different reason.
MatlabDoug
+1  A: 

Okay... Here is a hack that allows you to remap arbitrary keystrokes in Matlab's Command Window and Editor. This is an unsupported hack that involves undocumented internals of the IDE. But it's "magic" like you were hoping for. Works in R2008b and R2009b for me.

First, define a Java class that can handle events by replacing them with other keystroke input. Compile this to a JAR and get it on your Matlab's javaclasspath.

package test;

import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.text.JTextComponent;
import javax.swing.text.TextAction;

/**
 * An action that responds to an event with another keystroke.
 */
public class KeyReplacementAction extends TextAction {

    private final char replacement;

    /**
     * @param name Name of this action (ignored in practice)
     * @param replacement char to replace the event with
     */
    public KeyReplacementAction(String name, char replacement) {
        super(name);
        this.replacement = replacement;
    }

    public void actionPerformed(ActionEvent e) {
        if (!(e.getSource() instanceof JTextComponent)) {
            return;
        }
        JTextComponent src = (JTextComponent) e.getSource();
        KeyEvent replacementEvent = new KeyEvent(src, KeyEvent.KEY_TYPED, 
                java.lang.System.currentTimeMillis(), 0,
                KeyEvent.VK_UNDEFINED, replacement);
        src.dispatchEvent(replacementEvent);
    }

}

Now, use Matlab code to dig into the IDE's Swing widgets, find the keymaps for the editor and command window, and add handlers for the remapping to them.

function remap_keys_in_text_areas()
%REMAP_KEYS_IN_TEXT_AREAS Custom key remapping in Matlab GUI text areas
%
% Must be called after the editor is open, otherwise it won't find the
% editor keymap.

% { from, to; ... }
% Try "disp(char(1:1024))" to see all chars that work in your Matlab font
map = {
    '$' '^'
    '#' char(181)  % might be useful for text formatting
    };

make_sure_editor_is_open(); % otherwise we won't find its keymap

keymaps = find_ide_keymaps();
for i = 1:size(map,1)
    [from,to] = map{i,:};
    disp(sprintf('Re-binding %s to %s in text areas', from, to));
    for j = 1:numel(keymaps)
        bind_keystroke_for(keymaps{j}, from, to);
    end
end

function make_sure_editor_is_open()
s = find_editor_widgets();
if isempty(s.editors)
    edit;
end

function bind_keystroke_for(keymap, from, to)
%BIND_KEYSTROKE_FOR Remap a single keystroke in a text component

import javax.swing.KeyStroke;
import java.awt.event.InputEvent;
import test.KeyReplacementAction;

key = javax.swing.KeyStroke.getKeyStroke(from);
action = KeyReplacementAction(['remap ' from ' to ' to], to);
keymap.addActionForKeyStroke(key, action);

function out = find_ide_keymaps
%FIND_IDE_KEYMAPS Find keymap objects for Matlab IDE widgets
set = java.util.HashSet();
s = find_editor_widgets();
widgets = [s.cmdwin s.editors];
for i = 1:numel(widgets)
    set.add(widgets{i}.getKeymap());
end
set = set.toArray();
out = cell(size(set));
for i = 1:numel(set)
    out{i} = set(i);
end

function out = find_editor_widgets
%FIND_EDITOR_WIDGETS Find editor and command window widgets in Matlab Swing GUI
out.cmdwin = [];
out.editors = {};
wins = java.awt.Window.getOwnerlessWindows();
for i = 1:numel(wins)
    if isa(wins(i), 'com.mathworks.mde.desk.MLMainFrame')
        out.cmdwin = get_command_window_from_mainframe(wins(i));
    elseif isa(wins(i), 'com.mathworks.mde.desk.MLMultipleClientFrame')
        out.editors = [out.editors get_text_areas_from_editor_frame(wins(i))];
    end
end

function out = get_command_window_from_mainframe(frame)
out = findobj_swing_widget(frame, 'com.mathworks.mde.cmdwin.XCmdWndView');

function out = get_text_areas_from_editor_frame(frame)
out = findobj_swing_widget(frame, 'com.mathworks.widgets.SyntaxTextPane');

function out = findobj_swing_widget(widget, klass)
%FINDOBJ_SWING_WIDGET Recursively find all child components of given class
out = {};
if isa(widget, klass)
    out{end+1} = widget;
end
for i = 1:widget.getComponentCount()
    out = [out findobj_swing_widget(widget.getComponent(i-1), klass)];
end

To activate the remappings, just call the function. You could do this from within startup.m to have it happen automatically.

>> remap_keys_in_text_areas
Re-binding $ to ^ in text areas
Re-binding # to µ in text areas
Andrew Janke