【问题标题】:Eclipse Plugin to handle same file extension with different editors使用不同编辑器处理相同文件扩展名的 Eclipse 插件
【发布时间】:2011-04-20 10:08:00
【问题描述】:

我正在为 Eclipse 编写一个插件,它为我们的软件堆栈中使用的特定预处理器指令提供语法高亮显示。在编译实际代码之前,这些会被外部程序替换(想象像<% FOO %> 这样的标签会被其他东西替换,比如版本字符串)。

所以插件为每个标签提供了注解来快速识别这些。不是实现自己的编辑器,而是为现有的编辑器提供注释,例如 JavaEditor 或 PHP-Editor。

现在的问题是外部程序处理的文件都有相同的文件扩展名,比如.inc。它们可以包含 Java 代码或 PHP 代码(未来也可能包含其他语言)。

我已经成功地为我的插件添加了一个内容类型,我可以根据一些标准来区分不同的文件。所以,当我有一个 java .inc 文件并分配内容类型 inc file (java).

但是,用户应该能够覆盖此自动检测(此外,有时自动检测可能会失败)。因此,我希望能够使用不同的编辑器(Java 编辑器、PHP 编辑器……)打开一个文件 (foo.inc),并能够保存此关联。

我目前正在考虑的方法:

  • 覆盖文件打开操作以检查我的项目中的设置并打开相应的编辑器。我没有找到涵盖如何覆盖所有文件打开操作的解决方案(主菜单中的文件→打开文件,在项目导航器中打开,...)
  • 实现自己的编辑器,然后打开相应的编辑器。这似乎是一种骇人听闻的方法,也会导致一些延迟。
  • 在文件的“打开方式”上下文菜单中,用户可以更改编辑器。以编程方式更改它是可以的,但我找不到 API 或存储此选项的文件。
  • 为项目实施不同的性质,然后在每个性质的上下文中以不同的方式关联文件类型。只会提供特定于项目的关联,而不是每个文件的关联。

有更好的解决方案吗?您是否更了解我列出的任何方法?

【问题讨论】:

    标签: eclipse-plugin editor


    【解决方案1】:

    我发现了如何覆盖文件打开操作:通过注册一个覆盖org.eclipse.ui.navigator.resources.OpenActionsactionProvider。我提供了所有代码,因为将所有这些不同的东西放在一起并使其工作相对困难。

    让我们从 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 如下所示:

    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();
    }
    

    最后是 OpenGenElementAction 本身:

    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);
        }
    }
    

    【讨论】:

    • 之后,我发现这段代码在包资源管理器和项目导航器中都不起作用:(.
    • 感谢您发布此内容!
    【解决方案2】:

    您可以通过注册特定文件名而不仅仅是扩展名,以编程方式直接攻击 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 调用(菜单、工具栏等)最终都会调用此注册表以获取适当的编辑器。 打开专门注册此文件名的编辑器时设置一个挂钩。

    如果您有两个具有相同名称和不同语言的文件,这并非万无一失,但与您的方法相比,它实现起来又快又容易。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-04-07
      • 2021-04-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-25
      • 1970-01-01
      相关资源
      最近更新 更多