Eclipse Plugin для обработки одного и того же расширения файла с различными редакторами - PullRequest
4 голосов
/ 20 апреля 2011

Я пишу плагин для Eclipse, который обеспечивает подсветку синтаксиса для конкретной директивы препроцессора, которая используется в нашем программном стеке. Перед компиляцией реального кода они заменяются внешней программой (представьте тег типа <% FOO %>, который заменяется чем-то другим, например строкой версии).

Таким образом, плагин предоставляет аннотации для каждого тега, чтобы быстро идентифицировать их. Вместо реализации собственного редактора предоставляются аннотации для уже существующих редакторов, таких как JavaEditor или PHP-Editor.

Теперь проблема в том, что файлы, которые обрабатываются внешней программой, имеют одинаковое расширение, скажем, .inc. Они могут содержать код Java или код PHP (в будущем возможны и другие языки).

Я успешно добавил тип контента в свой плагин, и я могу различать разные файлы на основе некоторых критериев. Итак, когда у меня есть файл Java .inc и назначить тип содержимого inc file (java).

Однако пользователь должен иметь возможность перезаписать это автоопределение (также иногда автоопределение может завершиться неудачей). Итак, я хочу иметь возможность открыть один файл (foo.inc) в разных редакторах (Java Editor, PHP Editor, ...) и сохранить эту связь.

Подходы, о которых я сейчас думаю:

  • Перезаписать действие открытия файла, чтобы проверить настройку в моем проекте и открыть соответствующий редактор. Я не нашел решения, которое охватывает, как перезаписать все действия по открытию файла (Файл → Открыть файл в главном меню, Открыть в Навигаторе проекта,…)
  • Реализация собственного редактора, который затем открывает соответствующий редактор. Это, похоже, хакерский подход, который также может вызвать некоторую задержку.
  • В контекстном меню файла «открыть с помощью» пользователь может изменить редактор. Можно было бы изменить его программно, но я не могу найти API или файл, в котором хранится этот выбор.
  • Реализация различных Природ для проекта, затем по-разному ассоциировать типы файлов в контексте каждой природы. Предоставляет только привязку к конкретному проекту, а не для каждого файла.

Есть ли лучшие решения? Вы знаете больше о каком-либо из перечисленных мною подходов?

Ответы [ 2 ]

3 голосов
/ 21 апреля 2011

Я узнал, как перезаписать действие открытия файла: зарегистрировав actionProvider, который переопределяет org.eclipse.ui.navigator.resources.OpenActions.Я предоставляю весь код, потому что довольно сложно собрать все эти разные вещи и заставить его работать.

Давайте начнем с записи plugin.xml:

<!-- overwrite OpenActions -->
<extension
      point="org.eclipse.ui.navigator.navigatorContent">
   <actionProvider
         class="myplugin.navigator.OpenActionProvider"
         id="myplugin.navigator.actions.open"
         overrides="org.eclipse.ui.navigator.resources.OpenActions"
         priority="highest">
      <enablement>
         <and>
            <instanceof
                  value="org.eclipse.core.resources.IFile">
            </instanceof>
            <test
                  property="org.eclipse.core.resources.extension"
                  value="frm">
            </test>
         </and>
      </enablement>
   </actionProvider>
</extension>
<extension
      point="org.eclipse.ui.navigator.viewer">
   <viewerActionBinding
         viewerId="org.eclipse.ui.navigator.ProjectExplorer">
      <includes>
         <actionExtension
               pattern="myplugin.navigator.actions.open">
         </actionExtension>
      </includes>
   </viewerActionBinding>
</extension>

OpenActionProvider выглядит следующим образомthis:

package myplugin.navigator;

import org.eclipse.jface.action.IMenuManager;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.actions.ActionContext;
import org.eclipse.ui.navigator.CommonActionProvider;
import org.eclipse.ui.navigator.ICommonActionConstants;
import org.eclipse.ui.navigator.ICommonActionExtensionSite;
import org.eclipse.ui.navigator.ICommonViewerWorkbenchSite;

public class OpenActionProvider extends CommonActionProvider {
    private OpenEditorActionGroup fOpenGroup;

    @Override
    public void init(ICommonActionExtensionSite site) {
            ICommonViewerWorkbenchSite workbenchSite = null;
            if (site.getViewSite() instanceof ICommonViewerWorkbenchSite) {
                    workbenchSite = (ICommonViewerWorkbenchSite) site.getViewSite();
            }
            if (workbenchSite != null) {
                    if (workbenchSite.getPart() != null && workbenchSite.getPart() instanceof IViewPart) {
                            IViewPart viewPart = (IViewPart) workbenchSite.getPart();

                            fOpenGroup = new OpenEditorActionGroup(viewPart);
                    }
            }
    }

    @Override
    public void dispose() {
            if (fOpenGroup != null) {
                    fOpenGroup.dispose();
                    fOpenGroup = null;
            }
            super.dispose();
    }

    @Override
    public void fillActionBars(IActionBars actionBars) {
            if (fOpenGroup == null)
                    return;

            fOpenGroup.updateActionBars();
            actionBars.setGlobalActionHandler(ICommonActionConstants.OPEN, fOpenGroup.getOpenAction());
    }

