| /*=============================================================================# |
| # Copyright (c) 2012, 2019 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.console.ui.snippets; |
| |
| import java.io.IOException; |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.eclipse.core.commands.ExecutionEvent; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.core.variables.IDynamicVariable; |
| import org.eclipse.core.variables.IStringVariable; |
| import org.eclipse.core.variables.IStringVariableManager; |
| import org.eclipse.core.variables.VariablesPlugin; |
| import org.eclipse.jface.text.templates.Template; |
| import org.eclipse.jface.text.templates.TemplateContextType; |
| import org.eclipse.jface.text.templates.persistence.TemplateStore; |
| import org.eclipse.text.templates.ContextTypeRegistry; |
| import org.eclipse.ui.editors.text.templates.ContributionContextTypeRegistry; |
| import org.eclipse.ui.editors.text.templates.ContributionTemplateStore; |
| import org.eclipse.ui.statushandlers.StatusManager; |
| |
| import org.eclipse.statet.ecommons.text.TextUtil; |
| import org.eclipse.statet.ecommons.ui.util.UIAccess; |
| import org.eclipse.statet.ecommons.ui.workbench.WorkbenchUIUtils; |
| import org.eclipse.statet.ecommons.ui.workbench.workspace.ResourceVariableUtil; |
| import org.eclipse.statet.ecommons.variables.core.DynamicVariable; |
| import org.eclipse.statet.ecommons.variables.core.StaticVariable; |
| import org.eclipse.statet.ecommons.variables.core.StringVariable; |
| import org.eclipse.statet.ecommons.variables.core.UnresolvedVariable; |
| import org.eclipse.statet.ecommons.variables.core.VariableText2; |
| |
| import org.eclipse.statet.internal.r.console.ui.RConsoleUIPlugin; |
| import org.eclipse.statet.ltk.ui.util.LTKWorkbenchUIUtil; |
| import org.eclipse.statet.r.core.RUtil; |
| import org.eclipse.statet.r.launching.RCodeLaunching; |
| import org.eclipse.statet.r.ui.rtool.RElementNameVariableResolver; |
| import org.eclipse.statet.r.ui.rtool.RResourceEncodingVariableResolver; |
| |
| |
| public class RSnippets { |
| |
| |
| public static final String SUBMIT_SNIPPET_COMMAND_ID= "org.eclipse.statet.r.commands.SubmitRSnippet"; //$NON-NLS-1$ |
| |
| public static final String SUBMIT_LAST_COMMAND_ID= "org.eclipse.statet.r.commands.SubmitLastRSnippet"; //$NON-NLS-1$ |
| |
| public static final String SNIPPET_PAR= "snippet"; //$NON-NLS-1$ |
| |
| |
| public static final IStringVariable RESOURCE_ENCODING_VARIABLE= new StringVariable( |
| "resource_encoding", Messages.Variable_ResourceEncoding_description ); //$NON-NLS-1$ |
| |
| public static final IStringVariable ECHO_ENABLED_VARIABLE= new StringVariable( |
| "echo", Messages.Variable_Echo_description ); //$NON-NLS-1$ |
| |
| |
| private static final String[] PRECHECKED_NAMES= new String[] { |
| "selected_text", //$NON-NLS-1$ |
| RElementNameVariableResolver.R_OBJECT_NAME_NAME, |
| }; |
| |
| private static void add(final Map<String, IStringVariable> map, final IStringVariable var) { |
| map.put(var.getName(), var); |
| } |
| |
| |
| private ContributionContextTypeRegistry templatesContextTypeRegistry; |
| private TemplateStore templatesStore; |
| |
| private String lastSnippetName; |
| |
| private final Runnable lastSnippetRunnable= new Runnable() { |
| @Override |
| public void run() { |
| WorkbenchUIUtils.refreshCommandElements(SUBMIT_LAST_COMMAND_ID, null, null); |
| } |
| }; |
| |
| |
| public RSnippets() { |
| } |
| |
| |
| public List<IStringVariable> getVariables() { |
| final IStringVariable[] variables= VariablesPlugin.getDefault() |
| .getStringVariableManager().getVariables(); |
| |
| final List<IStringVariable> all= new ArrayList<>(variables.length + 2); |
| for (int i= 0; i < variables.length; i++) { |
| all.add(variables[i]); |
| } |
| all.add(RESOURCE_ENCODING_VARIABLE); |
| all.add(ECHO_ENABLED_VARIABLE); |
| |
| return all; |
| } |
| |
| |
| private synchronized void initTemplates() { |
| if (this.templatesContextTypeRegistry == null) { |
| this.templatesContextTypeRegistry= new ContributionContextTypeRegistry(); |
| this.templatesContextTypeRegistry.addContextType(new RSnippetTemplateContextType()); |
| |
| this.templatesStore= new ContributionTemplateStore(this.templatesContextTypeRegistry, |
| RConsoleUIPlugin.getInstance().getPreferenceStore(), |
| RSnippetTemplateContextType.TEMPLATES_KEY ); |
| try { |
| this.templatesStore.load(); |
| } |
| catch (final IOException e) { |
| RConsoleUIPlugin.log(new Status(IStatus.ERROR, RConsoleUIPlugin.BUNDLE_ID, -1, |
| "An error occured when loading 'R snippet' template store.", e )); //$NON-NLS-1$ |
| } |
| } |
| } |
| |
| /** |
| * Returns the template context type registry for the R snippets. |
| * |
| * @return the template context type registry |
| */ |
| public synchronized ContextTypeRegistry getTemplateContextRegistry() { |
| if (this.templatesContextTypeRegistry == null) { |
| initTemplates(); |
| } |
| return this.templatesContextTypeRegistry; |
| } |
| |
| /** |
| * Returns the template store for the R snippets. |
| * |
| * @return the template store |
| */ |
| public synchronized TemplateStore getTemplateStore() { |
| if (this.templatesStore == null) { |
| initTemplates(); |
| } |
| return this.templatesStore; |
| } |
| |
| |
| private Map<String, IStringVariable> createResolveVariables() { |
| final ResourceVariableUtil util= new ResourceVariableUtil(); |
| |
| final Map<String, IStringVariable> variables= new HashMap<>(); |
| add(variables, new DynamicVariable.ResolverVariable( |
| RSnippets.RESOURCE_ENCODING_VARIABLE, new RResourceEncodingVariableResolver(util))); |
| add(variables, new EchoEnabledVariable()); |
| |
| return variables; |
| } |
| |
| private void addPrechecked(final Map<String, IStringVariable> variables) { |
| final IStringVariableManager manager= VariablesPlugin.getDefault().getStringVariableManager(); |
| for (int i= 0; i < PRECHECKED_NAMES.length; i++) { |
| final IDynamicVariable real= manager.getDynamicVariable(PRECHECKED_NAMES[i]); |
| if (real == null) { |
| continue; |
| } |
| try { |
| final String value= real.getValue(null); |
| add(variables, new StaticVariable(real, value)); |
| } |
| catch (final CoreException e) { |
| add(variables, new UnresolvedVariable(real, e)); |
| } |
| } |
| } |
| |
| public String resolve(final Template template) throws CoreException { |
| final VariableText2 text= new VariableText2(createResolveVariables()) { |
| @Override |
| protected String checkValue(final IStringVariable variable, final String value) { |
| if (!"selected_text".equals(variable.getName()) //$NON-NLS-1$ |
| && !RElementNameVariableResolver.R_OBJECT_NAME_NAME.equals(variable.getName()) ) { |
| return RUtil.escapeCompletely(value); |
| } |
| return value; |
| } |
| }; |
| |
| return text.performStringSubstitution(template.getPattern(), null); |
| } |
| |
| |
| public IStatus validate(final TemplateContextType contextType, final String template) { |
| try { |
| final VariableText2 text= new VariableText2(createResolveVariables()); |
| |
| text.validate(template, VariableText2.Severities.CHECK_SYNTAX, null); |
| return Status.OK_STATUS; |
| } |
| catch (final CoreException e) { |
| return e.getStatus(); |
| } |
| } |
| |
| public List<Template> validate(final Template[] templates) { |
| final Map<String, IStringVariable> variables= createResolveVariables(); |
| addPrechecked(variables); |
| |
| final VariableText2 text= new VariableText2(variables); |
| |
| final List<Template> tested= new ArrayList<>(templates.length); |
| for (final Template template : templates) { |
| try { |
| text.validate(template.getPattern(), VariableText2.Severities.RESOLVE, null); |
| tested.add(template); |
| } |
| catch (final CoreException e) {} |
| } |
| |
| return tested; |
| } |
| |
| |
| public void setLastSnippet(final String name) { |
| synchronized (this.lastSnippetRunnable) { |
| if ((this.lastSnippetName != null) ? this.lastSnippetName.equals(name) : null == name) { |
| return; |
| } |
| this.lastSnippetName= name; |
| } |
| UIAccess.getDisplay().asyncExec(this.lastSnippetRunnable); |
| } |
| |
| public String getLastSnippet() { |
| synchronized (this.lastSnippetRunnable) { |
| return this.lastSnippetName; |
| } |
| } |
| |
| public void run(final Template template, final ExecutionEvent event) { |
| setLastSnippet(template.getName()); |
| try { |
| final String snippet= resolve(template); |
| final List<String> lines= TextUtil.toLines(snippet); |
| |
| RCodeLaunching.runRCodeDirect(lines, false, null); |
| |
| return; |
| } |
| catch (final CoreException e) { |
| StatusManager.getManager().handle(new Status(IStatus.ERROR, |
| RConsoleUIPlugin.BUNDLE_ID, 0, |
| "An error occurred while submitting code snippet to R.\n" + |
| "Template pattern:\n" + template.getPattern(), e )); |
| LTKWorkbenchUIUtil.indicateStatus(e.getStatus(), event); |
| } |
| } |
| |
| |
| } |