Bug 574748: [R-Console] Add support for 'pager' in R
- Add tool command handler for 'r/showContents'
Change-Id: Iab97a628265bff7ff31b1470bd8759a949cab9d0
diff --git a/r/org.eclipse.statet.r.console.ui/src/org/eclipse/statet/internal/r/console/ui/launching/RConsoleOptionsTab.java b/r/org.eclipse.statet.r.console.ui/src/org/eclipse/statet/internal/r/console/ui/launching/RConsoleOptionsTab.java
index 9933207..07cadca 100644
--- a/r/org.eclipse.statet.r.console.ui/src/org/eclipse/statet/internal/r/console/ui/launching/RConsoleOptionsTab.java
+++ b/r/org.eclipse.statet.r.console.ui/src/org/eclipse/statet/internal/r/console/ui/launching/RConsoleOptionsTab.java
@@ -103,9 +103,10 @@
static final TrackingConfiguration2LaunchConfiguration TRACKING_UTIL= new TrackingConfiguration2LaunchConfiguration();
static final String ATTR_INTEGRATION_ROOT= "org.eclipse.statet.r.debug/integration"; //$NON-NLS-1$
- static final String ATTR_INTEGRATION_RHELP_ENABLED= ATTR_INTEGRATION_ROOT+"integration.rhelp.enabled"; //$NON-NLS-1$
- static final String ATTR_INTEGRATION_RGRAPHICS_ASDEFAULT= ATTR_INTEGRATION_ROOT+"integration.rgraphics.asdefault"; //$NON-NLS-1$
- static final String ATTR_INTEGRATION_RDBGEXT_ENABLED= ATTR_INTEGRATION_ROOT+"integration.rdbgext.enabled"; //$NON-NLS-1$
+ static final String ATTR_INTEGRATION_RHELP_ENABLED= ATTR_INTEGRATION_ROOT + "integration.rhelp.enabled"; //$NON-NLS-1$
+ static final String ATTR_INTEGRATION_PAGER_ENABLED= ATTR_INTEGRATION_ROOT + "integration.pager.enabled"; //$NON-NLS-1$
+ static final String ATTR_INTEGRATION_RGRAPHICS_ASDEFAULT= ATTR_INTEGRATION_ROOT + "integration.rgraphics.asdefault"; //$NON-NLS-1$
+ static final String ATTR_INTEGRATION_RDBGEXT_ENABLED= ATTR_INTEGRATION_ROOT + "integration.rdbgext.enabled"; //$NON-NLS-1$
private final IObservableValue<Boolean> pinValue;
@@ -116,6 +117,7 @@
private final IObservableValue<String> startupSnippetValue;
private final IObservableValue<Boolean> rHelpByStatetValue;
+ private final IObservableValue<Boolean> pagerByStatetValue;
private final IObservableValue<Boolean> rGraphicsByStatetValue;
private final IObservableValue<Boolean> rDbgExtValue;
@@ -133,6 +135,7 @@
private SnippetEditor1 startupSnippetEditor;
private Button rHelpByStatetControl;
+ private Button pagerByStatetControl;
private Button rGraphicsByStatetControl;
private Button rDbgExtControl;
@@ -149,6 +152,7 @@
this.trackingEnabledSet= new WritableSet<>(realm, new HashSet<>(), TrackingConfiguration.class);
this.startupSnippetValue= new WritableValue<>(realm, "", String.class); //$NON-NLS-1$
this.rHelpByStatetValue= new WritableValue<>(realm, false, Boolean.TYPE);
+ this.pagerByStatetValue= new WritableValue<>(realm, false, Boolean.TYPE);
this.rGraphicsByStatetValue= new WritableValue<>(realm, false, Boolean.TYPE);
this.rDbgExtValue= new WritableValue<>(realm, false, Boolean.TYPE);
this.objectDBEnabledValue= new WritableValue<>(realm, false, Boolean.TYPE);
@@ -308,7 +312,12 @@
{ this.rHelpByStatetControl= new Button(container, SWT.CHECK);
final GridData gd= new GridData(SWT.FILL, SWT.FILL, true, false, 2, 1);
this.rHelpByStatetControl.setLayoutData(gd);
- this.rHelpByStatetControl.setText("Enable R Help by StatET for help functions in R ('help', 'help.start', '?')");
+ this.rHelpByStatetControl.setText("Enable integrated R Help for help functions in R ('help', 'help.start', '?')");
+ }
+ { this.pagerByStatetControl= new Button(container, SWT.CHECK);
+ final GridData gd= new GridData(SWT.FILL, SWT.FILL, true, false, 2, 1);
+ this.pagerByStatetControl.setLayoutData(gd);
+ this.pagerByStatetControl.setText("Enable integrated Pager view as default 'pager' to display text files ('file.show', ...)");
}
{ this.rGraphicsByStatetControl= new Button(container, SWT.CHECK);
final GridData gd= new GridData(SWT.FILL, SWT.FILL, true, false, 2, 1);
@@ -378,6 +387,10 @@
this.rHelpByStatetValue );
dbc.bindValue(
WidgetProperties.buttonSelection()
+ .observe(this.pagerByStatetControl),
+ this.pagerByStatetValue );
+ dbc.bindValue(
+ WidgetProperties.buttonSelection()
.observe(this.rGraphicsByStatetControl),
this.rGraphicsByStatetValue );
dbc.bindValue(
@@ -448,6 +461,9 @@
this.rHelpByStatetValue.setValue(readAttribute(configuration,
ATTR_INTEGRATION_RHELP_ENABLED,
true ));
+ this.pagerByStatetValue.setValue(readAttribute(configuration,
+ ATTR_INTEGRATION_RHELP_ENABLED,
+ true ));
this.rGraphicsByStatetValue.setValue(readAttribute(configuration,
ATTR_INTEGRATION_RGRAPHICS_ASDEFAULT,
true ));
@@ -530,6 +546,8 @@
configuration.setAttribute(ATTR_INTEGRATION_RHELP_ENABLED,
this.rHelpByStatetValue.getValue().booleanValue() );
+ configuration.setAttribute(ATTR_INTEGRATION_PAGER_ENABLED,
+ this.pagerByStatetValue.getValue().booleanValue() );
configuration.setAttribute(ATTR_INTEGRATION_RGRAPHICS_ASDEFAULT,
this.rGraphicsByStatetValue.getValue().booleanValue() );
configuration.setAttribute(ATTR_INTEGRATION_RDBGEXT_ENABLED,
diff --git a/r/org.eclipse.statet.r.console.ui/src/org/eclipse/statet/internal/r/console/ui/launching/RConsoleRJLaunchDelegate.java b/r/org.eclipse.statet.r.console.ui/src/org/eclipse/statet/internal/r/console/ui/launching/RConsoleRJLaunchDelegate.java
index be0520c..9cd044b 100644
--- a/r/org.eclipse.statet.r.console.ui/src/org/eclipse/statet/internal/r/console/ui/launching/RConsoleRJLaunchDelegate.java
+++ b/r/org.eclipse.statet.r.console.ui/src/org/eclipse/statet/internal/r/console/ui/launching/RConsoleRJLaunchDelegate.java
@@ -80,7 +80,6 @@
import org.eclipse.statet.rj.data.UnexpectedRDataException;
import org.eclipse.statet.rj.renv.core.REnvConfiguration;
import org.eclipse.statet.rj.server.RjsComConfig;
-import org.eclipse.statet.rj.services.FunctionCall;
import org.eclipse.statet.rj.services.RVersion;
@@ -99,15 +98,18 @@
private final Tool tool;
private final boolean enableRHelp;
+ private final boolean enablePager;
private final boolean enableRGraphics;
private final boolean enableRDbgExt;
private final boolean enableRDbg;
public ConfigRunnable(final Tool tool, final boolean enableRHelp,
+ final boolean enablePager,
final boolean enableRGraphics,
final boolean enableRDbgExt, final boolean enableRDbg) {
this.tool= tool;
this.enableRHelp= enableRHelp;
+ this.enablePager= enablePager;
this.enableRGraphics= enableRGraphics;
this.enableRDbgExt= enableRDbgExt;
this.enableRDbg= enableRDbg;
@@ -150,14 +152,30 @@
r.evalVoid("library('rj', quietly= TRUE)", m); //$NON-NLS-1$
}
if (this.enableRHelp) {
- final FunctionCall fcall= r.createFunctionCall(".statet.initHelp"); //$NON-NLS-1$
- fcall.evalVoid(m);
+ r.createFunctionCall(".statet.initHelp") //$NON-NLS-1$
+ .evalVoid(m);
+ }
+ if (this.enablePager) {
+ try {
+ if (RDataUtils.checkSingleLogiValue(
+ r.createFunctionCall("exists") //$NON-NLS-1$
+ .addChar("x", "rj.pager") //$NON-NLS-1$ //$NON-NLS-2$
+ .addChar("where", "package:rj") //$NON-NLS-1$
+ .evalData(m) )) {
+ r.createFunctionCall("base::options") //$NON-NLS-1$
+ .add("pager", "rj::rj.pager") //$NON-NLS-1$ //$NON-NLS-2$
+ .evalVoid(m);
+ }
+ }
+ catch (final StatusException | UnexpectedRDataException e) {
+ }
}
if (this.enableRGraphics) {
try {
- final FunctionCall fcall= r.createFunctionCall(".rj.initGD"); //$NON-NLS-1$
- fcall.addLogi("default", true); //$NON-NLS-1$
- RDataUtils.checkSingleLogiValue(fcall.evalData(m));
+ RDataUtils.checkSingleLogiValue(
+ r.createFunctionCall(".rj.initGD") //$NON-NLS-1$
+ .addLogi("default", true) //$NON-NLS-1$
+ .evalData(m) );
}
catch (final StatusException | UnexpectedRDataException e) {
r.handleStatus(new WarningStatus(RConsoleUIPlugin.BUNDLE_ID,
@@ -165,10 +183,10 @@
m );
}
}
- { final FunctionCall fcall= r.createFunctionCall(".statet.initDebug"); //$NON-NLS-1$
- fcall.addLogi("mode", this.enableRDbg); //$NON-NLS-1$
- fcall.addLogi("ext", this.enableRDbgExt); //$NON-NLS-1$
- fcall.evalVoid(m);
+ { r.createFunctionCall(".statet.initDebug") //$NON-NLS-1$
+ .addLogi("mode", this.enableRDbg) //$NON-NLS-1$
+ .addLogi("ext", this.enableRDbgExt) //$NON-NLS-1$
+ .evalVoid(m);
}
}
finally {
@@ -197,6 +215,7 @@
controller.addStartupRunnable(new ConfigRunnable(
controller.getTool(),
(rEnvConfig != null && configuration.getAttribute(RConsoleOptionsTab.ATTR_INTEGRATION_RHELP_ENABLED, true)),
+ configuration.getAttribute(RConsoleOptionsTab.ATTR_INTEGRATION_PAGER_ENABLED, true),
configuration.getAttribute(RConsoleOptionsTab.ATTR_INTEGRATION_RGRAPHICS_ASDEFAULT, true),
configuration.getAttribute(RConsoleOptionsTab.ATTR_INTEGRATION_RDBGEXT_ENABLED, true),
mode.equals(ILaunchManager.DEBUG_MODE) ));
diff --git a/r/org.eclipse.statet.r.console.ui/src/org/eclipse/statet/r/console/ui/launching/RConsoleLaunching.java b/r/org.eclipse.statet.r.console.ui/src/org/eclipse/statet/r/console/ui/launching/RConsoleLaunching.java
index d0e64db..ba3683c 100644
--- a/r/org.eclipse.statet.r.console.ui/src/org/eclipse/statet/r/console/ui/launching/RConsoleLaunching.java
+++ b/r/org.eclipse.statet.r.console.ui/src/org/eclipse/statet/r/console/ui/launching/RConsoleLaunching.java
@@ -32,6 +32,7 @@
import org.eclipse.statet.r.core.RUtil;
import org.eclipse.statet.r.ui.dataeditor.ShowRElementCommandHandler;
import org.eclipse.statet.r.ui.graphics.RGraphicCommandHandler;
+import org.eclipse.statet.r.ui.pager.RShowContentsCommandHandler;
import org.eclipse.statet.r.ui.pkgmanager.RPkgUICommandHandler;
import org.eclipse.statet.r.ui.rhelp.RHelpUICommandHandler;
@@ -134,6 +135,9 @@
{ final ToolCommandHandler handler = new RGraphicCommandHandler();
controller.addCommandHandler(AbstractRController.INIT_RGRAPHIC_FACTORY_HANDLER_ID, handler);
}
+ { final ToolCommandHandler handler= new RShowContentsCommandHandler();
+ controller.addCommandHandler(RShowContentsCommandHandler.SHOW_CONTENTS_COMMAND_ID, handler);
+ }
{ final ToolCommandHandler handler = new RHelpUICommandHandler();
controller.addCommandHandler(RHelpUICommandHandler.SHOW_HELP_COMMAND_ID, handler);
controller.addCommandHandler(RHelpUICommandHandler.SHOW_HELP_COMMAND_OLD_ID, handler);
diff --git a/r/org.eclipse.statet.r.ui/META-INF/MANIFEST.MF b/r/org.eclipse.statet.r.ui/META-INF/MANIFEST.MF
index 43b5297..0483cb3 100644
--- a/r/org.eclipse.statet.r.ui/META-INF/MANIFEST.MF
+++ b/r/org.eclipse.statet.r.ui/META-INF/MANIFEST.MF
@@ -79,6 +79,7 @@
org.eclipse.statet.r.ui.editors,
org.eclipse.statet.r.ui.editors.templates,
org.eclipse.statet.r.ui.graphics,
+ org.eclipse.statet.r.ui.pager,
org.eclipse.statet.r.ui.pkgmanager,
org.eclipse.statet.r.ui.rhelp,
org.eclipse.statet.r.ui.rtool,
diff --git a/r/org.eclipse.statet.r.ui/icons/view_16/pager.png b/r/org.eclipse.statet.r.ui/icons/view_16/pager.png
new file mode 100644
index 0000000..0f1a378
--- /dev/null
+++ b/r/org.eclipse.statet.r.ui/icons/view_16/pager.png
Binary files differ
diff --git a/r/org.eclipse.statet.r.ui/icons/view_16/pager@2x.png b/r/org.eclipse.statet.r.ui/icons/view_16/pager@2x.png
new file mode 100644
index 0000000..f8fd7e4
--- /dev/null
+++ b/r/org.eclipse.statet.r.ui/icons/view_16/pager@2x.png
Binary files differ
diff --git a/r/org.eclipse.statet.r.ui/plugin.xml b/r/org.eclipse.statet.r.ui/plugin.xml
index 800583b..534d731 100644
--- a/r/org.eclipse.statet.r.ui/plugin.xml
+++ b/r/org.eclipse.statet.r.ui/plugin.xml
@@ -2248,6 +2248,17 @@
sequence="M1+-"/>
</extension>
+ <!-- R Pager -->
+ <extension
+ point="org.eclipse.ui.editors">
+ <editor
+ id="org.eclipse.statet.r.editors.RPager"
+ icon="icons/r-graphic.png"
+ name="R Pager"
+ class="org.eclipse.statet.internal.r.ui.pager.RPagerEditor">
+ </editor>
+ </extension>
+
<!-- R Graphics -->
<extension
point="org.eclipse.ui.preferencePages">
diff --git a/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/internal/r/ui/RUIPlugin.java b/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/internal/r/ui/RUIPlugin.java
index fb7ea3d..79c4025 100644
--- a/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/internal/r/ui/RUIPlugin.java
+++ b/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/internal/r/ui/RUIPlugin.java
@@ -89,6 +89,8 @@
public static final String IMG_WIZBAN_NEW_RPROJECT= RUI.BUNDLE_ID + "/image/wizban/new.r_project"; //$NON-NLS-1$
public static final String IMG_WIZBAN_NEW_RPKGPROJECT= RUI.BUNDLE_ID + "/image/wizban/new.rpkg_project"; //$NON-NLS-1$
+ public static final String PAGER_VIEW_IMAGE_ID= RUI.BUNDLE_ID + "/image/view/pager"; //$NON-NLS-1$
+
public static final String IMG_LOCTOOL_FILTER_GENERAL= RUI.BUNDLE_ID + "/image/ltool/filter.general"; //$NON-NLS-1$
public static final String IMG_LOCTOOL_FILTER_LOCAL= RUI.BUNDLE_ID + "/image/ltool/filter.local"; //$NON-NLS-1$
@@ -261,6 +263,8 @@
util.register(RHelpUI.RHELP_VIEW_IMAGE_ID, ImageRegistryUtil.T_VIEW, "rhelp.png"); //$NON-NLS-1$
+ util.register(PAGER_VIEW_IMAGE_ID, ImageRegistryUtil.T_VIEW, "pager.png"); //$NON-NLS-1$
+
util.register(RUI.IMG_OBJ_COMMON_FUNCTION, ImageRegistryUtil.T_OBJ, "function.png"); //$NON-NLS-1$
util.register(RUI.IMG_OBJ_COMMON_LOCAL_FUNCTION, ImageRegistryUtil.T_OBJ, "function-local.png"); //$NON-NLS-1$
util.register(RUI.IMG_OBJ_GENERIC_FUNCTION, ImageRegistryUtil.T_OBJ, "generic_function.png"); //$NON-NLS-1$
diff --git a/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/internal/r/ui/pager/RPagerEditor.java b/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/internal/r/ui/pager/RPagerEditor.java
new file mode 100644
index 0000000..38947d1
--- /dev/null
+++ b/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/internal/r/ui/pager/RPagerEditor.java
@@ -0,0 +1,140 @@
+/*=============================================================================#
+ # Copyright (c) 2021 Stephan Wahlbrink and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.internal.r.ui.pager;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.part.MultiPageEditorPart;
+
+import org.eclipse.statet.jcommons.collections.ImList;
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+
+import org.eclipse.statet.ecommons.text.core.util.ImmutableDocument;
+
+import org.eclipse.statet.internal.r.ui.RUIPlugin;
+import org.eclipse.statet.internal.r.ui.pager.RPagerEditorInput.TextFile;
+import org.eclipse.statet.ltk.core.input.BasicSourceFragment;
+import org.eclipse.statet.r.ui.RUI;
+
+
+@NonNullByDefault
+public class RPagerEditor extends MultiPageEditorPart {
+
+
+ public RPagerEditor() {
+ }
+
+
+ @Override
+ protected Image getDefaultImage() {
+ return RUI.getImage(RUIPlugin.PAGER_VIEW_IMAGE_ID);
+ }
+
+
+ @Override
+ protected void setInputWithNotify(final IEditorInput input) {
+ super.setInput(input);
+
+ setPartName(input.getName());
+
+ if (getContainer() != null) {
+ updatePages();
+ }
+
+ firePropertyChange(IEditorPart.PROP_INPUT);
+ }
+
+ @Override
+ protected void setInput(final IEditorInput input) {
+ setInputWithNotify(input);
+ }
+
+
+ protected void updatePages() {
+ while (true) {
+ final int pageCount= getPageCount();
+ if (pageCount == 0) {
+ break;
+ }
+ removePage(pageCount - 1);
+ }
+
+ final IEditorInput editorInput= getEditorInput();
+ if (editorInput instanceof RPagerEditorInput) {
+ final var pagerInput= (RPagerEditorInput)editorInput;
+ final ImList<TextFile> files= pagerInput.getFiles();
+ int id= 0;
+ for (final var textFile : files) {
+ try {
+ final var sourceFragment= new BasicSourceFragment("RPagerFile#" + id++,
+ textFile.getName(), textFile.getName(),
+ new ImmutableDocument(textFile.getContent(), 0) );
+ final TextFilePage page= new TextFilePage();
+ addPage(page, new TextFileEditorInput(sourceFragment));
+ }
+ catch (final Exception e) {
+ RUIPlugin.logError(String.format("An error occurred when creating R Pager editor page for '%1$s'.",
+ textFile.getName() ),
+ e );
+ }
+ }
+ }
+ }
+
+ @Override
+ protected void createPages() {
+ updatePages();
+ }
+
+ @Override
+ public void addPage(final int index, final IEditorPart editor, final IEditorInput input)
+ throws PartInitException {
+ super.addPage(index, editor, input);
+ setPageText(index, input.getName());
+ }
+
+
+ @Override
+ public boolean isSaveAsAllowed() {
+ final int pageIndex= getActivePage();
+ if (pageIndex >= 0) {
+ final IEditorPart editor= getEditor(pageIndex);
+ if (editor != null) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public void doSave(final IProgressMonitor monitor) {
+ }
+
+ @Override
+ public void doSaveAs() {
+ final int pageIndex= getActivePage();
+ if (pageIndex >= 0) {
+ final IEditorPart editor= getEditor(pageIndex);
+ if (editor != null) {
+ editor.doSaveAs();
+ return;
+ }
+ }
+ }
+
+}
diff --git a/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/internal/r/ui/pager/RPagerEditorInput.java b/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/internal/r/ui/pager/RPagerEditorInput.java
new file mode 100644
index 0000000..1bf4035
--- /dev/null
+++ b/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/internal/r/ui/pager/RPagerEditorInput.java
@@ -0,0 +1,105 @@
+/*=============================================================================#
+ # Copyright (c) 2021 Stephan Wahlbrink and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.internal.r.ui.pager;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IPersistableElement;
+
+import org.eclipse.statet.jcommons.collections.ImList;
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+import org.eclipse.statet.jcommons.ts.core.Tool;
+
+import org.eclipse.statet.r.ui.RUI;
+import org.eclipse.statet.rj.ts.core.RTool;
+
+
+@NonNullByDefault
+public class RPagerEditorInput implements IEditorInput {
+
+
+ public static class TextFile {
+
+ private final String name;
+ private final String content;
+
+ public TextFile(final String name, final String content) {
+ this.name= name;
+ this.content= content;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public String getContent() {
+ return this.content;
+ }
+
+ }
+
+
+ private final String name;
+ private final RTool source;
+
+ private final ImList<TextFile> files;
+
+
+ public RPagerEditorInput(final String name, final RTool source,
+ final ImList<TextFile> files) {
+ this.name= name;
+ this.source= source;
+ this.files= files;
+ }
+
+
+ @Override
+ public boolean exists() {
+ return true;
+ }
+
+ @Override
+ public @Nullable ImageDescriptor getImageDescriptor() {
+ return RUI.getImageDescriptor(RUI.RD_EDITOR_ID);
+ }
+
+ @Override
+ public String getName() {
+ return this.name;
+ }
+
+ @Override
+ public String getToolTipText() {
+ return this.name + '\n' + this.source.getLabel(Tool.LONG_LABEL);
+ }
+
+
+ public ImList<TextFile> getFiles() {
+ return this.files;
+ }
+
+ @Override
+ public @Nullable IPersistableElement getPersistable() {
+ return null;
+ }
+
+
+ @Override
+ public <T> @Nullable T getAdapter(final Class<T> adapter) {
+ return null;
+ }
+
+}
diff --git a/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/internal/r/ui/pager/TextFileEditorInput.java b/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/internal/r/ui/pager/TextFileEditorInput.java
new file mode 100644
index 0000000..af10973
--- /dev/null
+++ b/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/internal/r/ui/pager/TextFileEditorInput.java
@@ -0,0 +1,32 @@
+/*=============================================================================#
+ # Copyright (c) 2021 Stephan Wahlbrink and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.internal.r.ui.pager;
+
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+
+import org.eclipse.statet.ltk.core.input.SourceFragment;
+import org.eclipse.statet.ltk.ui.input.BasicSourceFragmentEditorInput;
+
+
+@NonNullByDefault
+public class TextFileEditorInput extends BasicSourceFragmentEditorInput<SourceFragment> {
+
+
+ public TextFileEditorInput(final SourceFragment fragment) {
+ super(fragment);
+ }
+
+
+}
diff --git a/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/internal/r/ui/pager/TextFilePage.java b/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/internal/r/ui/pager/TextFilePage.java
new file mode 100644
index 0000000..9095d66
--- /dev/null
+++ b/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/internal/r/ui/pager/TextFilePage.java
@@ -0,0 +1,63 @@
+/*=============================================================================#
+ # Copyright (c) 2021 Stephan Wahlbrink and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.internal.r.ui.pager;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.text.source.CompositeRuler;
+import org.eclipse.jface.text.source.IVerticalRuler;
+import org.eclipse.ui.texteditor.IDocumentProvider;
+import org.eclipse.ui.texteditor.StatusTextEditor;
+
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+
+import org.eclipse.statet.ltk.ui.sourceediting.FragmentDocumentProvider;
+
+
+@NonNullByDefault
+public class TextFilePage extends StatusTextEditor {
+
+
+ private final IDocumentProvider documentProvider= new FragmentDocumentProvider("", null);
+
+
+ public TextFilePage() {
+ setDocumentProvider(this.documentProvider);
+ setRulerContextMenuId(""); //$NON-NLS-1$
+ }
+
+
+ @Override
+ public boolean isDirty() {
+ return false;
+ }
+
+ @Override
+ public boolean isSaveAsAllowed() {
+ return false;
+ }
+
+ @Override
+ protected void performSaveAs(final @Nullable IProgressMonitor progressMonitor) {
+ // for save as: implement and change isSaveAsAllowed to true
+ }
+
+
+ @Override
+ protected IVerticalRuler createVerticalRuler() {
+ return new CompositeRuler();
+ }
+
+}
diff --git a/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/r/ui/pager/RShowContentsCommandHandler.java b/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/r/ui/pager/RShowContentsCommandHandler.java
new file mode 100644
index 0000000..a3661a2
--- /dev/null
+++ b/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/r/ui/pager/RShowContentsCommandHandler.java
@@ -0,0 +1,94 @@
+/*=============================================================================#
+ # Copyright (c) 2012, 2021 Stephan Wahlbrink and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.r.ui.pager;
+
+import static org.eclipse.statet.jcommons.lang.ObjectUtils.NonNull_StringArray_TYPE;
+import static org.eclipse.statet.jcommons.lang.ObjectUtils.Nullable_StringArray_TYPE;
+import static org.eclipse.statet.jcommons.lang.ObjectUtils.nonNullAssert;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.ui.ide.IDE;
+
+import org.eclipse.statet.jcommons.collections.ImCollections;
+import org.eclipse.statet.jcommons.lang.NonNull;
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.status.ErrorStatus;
+import org.eclipse.statet.jcommons.status.ProgressMonitor;
+import org.eclipse.statet.jcommons.status.Status;
+import org.eclipse.statet.jcommons.status.StatusException;
+import org.eclipse.statet.jcommons.ts.core.ToolCommandData;
+import org.eclipse.statet.jcommons.util.StringUtils;
+
+import org.eclipse.statet.ecommons.ui.util.UIAccess;
+
+import org.eclipse.statet.internal.r.ui.pager.RPagerEditorInput;
+import org.eclipse.statet.nico.ui.NicoUI;
+import org.eclipse.statet.r.ui.RUI;
+import org.eclipse.statet.rj.ts.core.AbstractRToolCommandHandler;
+import org.eclipse.statet.rj.ts.core.RToolService;
+
+
+@NonNullByDefault
+public class RShowContentsCommandHandler extends AbstractRToolCommandHandler {
+
+
+ public static final String SHOW_CONTENTS_COMMAND_ID= "r/showContents"; //$NON-NLS-1$
+
+
+ public RShowContentsCommandHandler() {
+ }
+
+
+ @Override
+ public Status execute(final String id, final RToolService r, final ToolCommandData data,
+ final ProgressMonitor m) throws StatusException {
+ switch (id) {
+ case SHOW_CONTENTS_COMMAND_ID:
+ { final var contents= data.getRequired("contents", NonNull_StringArray_TYPE);
+ var title= data.getStringRequired("title");
+ final var headers= data.getRequired("headers", Nullable_StringArray_TYPE);
+
+ title= StringUtils.toSimpleSingleLine(title);
+ final var files= new RPagerEditorInput. @NonNull TextFile[contents.length];
+ for (int i= 0; i < files.length; i++) {
+ String header= headers[i];
+ if (header == null) {
+ header= "#" + (i + 1);
+ }
+ files[i]= new RPagerEditorInput.TextFile(header, nonNullAssert(contents[i]));
+ }
+
+ final var editorInput= new RPagerEditorInput(title, r.getTool(),
+ ImCollections.newList(files) );
+ try {
+ UIAccess.checkedSyncExec(() -> {
+ final var workbenchPage= NicoUI.getToolRegistry().findWorkbenchPage(r.getTool());
+ IDE.openEditor(workbenchPage, editorInput, "org.eclipse.statet.r.editors.RPager", true);
+ });
+ }
+ catch (final CoreException e) {
+ throw new StatusException(new ErrorStatus(RUI.BUNDLE_ID, 0,
+ "An error occurred when opening the R Pager view.",
+ e ));
+ }
+
+ return Status.OK_STATUS;
+ }
+ default:
+ throw new UnsupportedOperationException();
+ }
+ }
+
+}