Skip to content
Permalink
Browse files

Merge branch 'feature/indent-on-paste'

  • Loading branch information
kevinushey committed Oct 17, 2019
2 parents efe2c2c + 0efd19e commit bb524dc9cc7dacc88973e136552694a44f475333
@@ -241,6 +241,10 @@ void MenuCallback::addCommand(QString commandId,
{
keySequence = QKeySequence(QKeySequence::Paste);
}
else if (commandId == QStringLiteral("pasteWithIndentDummy"))
{
keySequence = QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_V);
}
else if (commandId == QStringLiteral("undoDummy"))
{
keySequence = QKeySequence(QKeySequence::Undo);
@@ -159,23 +159,19 @@ QString WebView::promptForFilename(const QNetworkRequest& request,

void WebView::keyPressEvent(QKeyEvent* pEvent)
{

#ifdef Q_OS_MAC
if (pEvent->key() == Qt::Key_W &&
pEvent->modifiers() == Qt::CTRL)
// on macOS, intercept Cmd+W and emit the window close signal
if (pEvent->key() == Qt::Key_W && pEvent->modifiers() == Qt::CTRL)
{
// on macOS, intercept Cmd+W and emit the window close signal
onCloseWindowShortcut();
return;
}
else
{
// pass other key events through to WebEngine
QWebEngineView::keyPressEvent(pEvent);
}
#else

#endif

// use default behavior otherwise
QWebEngineView::keyPressEvent(pEvent);

#endif
}

void WebView::openFile(QString fileName)
@@ -0,0 +1,53 @@
/*
* KeyboardTracker.java
*
* Copyright (C) 2009-17 by RStudio, Inc.
*
* Unless you have received this program directly from RStudio pursuant
* to the terms of a commercial license agreement with RStudio, then
* this program is licensed to you under the terms of version 3 of the
* GNU Affero General Public License. This program is distributed WITHOUT
* ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
* AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
*
*/
package org.rstudio.core.client;

import org.rstudio.core.client.command.KeyboardShortcut;

import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.Event.NativePreviewEvent;
import com.google.gwt.user.client.Event.NativePreviewHandler;
import com.google.inject.Singleton;

@Singleton
public class KeyboardTracker
{
public KeyboardTracker()
{
Event.addNativePreviewHandler(new NativePreviewHandler()
{
@Override
public void onPreviewNativeEvent(NativePreviewEvent preview)
{
int type = preview.getTypeInt();
if ((type & Event.KEYEVENTS) == 0)
return;

NativeEvent event = preview.getNativeEvent();
modifier_ = KeyboardShortcut.getModifierValue(event);
}

});
}

public boolean isShiftKeyDown()
{
return (modifier_ & KeyboardShortcut.SHIFT) != 0;
}

private int modifier_ = 0;

}
@@ -290,6 +290,13 @@ void onPasteDummy()
fireEditEvent(EditEvent.TYPE_PASTE);
Desktop.getFrame().clipboardPaste();
}

@Handler
void onPasteWithIndentDummy()
{
fireEditEvent(EditEvent.TYPE_PASTE_WITH_INDENT);
Desktop.getFrame().clipboardPaste();
}

@Handler
void onShowLogFiles()
@@ -314,12 +314,13 @@ private void advertiseEditingShortcuts(final GlobalDisplay display,
{
int modifiers = BrowseCap.hasMetaKey() ? KeyboardShortcut.META : KeyboardShortcut.CTRL;

setCommandShortcut(commands.undoDummy(), "z", 'Z', modifiers);
setCommandShortcut(commands.redoDummy(), "Z", 'Z', modifiers | KeyboardShortcut.SHIFT);
setCommandShortcut(commands.undoDummy(), "z", 'Z', modifiers);
setCommandShortcut(commands.redoDummy(), "Z", 'Z', modifiers | KeyboardShortcut.SHIFT);

setCommandShortcut(commands.cutDummy(), "x", 'X', modifiers);
setCommandShortcut(commands.copyDummy(), "c", 'C', modifiers);
setCommandShortcut(commands.pasteDummy(), "v", 'V', modifiers);
setCommandShortcut(commands.cutDummy(), "x", 'X', modifiers);
setCommandShortcut(commands.copyDummy(), "c", 'C', modifiers);
setCommandShortcut(commands.pasteDummy(), "v", 'V', modifiers);
setCommandShortcut(commands.pasteWithIndentDummy(), "v", 'V', modifiers | KeyboardShortcut.SHIFT);

CommandHandler useKeyboardNotification = new CommandHandler()
{
@@ -335,6 +336,7 @@ public void onCommand(AppCommand command)
makeRow(commands.cutDummy()) +
makeRow(commands.copyDummy()) +
makeRow(commands.pasteDummy()) +
makeRow(commands.pasteWithIndentDummy()) +
"</table>"
);
new WebDialogBuilderFactory().create(
@@ -359,6 +361,7 @@ private String makeRow(AppCommand cmd)
commands.cutDummy().addHandler(useKeyboardNotification);
commands.copyDummy().addHandler(useKeyboardNotification);
commands.pasteDummy().addHandler(useKeyboardNotification);
commands.pasteWithIndentDummy().addHandler(useKeyboardNotification);
}

public int getPreferredHeight()
@@ -38,10 +38,11 @@ public int getType()
private final boolean before_;
private final int type_;

public static final int TYPE_NONE = 0;
public static final int TYPE_CUT = 1;
public static final int TYPE_COPY = 2;
public static final int TYPE_PASTE = 4;
public static final int TYPE_NONE = 0;
public static final int TYPE_CUT = 1;
public static final int TYPE_COPY = 2;
public static final int TYPE_PASTE = 4;
public static final int TYPE_PASTE_WITH_INDENT = 8;

// Boilerplate ----
public interface Handler extends EventHandler
@@ -168,6 +168,7 @@ well as menu structures (for main menu and popup menus).
<cmd refid="cutDummy"/>
<cmd refid="copyDummy"/>
<cmd refid="pasteDummy"/>
<cmd refid="pasteWithIndentDummy"/>
<separator/>
<menu label="_Folding">
<cmd refid="fold"/>
@@ -572,6 +573,10 @@ well as menu structures (for main menu and popup menus).
<!-- Use spaces for key sequences, e.g. 'Ctrl+X Ctrl+F' -->
<!-- Separate shortcuts with '|', e.g. 'Ctrl+X Ctrl+F|Cmd+O' -->
<shortcutgroup name="Source Editor">
<shortcut refid="cutDummy" value="Cmd+X" if="org.rstudio.studio.client.application.Desktop.isDesktop()"/>
<shortcut refid="copyDummy" value="Cmd+C" if="org.rstudio.studio.client.application.Desktop.isDesktop()"/>
<shortcut refid="pasteDummy" value="Cmd+V" if="org.rstudio.studio.client.application.Desktop.isDesktop()"/>
<shortcut refid="pasteWithIndentDummy" value="Cmd+Shift+V" if="org.rstudio.studio.client.application.Desktop.isDesktop()"/>
<shortcut refid="insertChunk" value="Cmd+Alt+I"/>
<shortcut refid="insertSection" value="Cmd+Shift+R" disableModes="sublime"/>
<shortcut refid="insertSection" value="Ctrl+Shift+R" if="org.rstudio.core.client.BrowseCap.isMacintosh()"/>
@@ -3089,6 +3094,10 @@ well as menu structures (for main menu and popup menus).
menuLabel="_Paste"
rebindable="false"/>

<cmd id="pasteWithIndentDummy"
menuLabel="Paste with Indent"
rebindable="false"/>

<cmd id="yankBeforeCursor"
label="Yank Before Cursor"
context="editor"/>
@@ -514,6 +514,7 @@
public abstract AppCommand cutDummy();
public abstract AppCommand copyDummy();
public abstract AppCommand pasteDummy();
public abstract AppCommand pasteWithIndentDummy();

// Placeholder for most recently used files
public abstract AppCommand mru0();
@@ -54,9 +54,12 @@
import org.rstudio.core.client.CommandWithArg;
import org.rstudio.core.client.ElementIds;
import org.rstudio.core.client.ExternalJavaScriptLoader;
import org.rstudio.core.client.ExternalJavaScriptLoader.Callback;
import org.rstudio.core.client.KeyboardTracker;
import org.rstudio.core.client.Rectangle;
import org.rstudio.core.client.StringUtil;
import org.rstudio.core.client.command.KeySequence;
import org.rstudio.core.client.command.ShortcutManager;
import org.rstudio.core.client.dom.DomUtils;
import org.rstudio.core.client.dom.WindowEx;
import org.rstudio.core.client.js.JsMap;
@@ -74,6 +77,7 @@
import org.rstudio.studio.client.common.debugging.model.Breakpoint;
import org.rstudio.studio.client.common.filetypes.DocumentMode;
import org.rstudio.studio.client.common.filetypes.DocumentMode.Mode;
import org.rstudio.studio.client.events.EditEvent;
import org.rstudio.studio.client.common.filetypes.TextFileType;
import org.rstudio.studio.client.server.Void;
import org.rstudio.studio.client.workbench.MainWindowObject;
@@ -340,6 +344,25 @@ public AceEditor()
});

widget_.addFoldChangeHandler(event -> AceEditor.this.fireEvent(new FoldChangeEvent()));

events_.addHandler(EditEvent.TYPE, new EditEvent.Handler()
{
@Override
public void onEdit(EditEvent event)
{
if (event.isBeforeEdit())
{
activeEditEventType_ = event.getType();
}
else
{
Scheduler.get().scheduleDeferred(() ->
{
activeEditEventType_ = EditEvent.TYPE_NONE;
});
}
}
});

addPasteHandler(event -> {
if (completionManager_ != null)
@@ -349,7 +372,8 @@ public AceEditor()

Scheduler.get().scheduleDeferred(() -> {
Range range = Range.fromPoints(start, getSelectionEnd());
indentPastedRange(range);
if (shouldIndentOnPaste())
indentPastedRange(range);
});
});

@@ -607,16 +631,27 @@ public void insertPipeOperator()
else
insertCode(" %>% ", false);
}

