mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[patch]: implement analyze and apply patch on the fly
This commit is contained in:
@@ -47,6 +47,9 @@ public class PatchReader {
|
||||
|
||||
@NonNls private static final String CONTEXT_HUNK_PREFIX = "***************";
|
||||
@NonNls private static final String CONTEXT_FILE_PREFIX = "*** ";
|
||||
@NonNls private static final String UNIFIED_BEFORE_HUNK_PREFIX = "--- ";
|
||||
@NonNls private static final String UNIFIED_AFTER_HUNK_PREFIX = "+++ ";
|
||||
|
||||
@NonNls private static final Pattern ourUnifiedHunkStartPattern = Pattern.compile("@@ -(\\d+)(,(\\d+))? \\+(\\d+)(,(\\d+))? @@.*");
|
||||
@NonNls private static final Pattern ourContextBeforeHunkStartPattern = Pattern.compile("\\*\\*\\* (\\d+),(\\d+) \\*\\*\\*\\*");
|
||||
@NonNls private static final Pattern ourContextAfterHunkStartPattern = Pattern.compile("--- (\\d+),(\\d+) ----");
|
||||
@@ -629,4 +632,36 @@ public class PatchReader {
|
||||
return myHunkCount == 1 && myDeleted;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isPatchContent(@Nullable String content) {
|
||||
if (content == null) return false;
|
||||
List<String> lines = LineTokenizer.tokenizeIntoList(content, false);
|
||||
final ListIterator<String> iterator = lines.listIterator();
|
||||
DiffFormat currentFormat = null;
|
||||
while (iterator.hasNext()) {
|
||||
String line = iterator.next();
|
||||
if (line.startsWith(CONTEXT_HUNK_PREFIX)) {
|
||||
currentFormat = DiffFormat.CONTEXT;
|
||||
}
|
||||
else if (currentFormat == DiffFormat.CONTEXT && ourContextBeforeHunkStartPattern.matcher(line).matches()) {
|
||||
break;
|
||||
}
|
||||
else if (line.startsWith(UNIFIED_BEFORE_HUNK_PREFIX) && currentFormat == null) {
|
||||
currentFormat = DiffFormat.UNIFIED;
|
||||
}
|
||||
else if (currentFormat == DiffFormat.UNIFIED && line.startsWith(UNIFIED_AFTER_HUNK_PREFIX)) break;
|
||||
}
|
||||
if (currentFormat == null) return false; // can't detect format
|
||||
// check that contains at least one chunk
|
||||
while (iterator.hasNext()) {
|
||||
String line = iterator.next();
|
||||
if (currentFormat == DiffFormat.CONTEXT) {
|
||||
if (ourContextAfterHunkStartPattern.matcher(line).matches()) return true;
|
||||
}
|
||||
else {
|
||||
if (ourUnifiedHunkStartPattern.matcher(line).matches()) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ public class VcsApplicationSettings implements PersistentStateComponent<VcsAppli
|
||||
public boolean SHOW_WHITESPACES_IN_LST = false;
|
||||
public boolean SHOW_LST_GUTTER_MARKERS = true;
|
||||
public boolean SHOW_LST_WORD_DIFFERENCES = true;
|
||||
public boolean DETECT_PATCH_ON_THE_FLY = true;
|
||||
|
||||
public static VcsApplicationSettings getInstance() {
|
||||
return ServiceManager.getService(VcsApplicationSettings.class);
|
||||
|
||||
+47
-5
@@ -2,23 +2,39 @@ package com.intellij.openapi.vcs.changes.patch;
|
||||
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys;
|
||||
import com.intellij.openapi.application.ApplicationActivationListener;
|
||||
import com.intellij.openapi.application.ex.ApplicationManagerEx;
|
||||
import com.intellij.openapi.application.ex.ClipboardUtil;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.project.DumbAwareAction;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vcs.VcsApplicationSettings;
|
||||
import com.intellij.openapi.vcs.changes.ChangeListManager;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.testFramework.LightVirtualFile;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.messages.MessageBusConnection;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.util.Collections;
|
||||
|
||||
public class ApplyPatchFromClipboardAction extends DumbAwareAction {
|
||||
private static final PatchClipboardListener LISTENER = new PatchClipboardListener();
|
||||
|
||||
public ApplyPatchFromClipboardAction() {
|
||||
MessageBusConnection connection = ApplicationManagerEx.getApplicationEx().getMessageBus().connect();
|
||||
connection.subscribe(ApplicationActivationListener.TOPIC, LISTENER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(AnActionEvent e) {
|
||||
Project project = e.getData(CommonDataKeys.PROJECT);
|
||||
String text = ClipboardUtil.getTextInClipboard();
|
||||
e.getPresentation().setEnabled(project != null && PatchFileUtil.isPatchContent(text));
|
||||
// allow to apply from clipboard even we do not detect it as a patch, because during applying we parse content more precisely
|
||||
e.getPresentation().setEnabled(project != null && text != null);
|
||||
}
|
||||
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
@@ -28,8 +44,34 @@ public class ApplyPatchFromClipboardAction extends DumbAwareAction {
|
||||
|
||||
String clipboardText = ClipboardUtil.getTextInClipboard();
|
||||
assert clipboardText != null;
|
||||
VirtualFile vFile = new LightVirtualFile("clipboardPatchFile", clipboardText);
|
||||
new ApplyPatchDifferentiatedDialog(project, new ApplyPatchDefaultExecutor(project), Collections.emptyList(),
|
||||
ApplyPatchMode.APPLY_PATCH_IN_MEMORY, vFile).show();
|
||||
new MyApplyPatchFromClipboardDialog(project, clipboardText).show();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static JCheckBox createAnalyzeOnTheFlyOptionPanel() {
|
||||
final JCheckBox removeOptionCheckBox = new JCheckBox("Analyze and Apply Patch from Clipboard on the Fly");
|
||||
removeOptionCheckBox.setMnemonic(KeyEvent.VK_L);
|
||||
removeOptionCheckBox.setSelected(VcsApplicationSettings.getInstance().DETECT_PATCH_ON_THE_FLY);
|
||||
removeOptionCheckBox.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
VcsApplicationSettings.getInstance().DETECT_PATCH_ON_THE_FLY = removeOptionCheckBox.isSelected();
|
||||
}
|
||||
});
|
||||
return removeOptionCheckBox;
|
||||
}
|
||||
|
||||
public static class MyApplyPatchFromClipboardDialog extends ApplyPatchDifferentiatedDialog {
|
||||
private static final JCheckBox FLY_OPTION_PANEL = createAnalyzeOnTheFlyOptionPanel();
|
||||
|
||||
public MyApplyPatchFromClipboardDialog(@NotNull Project project, @NotNull String clipboardText) {
|
||||
super(project, new ApplyPatchDefaultExecutor(project), Collections.emptyList(), ApplyPatchMode.APPLY_PATCH_IN_MEMORY,
|
||||
new LightVirtualFile("clipboardPatchFile", clipboardText));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JComponent createSouthPanel() {
|
||||
return addDoNotShowCheckBox(ObjectUtils.assertNotNull(super.createSouthPanel()), FLY_OPTION_PANEL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.openapi.vcs.changes.patch;
|
||||
|
||||
import com.intellij.openapi.application.ClipboardAnalyzeListener;
|
||||
import com.intellij.openapi.diff.impl.patch.PatchReader;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vcs.VcsApplicationSettings;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class PatchClipboardListener extends ClipboardAnalyzeListener {
|
||||
@Override
|
||||
protected void handle(@NotNull Project project, @NotNull String value) {
|
||||
new ApplyPatchFromClipboardAction.MyApplyPatchFromClipboardDialog(project, value).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canHandle(@NotNull String value) {
|
||||
if (!VcsApplicationSettings.getInstance().DETECT_PATCH_ON_THE_FLY) return false;
|
||||
return PatchReader.isPatchContent(value);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user