    @Override
    public void fillContextMenu(IMenuManager menu) {
            if (fOpenGroup == null)
                    return;
            fOpenGroup.fillContextMenu(menu);
    }

    @Override
    public void setContext(ActionContext context) {
            super.setContext(context);
            if (fOpenGroup == null)
                    return;
            fOpenGroup.setContext(context);
    }
}

OpenEditorActionGroup выглядит следующим образом:

package myplugin.navigator;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.actions.OpenFileAction;
import org.eclipse.ui.actions.OpenWithMenu;
import org.eclipse.ui.navigator.ICommonMenuConstants;


public class OpenEditorActionGroup extends AbstractActionGroup {
    private OpenFileAction fOpenFileAction;

    public OpenEditorActionGroup(IViewPart viewPart) {
            super(viewPart);
    }

    @Override
    protected void makeActions() {
            fOpenFileAction= new OpenGenElementAction(getViewPart().getSite().getPage());
    }

    public static IStructuredSelection convertSelectionToResources(ISelection s) {
            List<Object> converted = new ArrayList<Object>();
            if (s instanceof StructuredSelection) {
                    Object[] elements = ((StructuredSelection) s).toArray();
                    for (int i = 0; i < elements.length; i++) {
                            Object e = elements[i];
                            if (e instanceof IResource) {
                                    converted.add(e);
                            } else if (e instanceof IAdaptable) {
                                    IResource r = (IResource) ((IAdaptable) e).getAdapter(IResource.class);
                                    if (r != null) {
                                            converted.add(r);
                                    }
                            }
                    }
            }
            return new StructuredSelection(converted.toArray());
    }


    @Override
    public void fillContextMenu(IMenuManager menu) {
            System.out.println("fillcontextmenu");
            if (getContext() == null)
                    return;
        IStructuredSelection celements = (IStructuredSelection)getContext().getSelection();
            IStructuredSelection selection = convertSelectionToResources(celements);

            fOpenFileAction.selectionChanged(celements);
            if (!fOpenFileAction.isEnabled())
                    return;
            menu.appendToGroup(ICommonMenuConstants.GROUP_OPEN, fOpenFileAction);
            fillOpenWithMenu(menu, selection);
    }

AbstractActionGroup - просто оболочка, если вы хотите реализовать больше из них:

package myplugin.navigator;
import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.actions.ActionGroup;

public abstract class AbstractActionGroup extends ActionGroup {
    private final IViewPart fViewPart;

    public AbstractActionGroup(IViewPart viewPart) {
            Assert.isNotNull(viewPart);
            fViewPart = viewPart;
            makeActions();
    }

    protected IViewPart getViewPart() {
            return fViewPart;
    }

    protected ImageDescriptor getImageDescriptor(String relativePath) {
            return ImageDescriptor.createFromURL(null);
    }

    protected abstract void makeActions();
    @Override
    public abstract void fillContextMenu(IMenuManager menu);
    @Override
    public abstract void fillActionBars(IActionBars actionBars);
    @Override
    public abstract void updateActionBars();
}
* 1016И, наконец, само действие OpenGenElement:
package myplugin.navigator;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.ui.IEditorDescriptor;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.actions.OpenFileAction;
import org.eclipse.ui.editors.text.EditorsUI;
import org.eclipse.ui.part.FileEditorInput;

public class OpenGenElementAction extends OpenFileAction {
    private IFile selectedFile = null;
    private final IWorkbenchPage workbenchPage;

    public OpenGenElementAction(IWorkbenchPage page) {
            super(page);
            workbenchPage = page;
    }

    @Override
    public boolean isEnabled() {
            return true;
    }

    @Override
    public void run() {
            System.out.println("RUN");
    }

    @Override
    protected boolean updateSelection(IStructuredSelection selection) {
            if (selection.size() != 1)
                    return super.updateSelection(selection);
            Object element = selection.getFirstElement();
            if (element instanceof IFile) {
                    selectedFile = (IFile)element;
            }

            return selectedFile != null || super.updateSelection(selection);
    }
}
0 голосов
/ 08 июля 2015

Вы можете атаковать IEditorRegistry напрямую программно, регистрируя определенные имена файлов, а не только расширения.

Посмотрите: «Справка по IEditorRegistry»

http://help.eclipse.org/luna/index.jsp?topic=%2Forg.eclipse.platform.doc.isv%2Freference%2Fapi%2Forg%2Feclipse%2Fui%2FIEditorRegistry.html

Метод:

void    setDefaultEditor(String fileNameOrExtension, String editorId) 
      Sets the default editor id for the files that match
      that specified file name or extension.

принимает полные имена и / или символы подстановки.Большинство вызовов openEditor (меню, панели инструментов и т. Д.) Заканчиваются вызовами в этот реестр, чтобы получить соответствующий редактор.Установите хук при открытии редактора, который специально регистрирует это имя файла.

Это небезопасно, если у вас есть два файла с одним и тем же именем и на другом языке, но это быстро и легко реализовать по сравнению с вашими подходами.

...