private boolean shouldIndentOnPaste()
{
if (fileType_ == null || !fileType_.canAutoIndent())
return false;

// if the user has requested reindent on paste, then we reindent
boolean indentPref = RStudioGinjector.INSTANCE.getUserPrefs().reindentOnPaste().getValue();
if (indentPref)
return true;

// if the user has explicitly executed a paste with indent command, we reindent
if (activeEditEventType_ == EditEvent.TYPE_PASTE_WITH_INDENT)
return true;

// finally, infer based on whether shift key is down
return keyboard_.isShiftKeyDown();
}

private void indentPastedRange(Range range)
{
if (fileType_ == null ||
!fileType_.canAutoIndent() ||
!RStudioGinjector.INSTANCE.getUserPrefs().reindentOnPaste().getValue())
{
return;
}

String firstLinePrefix = getSession().getTextRange(
Range.fromPoints(Position.create(range.getStart().getRow(), 0),
range.getStart()));
@@ -658,12 +693,14 @@ public void resetCommands()
void initialize(CodeToolsServerOperations server,
UserPrefs uiPrefs,
CollabEditor collab,
KeyboardTracker keyboard,
Commands commands,
EventBus events)
{
server_ = server;
userPrefs_ = uiPrefs;
collab_ = collab;
keyboard_ = keyboard;
commands_ = commands;
events_ = events;
}
@@ -2927,11 +2964,16 @@ public HandlerRegistration addUndoRedoHandler(UndoRedoHandler handler)
{
return widget_.addUndoRedoHandler(handler);
}

public HandlerRegistration addPasteHandler(PasteEvent.Handler handler)
{
return widget_.addPasteHandler(handler);
}

public HandlerRegistration addEditHandler(EditEvent.Handler handler)
{
return widget_.addHandler(handler, EditEvent.TYPE);
}

public HandlerRegistration addAceClickHandler(Handler handler)
{
@@ -4070,6 +4112,7 @@ public void execute(double timestamp)
private ScopeTreeManager scopes_;
private CodeToolsServerOperations server_;
private UserPrefs userPrefs_;
private KeyboardTracker keyboard_;
private CollabEditor collab_;
private Commands commands_;
private EventBus events_;
@@ -4137,6 +4180,8 @@ private static final ExternalJavaScriptLoader getLoader(StaticDataResource relea
private long lastModifiedTime_;
private String yankedText_ = null;

private int activeEditEventType_ = EditEvent.TYPE_NONE;

private static AceEditor s_lastFocusedEditor = null;

private final List<HandlerRegistration> editorEventListeners_;
@@ -358,6 +358,8 @@ else if (type == EditEvent.TYPE_CUT)
unmapForEditImpl("<C-x>", "c-x");
else if (type == EditEvent.TYPE_PASTE)
unmapForEditImpl("<C-v>", "c-v");
else if (type == EditEvent.TYPE_PASTE_WITH_INDENT)
unmapForEditImpl("<C-S-v>", "c-s-v");
}

private final void remapForEdit(int type)
@@ -368,6 +370,8 @@ else if (type == EditEvent.TYPE_CUT)
remapForEditImpl("<C-x>", "c-x");
else if (type == EditEvent.TYPE_PASTE)
remapForEditImpl("<C-v>", "c-v");
else if (type == EditEvent.TYPE_PASTE_WITH_INDENT)
remapForEditImpl("<C-S-v>", "c-s-v");
}

private static final native void unmapForEditImpl(String vimKeys, String emacsKeys)

0 comments on commit bb524dc

Please sign in to comment.
You can’t perform that action at this time.