/** * Copyright (c) 2009-2012 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.preferences; import java.util.Arrays; import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.ITextSelection; import org.eclipse.ui.texteditor.ITextEditor; import com.mulgasoft.emacsplus.EmacsPlusActivator; import com.mulgasoft.emacsplus.commands.INonEditingCommand; import com.mulgasoft.emacsplus.commands.PreferenceHandler; import com.mulgasoft.emacsplus.minibuffer.BooleanMinibuffer; import com.mulgasoft.emacsplus.minibuffer.ExecutingMinibuffer; import com.mulgasoft.emacsplus.minibuffer.IMinibufferExecutable; import com.mulgasoft.emacsplus.minibuffer.IMinibufferState; import com.mulgasoft.emacsplus.minibuffer.EvalMinibuffer; import com.mulgasoft.emacsplus.minibuffer.StrictMinibuffer; import com.mulgasoft.emacsplus.minibuffer.ReadNumberMinibuffer; import com.mulgasoft.emacsplus.minibuffer.TextMinibuffer; /** * Set preference variables to a value dynamically * * @author Mark Feber - initial API and implementation */ public class EvalHandler extends PreferenceHandler implements IMinibufferExecutable, INonEditingCommand { private final static String PROMPT = ": "; //$NON-NLS-1$ private final static String INIT = "M-"; //$NON-NLS-1$ private final static String ABORT = EmacsPlusActivator.getResourceString("Exec_Abort"); //$NON-NLS-1$ private final static String SV = EmacsPlusActivator.getResourceString("Set_Variable"); //$NON-NLS-1$ // the state object for linked minibuffers protected IMinibufferState mbState = null; enum EvalType { setq(SV), eval; EvalType(){} EvalType(String prompt){typePrompt = prompt;} String typePrompt = null; /** * @see java.lang.Enum#toString() */ @Override public String toString() { return (typePrompt != null ? typePrompt : super.toString()); } }; protected String getTypePrompt(EvalType e) { return e.name(); } /** * @see com.mulgasoft.emacsplus.commands.EmacsPlusCmdHandler#transform(org.eclipse.ui.texteditor.ITextEditor, * org.eclipse.jface.text.IDocument, org.eclipse.jface.text.ITextSelection, * org.eclipse.core.commands.ExecutionEvent) */ @Override protected int transform(ITextEditor editor, IDocument document, ITextSelection currentSelection, ExecutionEvent event) throws BadLocationException { if (isUniversalPresent()) { // show only mbState = variableState(EvalType.eval); mbState.run(editor); } else { mbState = evalState(INIT+PROMPT); return mbState.run(editor); } return NO_OFFSET; } private IMinibufferState evalState(final String prompt) { return new IMinibufferState() { public String getMinibufferPrefix() { return prompt; } public int run(ITextEditor editor) { miniTransform( new StrictMinibuffer(EvalHandler.this, Arrays.asList(EvalType.eval.name(), EvalType.setq.name()), true) {}, editor, null); return NO_OFFSET; } public boolean executeResult(ITextEditor editor, Object minibufferResult) { EvalType type = null; if (minibufferResult != null) { try { type = EvalType.valueOf((String) minibufferResult); } catch (Exception e) { } // ignore } if (type != null) { mbState = variableState(type); mbState.run(editor); } else { setResultMessage(ABORT, true, editor); } return true; } }; } /** * Get state object to handle variable selection * * @param prompt the minibuffer prompt * @return the variable minibuffer state object */ IMinibufferState variableState(final EvalType type) { return new IMinibufferState() { public String getMinibufferPrefix() { return getTypePrompt(type) + PROMPT; } public int run(ITextEditor editor) { miniTransform(new EvalMinibuffer(EvalHandler.this), editor, null); return NO_OFFSET; } public boolean executeResult(ITextEditor editor, Object minibufferResult) { boolean result = true; if (minibufferResult != null && minibufferResult instanceof PrefVars) { PrefVars var = (PrefVars) minibufferResult; transitionState(editor, var); } return result; } private void transitionState(ITextEditor editor, PrefVars var) { switch (type) { case eval: setResultMessage(var.getValue().toString(), false, editor); break; case setq: switch (var.getType()) { case BOOLEAN: mbState = trueFalseState(var); mbState.run(editor); break; case INTEGER: mbState = numberState(var); mbState.run(editor); break; case RECT: case STRING: mbState = stringState(var); mbState.run(editor); break; default: break; } break; } } }; } /** * Get state to handle true/false prompt * * @param var the variable object we're setting * @return true/false minibuffer state object */ private IMinibufferState trueFalseState(final PrefVars var) { return new IMinibufferState() { public String getMinibufferPrefix() { return getTypePrompt(EvalType.setq) + ' ' + var.name() + PROMPT; } public int run(ITextEditor editor) { miniTransform(new BooleanMinibuffer(EvalHandler.this), editor, null); return NO_OFFSET; } public boolean executeResult(ITextEditor editor, Object minibufferResult) { boolean result = true; if (minibufferResult != null && minibufferResult instanceof Boolean) { var.setValue(minibufferResult); setResultMessage(minibufferResult.toString(), false, editor); } else { setResultMessage(ABORT, true, editor); } return result; } }; } private IMinibufferState numberState(final PrefVars var) { return new IMinibufferState() { public String getMinibufferPrefix() { return getTypePrompt(EvalType.setq) + ' ' + var.name() + PROMPT; } public int run(ITextEditor editor) { miniTransform(new ReadNumberMinibuffer(EvalHandler.this), editor, null); return NO_OFFSET; } public boolean executeResult(ITextEditor editor, Object minibufferResult) { boolean result = true; if (minibufferResult != null && minibufferResult instanceof Integer) { var.setValue(minibufferResult); setResultMessage(minibufferResult.toString(), false, editor); } else { setResultMessage(ABORT, true, editor); } return result; } }; } /** * Return a minibuffer state object for reading and setting a string value. The string read may be * free form, or limited by a set of values defined by an enum on the preference declaration. * * @param var * @return */ private IMinibufferState stringState(final PrefVars var) { return new IMinibufferState() { public String getMinibufferPrefix() { return EvalType.setq.name() + ' ' + var.name() + PROMPT; } public int run(ITextEditor editor) { String[] pvalues = var.getPossibleValues(); ExecutingMinibuffer mini = null; if (pvalues != null) { mini = new StrictMinibuffer(EvalHandler.this, Arrays.asList(pvalues), true) {}; } else { mini = new TextMinibuffer(EvalHandler.this); } miniTransform(mini, editor, null); return NO_OFFSET; } public boolean executeResult(ITextEditor editor, Object minibufferResult) { boolean result = true; if (minibufferResult != null) { var.setValue(minibufferResult.toString()); setResultMessage(minibufferResult.toString(), false, editor); } else { setResultMessage(ABORT, true, editor); } return result; } }; } /** * Dispatch through state object * * @see com.mulgasoft.emacsplus.commands.MinibufferHandler#getMinibufferPrefix() */ @Override public String getMinibufferPrefix() { return mbState.getMinibufferPrefix(); } /** * Dispatch through state object * * @see com.mulgasoft.emacsplus.minibuffer.IMinibufferExecutable#executeResult(org.eclipse.ui.texteditor.ITextEditor, * java.lang.Object) */ public boolean executeResult(ITextEditor editor, Object minibufferResult) { return mbState.executeResult(editor, minibufferResult); } /** * Set and show the result of the last minibuffer in sequence * * @see com.mulgasoft.emacsplus.minibuffer.IMinibufferExecutable#setResultMessage(java.lang.String, * boolean) */ public void setResultMessage(String resultMessage, boolean resultError, ITextEditor editor) { super.setResultMessage(resultMessage, resultError); showResultMessage(editor); } }