2015-12-22 4 views
0

Я разрабатываю плагин eclipse, который содержит специальный текстовый редактор.
Я хочу реализовать функциональность автоматических закрывающих скобок (и кавычек), что означает, что когда пользователь набирает (, редактор должен автоматически вставить соответствующий закрывающий кронштейн ).Как реализовать автоматическое закрытие брекета?

Мой текущий подход состоит в том, чтобы добавить IDocumentListener в базовый IDocument и всякий раз, когда документ был изменен, я смотрю на новый символ, и если он один, я хочу добавить символ закрытия, я добавляю его, текст документа, но это всегда бросает мое это исключение:

!SESSION 2015-12-22 15:03:53.517 ----------------------------------------------- 
eclipse.buildId=unknown 
java.version=1.8.0_45 
java.vendor=Oracle Corporation 
BootLoader constants: OS=win32, ARCH=x86_64, WS=win32, NL=de_DE 
Framework arguments: -product org.eclipse.sdk.ide 
Command-line arguments: -product org.eclipse.sdk.ide -data C:\Users\Robert Adam\Documents\eclipse.mars.pluginDev\workspace/../runtime-EclipseApplication(1) -dev file:C:/Users/Robert Adam/Documents/eclipse.mars.pluginDev/workspace/.metadata/.plugins/org.eclipse.pde.core/Eclipse Application (1)/dev.properties -os win32 -ws win32 -arch x86_64 -consoleLog 

!ENTRY org.eclipse.text 4 2 2015-12-22 15:04:23.611 
!MESSAGE Problems occurred when invoking code from plug-in: "org.eclipse.text". 
!STACK 0 
org.eclipse.core.runtime.AssertionFailedException: assertion failed: 
    at org.eclipse.core.runtime.Assert.isTrue(Assert.java:110) 
    at org.eclipse.core.runtime.Assert.isTrue(Assert.java:96) 
    at org.eclipse.ui.internal.texteditor.quickdiff.DocumentLineDiffer.handleAboutToBeChanged(DocumentLineDiffer.java:816) 
    at org.eclipse.ui.internal.texteditor.quickdiff.DocumentLineDiffer.documentAboutToBeChanged(DocumentLineDiffer.java:785) 
    at org.eclipse.jface.text.AbstractDocument.fireDocumentAboutToBeChanged(AbstractDocument.java:665) 
    at org.eclipse.jface.text.AbstractDocument.set(AbstractDocument.java:1228) 
    at org.eclipse.jface.text.AbstractDocument.set(AbstractDocument.java:1217) 
    at raven.sqdev.editors.sqfeditor.SQFDocumentListener.handleAddition(SQFDocumentListener.java:61) 
    at raven.sqdev.editors.sqfeditor.SQFDocumentListener.documentChanged(SQFDocumentListener.java:33) 
    at org.eclipse.jface.text.AbstractDocument.doFireDocumentChanged2(AbstractDocument.java:769) 
    at org.eclipse.jface.text.AbstractDocument.doFireDocumentChanged(AbstractDocument.java:736) 
    at org.eclipse.jface.text.AbstractDocument.doFireDocumentChanged(AbstractDocument.java:721) 
    at org.eclipse.jface.text.AbstractDocument.fireDocumentChanged(AbstractDocument.java:796) 
    at org.eclipse.jface.text.AbstractDocument.replace(AbstractDocument.java:1191) 
    at org.eclipse.jface.text.AbstractDocument.replace(AbstractDocument.java:1210) 
    at org.eclipse.jface.text.DefaultDocumentAdapter.replaceTextRange(DefaultDocumentAdapter.java:248) 
    at org.eclipse.swt.custom.StyledText.modifyContent(StyledText.java:7268) 
    at org.eclipse.swt.custom.StyledText.sendKeyEvent(StyledText.java:8111) 
    at org.eclipse.swt.custom.StyledText.doContent(StyledText.java:2481) 
    at org.eclipse.swt.custom.StyledText.handleKey(StyledText.java:5955) 
    at org.eclipse.swt.custom.StyledText.handleKeyDown(StyledText.java:5986) 
    at org.eclipse.swt.custom.StyledText$7.handleEvent(StyledText.java:5663) 
    at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84) 
    at org.eclipse.swt.widgets.Display.sendEvent(Display.java:4353) 
    at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1061) 
    at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1085) 
    at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1070) 
    at org.eclipse.swt.widgets.Widget.sendKeyEvent(Widget.java:1112) 
    at org.eclipse.swt.widgets.Widget.sendKeyEvent(Widget.java:1108) 
    at org.eclipse.swt.widgets.Widget.wmChar(Widget.java:1529) 
    at org.eclipse.swt.widgets.Control.WM_CHAR(Control.java:4722) 
    at org.eclipse.swt.widgets.Canvas.WM_CHAR(Canvas.java:343) 
    at org.eclipse.swt.widgets.Control.windowProc(Control.java:4610) 
    at org.eclipse.swt.widgets.Canvas.windowProc(Canvas.java:339) 
    at org.eclipse.swt.widgets.Display.windowProc(Display.java:5023) 
    at org.eclipse.swt.internal.win32.OS.DispatchMessageW(Native Method) 
    at org.eclipse.swt.internal.win32.OS.DispatchMessage(OS.java:2549) 
    at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3759) 
    at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$9.run(PartRenderingEngine.java:1151) 
    at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332) 
    at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1032) 
    at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:148) 
    at org.eclipse.ui.internal.Workbench$5.run(Workbench.java:636) 
    at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332) 
    at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:579) 
    at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:150) 
    at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:135) 
    at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196) 
    at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:134) 
    at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:104) 
    at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:380) 
    at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:235) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) 
    at java.lang.reflect.Method.invoke(Unknown Source) 
    at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:648) 
    at org.eclipse.equinox.launcher.Main.basicRun(Main.java:603) 
    at org.eclipse.equinox.launcher.Main.run(Main.java:1465) 
    at org.eclipse.equinox.launcher.Main.main(Main.java:1438) 

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

