Java tutorial
/** * 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 org.eclipse.core.commands.ExecutionEvent; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.ITextSelection; import org.eclipse.swt.custom.StyledText; import org.eclipse.ui.handlers.HandlerUtil; import org.eclipse.ui.texteditor.ITextEditor; import com.mulgasoft.emacsplus.EmacsPlusActivator; import com.mulgasoft.emacsplus.EmacsPlusUtils; import com.mulgasoft.emacsplus.IEmacsPlusCommandDefinitionIds; import com.mulgasoft.emacsplus.KillRing; import com.mulgasoft.emacsplus.preferences.EmacsPlusPreferenceConstants; /** * Implements: yank-pop * * Valid only if called immediately after a `yank' or a `yank-pop' * yank-pop deletes previous popped text and replaces it with the 'next' stretch of killed text. * * With no argument, then previous kill is inserted * With ARG, insert the ARGth 'previous' kill (ARG == 1 is the same as no argument) * With negative ARG, insert the ARGth 'next' kill * * @author Mark Feber - initial API and implementation */ public class YankPopHandler extends BaseYankHandler { // if true, then auto browse kill ring on invocation with no previous yank private static boolean autoBrowse = (Boolean) getPreference(EmacsPlusPreferenceConstants.P_AUTO_BROWSE_KR); private static final String YP_DISABLED = "YankPopHandler_0"; //$NON-NLS-1$ /** * Replace the yanked text with the previous yank and return the new offset * * @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 { if (KillRing.getInstance().isYanked()) { return (currentSelection.getOffset() + yankIt(document, currentSelection)); } else if (autoBrowse) { // Browse kill ring if true try { EmacsPlusUtils.executeCommand(IEmacsPlusCommandDefinitionIds.BROWSE_KILL_RING, null, editor); } catch (Exception e) { EmacsPlusUtils.showMessage(editor, EmacsPlusActivator.getString(YP_DISABLED), false); } } else { EmacsPlusUtils.showMessage(editor, EmacsPlusActivator.getString(YP_DISABLED), false); } return currentSelection.getOffset(); } protected int yankIt(IDocument document, ITextSelection selection) throws BadLocationException { int len = 0; KillRing kb = KillRing.getInstance(); String prevText = convertDelimiters(kb.lastYank()); String yankText = convertDelimiters(kb.yankPop()); if (yankText != null) { int origin = selection.getOffset() - prevText.length(); // in case selection has been mouse moved // Since our mouse listener would have to be on the StyledText widget if (prevText == null || !prevText.equals(document.get(origin, prevText.length()))) { kb.setYanked(false); return 0; } updateText(document, origin, prevText.length(), yankText); kb.setYanked(true); return yankText.length() - prevText.length(); } return len; } /** * Simulate yank pop * * @see com.mulgasoft.emacsplus.commands.BaseYankHandler#paste(org.eclipse.core.commands.ExecutionEvent, org.eclipse.swt.custom.StyledText) */ protected void paste(ExecutionEvent event, StyledText widget, boolean isProcess) { KillRing kb = KillRing.getInstance(); if (kb.isYanked()) { String cacheText = KillRing.getInstance().getClipboardText(); String prevText = convertDelimiters(kb.lastYank(), isProcess); String yankText = convertDelimiters(kb.yankPop(), isProcess); try { int offset = widget.getCaretOffset(); if (prevText == null || !prevText.equals(widget.getText(offset - prevText.length(), offset - 1))) { kb.setYanked(false); EmacsPlusUtils.showMessage(HandlerUtil.getActivePart(event), EmacsPlusActivator.getString(YP_DISABLED), false); return; } widget.setRedraw(false); widget.setSelection(offset - prevText.length(), offset); kb.setClipboardText(yankText); super.paste(event, widget); } finally { if (cacheText != null) { kb.setClipboardText(cacheText); } widget.setRedraw(true); } } else { EmacsPlusUtils.showMessage(HandlerUtil.getActivePart(event), EmacsPlusActivator.getString(YP_DISABLED), false); } } /** * Enable or disable auto browse of kill ring * * @param auto */ public static void setAutoBrowse(boolean auto) { YankPopHandler.autoBrowse = auto; } private static boolean getPreference(String key) { boolean result = false; IPreferenceStore store = EmacsPlusActivator.getDefault().getPreferenceStore(); if (store != null) { result = store.getBoolean(key); } return result; } }