/**
* Copyright (c) 2009, 2010 Mark Feber, MulgaSoft
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
*/
package com.mulgasoft.emacsplus.commands;
import java.util.Map.Entry;
import java.util.Set;
import java.util.SortedMap;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import org.eclipse.core.commands.Command;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.common.NotDefinedException;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.swt.SWT;
import org.eclipse.ui.texteditor.ITextEditor;
import com.mulgasoft.emacsplus.EmacsPlusActivator;
import com.mulgasoft.emacsplus.execute.CommandHelp;
import com.mulgasoft.emacsplus.execute.CommandSupport;
import com.mulgasoft.emacsplus.execute.EmacsPlusConsole;
import com.mulgasoft.emacsplus.minibuffer.AproposMinibuffer;
/**
* Implement: apropos
*
* Display information about matching commands in the Emacs+ console
*
* @author Mark Feber - initial API and implementation
*/
public class CommandAproposHandler extends MinibufferExecHandler implements INonEditingCommand {
private static final String A_MSG = "["; //$NON-NLS-1$
private static final String Z_MSG = "] "; //$NON-NLS-1$
private static String APROPOS_PREFIX = EmacsPlusActivator.getResourceString("Cmd_Apropos_Prefix"); //$NON-NLS-1$
private static String APROPOS_FAIL = EmacsPlusActivator.getResourceString("Cmd_Fail"); //$NON-NLS-1$
private static String REGEX_WRAPPER = ".*"; //$NON-NLS-1$
private String prefix = APROPOS_PREFIX;
private String blanks;
public String getMinibufferPrefix() {
return prefix;
}
/**
* @see com.mulgasoft.emacsplus.commands.EmacsPlusCmdHandler#transform(ITextEditor, IDocument, ITextSelection, ExecutionEvent)
*/
@Override
protected int transform(ITextEditor editor, IDocument document, ITextSelection currentSelection,
ExecutionEvent event) throws BadLocationException {
return bufferTransform(new AproposMinibuffer(this), editor, event);
}
/**
* @see com.mulgasoft.emacsplus.minibuffer.IMinibufferExecutable#executeResult(org.eclipse.ui.texteditor.ITextEditor, java.lang.Object)
*/
public boolean doExecuteResult(ITextEditor editor, Object minibufferResult) {
printCommands(editor,(String)minibufferResult);
return true;
}
private void printCommands(ITextEditor editor, String apropos) {
CommandSupport commander = new CommandSupport();
SortedMap<String, Command>commandList = commander.getCommandList(editor);
String regApropos = apropos.trim();
if (regApropos.length() == 0) {
// detect empty string edge case
fail(editor,apropos);
return;
}
if (Character.isJavaIdentifierPart(regApropos.charAt(0))) {
regApropos = REGEX_WRAPPER + regApropos;
}
if (Character.isJavaIdentifierPart(regApropos.charAt(regApropos.length()-1))) {
regApropos = regApropos + REGEX_WRAPPER;
}
try {
Pattern.compile(apropos);
} catch (PatternSyntaxException p) {
fail(editor,apropos);
return;
}
// get all appropriate commands (including currently disabled ones) that match
SortedMap<String, Command> aproposTree = commander.getCommandSubTree(commandList, regApropos, true, true);
Set<Entry<String, Command>> entries = aproposTree.entrySet();
Set<String> keys = aproposTree.keySet();
if (!entries.isEmpty()) {
int maxLen = 0;
for (String key : keys) {
int len = key.length();
if (len > maxLen) {
maxLen = len;
}
}
StringBuilder nameBuf = new StringBuilder(maxLen);
for (int i=0; i < maxLen; i++) {
nameBuf.append(' ');
}
blanks = nameBuf.toString();
EmacsPlusConsole console = EmacsPlusConsole.getInstance();
console.clear();
console.activate();
for (Entry<String, Command> entry : entries) {
nameBuf.replace(0, maxLen, blanks);
nameBuf.replace(0, entry.getKey().length(), entry.getKey());
printCommand(nameBuf.toString(), entry.getValue(), console);
}
} else {
fail(editor,apropos);
}
}
private void fail(ITextEditor editor, String apropos) {
try {
prefix = APROPOS_FAIL;
this.showResultMessage(editor, apropos, true);
} finally {
prefix = APROPOS_PREFIX;
}
}
private void printCommand(String name, Command command, EmacsPlusConsole console) {
console.printBold(name + SWT.TAB);
String bindingStrings = CommandHelp.getKeyBindingString(command, true);
if (bindingStrings != null) {
console.printContext(A_MSG + bindingStrings + Z_MSG);
}
try {
String desc = command.getDescription();
if (desc != null) {
desc = desc.replaceAll(CR, CR + blanks + SWT.TAB);
console.print(desc + CR);
} else {
console.print(CR);
}
} catch (NotDefinedException e) {
}
}
}