Я думал о том, что эта задача может быть связана с ContentAssist, но я ничего не могу найти об этом.

Кто-нибудь знает, как правильно реализовать эту функциональность в моем плагине eclipse?

+0

Я бы посмотрел исходный код Java-редактора JDT, чтобы увидеть, как он решает эту проблему. –

+0

Я не нашел соответствующую информацию в источниках ... Можете ли вы дать мне подсказку, мог ли этот механизм быть реализован? – Raven

+0

Из чтения источников, кажется, что 'BracketInserter', внутренний класс' CompilationUnitEditor' несет ответственность. Он использует 'VerifyKeyListener' для обнаружения вставок вставки. –

ответ

1

После просмотра исходного кода плагина org.eclipse.jdt.ui я узнал, что они создали эту функцию, используя VerifyKeyListener в редакторе SourceViewer. Он захватывает все ключевые входы и имеет доступ к соответствующему тексту через событие.

Однако это оказалось довольно сложно добраться до SourceViewer моего редактора, как он будет создан после того, как мой редактор и поэтому метод getSourceViewer() вернулся null при вызове в конструкторе моего редактора.
Ключом было переопределить createSourceViewer() в моем классе редактора, который объявлен в AbstractDecoratedTextEditor.
Там я сделал что-то вроде этого:

@Override 
    public ISourceViewer createSourceViewer(Composite parent, IVerticalRuler ruler, int styles) { 
     ISourceViewer viewer = super.createSourceViewer(parent, ruler, styles); 

     if(viewer instanceof ITextViewerExtension) { 
      ((ITextViewerExtension) viewer).appendVerifyKeyListener(<Listener>); 
     } 

     return viewer; 
    } 

Я реализовал мои собственные VerifyKeyListern, в котором я обрабатывать находя символы сопряжения (как открытия и закрытия скобки), а затем использовали что-то вроде этого внутрь verifyKey() -метода:

StyledText text = (StyledText) event.getSource(); 

text.insert(String.valueOf(<pairingCharacter>)); 

Как набранный характер (открытие символа) вставляется в текст в любом случае я только добавить соответствующий закрывающий Charakter через insert() -метода, который имеет хороший Effekt, что после этого мой курсор находится в промежутке между этими двумя символами

Смежные вопросы