From c2db4725b1926780ac0c96f3772d43867a9dfb5f Mon Sep 17 00:00:00 2001 From: Albert Tregnaghi Date: Tue, 9 Oct 2018 23:16:36 +0200 Subject: [PATCH] Make it possible to use installed asciidoctor instance #147 - removed unnecessary dependency to OSGI wrapper from editor - implemented speciall asciidoctor implementation which just uses installed variant - preferences added + defaults --- asciidoctor-editor-libs/.classpath | 4 +- asciidoctor-editor-other/doc/00_External.adoc | 18 + .../bugfixes/issue-155-stdlib.adoc | 9 + .../asciidoctoreditor/AsciiDoctorEditor.java | 4 +- .../asciidoctoreditor/AsciiDoctorWrapper.java | 49 +- .../InstalledAsciidoctor.java | 430 +++++++++++++++ .../AsciiDoctorEditorPreferenceConstants.java | 4 + ...sciiDoctorEditorPreferenceInitializer.java | 3 + .../AsciiDoctorEditorPreferencePage.java | 179 ++++--- .../AsciiDoctorEditorPreferences.java | 8 + .../MultiLineStringFieldEditor.java | 505 ++++++++++++++++++ .../jcup/asciidoctoreditor/CLITextUtil.java | 25 + .../de/jcup/asciidoctoreditor/OSUtil.java | 17 + .../asciidoctoreditor/CLITextUtilTest.java | 87 +++ 14 files changed, 1239 insertions(+), 103 deletions(-) create mode 100644 asciidoctor-editor-other/doc/00_External.adoc create mode 100644 asciidoctor-editor-other/testscripts/bugfixes/issue-155-stdlib.adoc create mode 100644 asciidoctor-editor-plugin/src/main/java-eclipse/de/jcup/asciidoctoreditor/InstalledAsciidoctor.java create mode 100644 asciidoctor-editor-plugin/src/main/java-eclipse/de/jcup/asciidoctoreditor/preferences/MultiLineStringFieldEditor.java create mode 100644 asciidoctor-editor-plugin/src/main/java/de/jcup/asciidoctoreditor/CLITextUtil.java create mode 100644 asciidoctor-editor-plugin/src/main/java/de/jcup/asciidoctoreditor/OSUtil.java create mode 100644 asciidoctor-editor-plugin/src/test/java/de/jcup/asciidoctoreditor/CLITextUtilTest.java diff --git a/asciidoctor-editor-libs/.classpath b/asciidoctor-editor-libs/.classpath index f15e623e..9e0ab49a 100644 --- a/asciidoctor-editor-libs/.classpath +++ b/asciidoctor-editor-libs/.classpath @@ -7,10 +7,10 @@ - + - + diff --git a/asciidoctor-editor-other/doc/00_External.adoc b/asciidoctor-editor-other/doc/00_External.adoc new file mode 100644 index 00000000..8f13161d --- /dev/null +++ b/asciidoctor-editor-other/doc/00_External.adoc @@ -0,0 +1,18 @@ +== Install asciidoctor +For details look also at https://asciidoctor.org/docs/install-toolchain/ + +=== Windows + +==== Install ruby +First of all - if not already done - we must install ruby from +https://rubyinstaller.org/ (e.g. `rubyinstaller-devkit-2.4.4-2-x64.exe` ) + +==== Install asciidoc + +`gem install asciidoctor` + +`gem install asciidoctor-diagram` +https://rubygems.org/gems/asciidoctor-diagram/versions/1.2.1 + +https://asciidoctor.org/docs/asciidoctor-pdf/ +`gem install asciidoctor-pdf --pre` (pre necessary because pdf still alpha...) diff --git a/asciidoctor-editor-other/testscripts/bugfixes/issue-155-stdlib.adoc b/asciidoctor-editor-other/testscripts/bugfixes/issue-155-stdlib.adoc new file mode 100644 index 00000000..4490f16e --- /dev/null +++ b/asciidoctor-editor-other/testscripts/bugfixes/issue-155-stdlib.adoc @@ -0,0 +1,9 @@ +[plantuml, sample-plantuml-diagram-u1, alt="Use case diagram 1"] +---- +@startuml AWS icon test +!include +!include +AMAZONAPIGATEWAY(gateway,"",rectangle) + +@enduml +---- \ No newline at end of file diff --git a/asciidoctor-editor-plugin/src/main/java-eclipse/de/jcup/asciidoctoreditor/AsciiDoctorEditor.java b/asciidoctor-editor-plugin/src/main/java-eclipse/de/jcup/asciidoctoreditor/AsciiDoctorEditor.java index 46d36a2b..72b83d93 100644 --- a/asciidoctor-editor-plugin/src/main/java-eclipse/de/jcup/asciidoctoreditor/AsciiDoctorEditor.java +++ b/asciidoctor-editor-plugin/src/main/java-eclipse/de/jcup/asciidoctoreditor/AsciiDoctorEditor.java @@ -183,7 +183,7 @@ public AsciiDoctorEditor() { this.editorTempIdentifier = System.nanoTime(); setSourceViewerConfiguration(createSourceViewerConfig()); this.modelBuilder = new AsciiDoctorScriptModelBuilder(); - asciidoctorWrapper = new AsciiDoctorWrapper(editorTempIdentifier, AsciiDoctorEclipseLogAdapter.INSTANCE); + asciidoctorWrapper = new AsciiDoctorWrapper(editorTempIdentifier, AsciiDoctorEclipseLogAdapter.INSTANCE, AsciiDoctorEditorPreferences.getInstance().isUsingInstalledAsciidoctor()); contentTransformer = createCustomContentTransformer(); if (contentTransformer == null) { @@ -922,7 +922,7 @@ protected void showRebuildingInPreviewAndTriggerFullHTMLRebuildAsJob(BuildAsciiD try { outputBuildSemaphore.acquire(); if (initializing) { - File previewInitializingFile = new File(AsciiDoctorOSGIWrapper.INSTANCE.getAddonsFolder(), + File previewInitializingFile = new File(asciidoctorWrapper.getAddonsFolder(), "html/initialize/preview_initializing.html"); boolean previewInitializingFileFound = false; try { diff --git a/asciidoctor-editor-plugin/src/main/java-eclipse/de/jcup/asciidoctoreditor/AsciiDoctorWrapper.java b/asciidoctor-editor-plugin/src/main/java-eclipse/de/jcup/asciidoctoreditor/AsciiDoctorWrapper.java index 4e7083df..09f60076 100644 --- a/asciidoctor-editor-plugin/src/main/java-eclipse/de/jcup/asciidoctoreditor/AsciiDoctorWrapper.java +++ b/asciidoctor-editor-plugin/src/main/java-eclipse/de/jcup/asciidoctoreditor/AsciiDoctorWrapper.java @@ -33,7 +33,6 @@ import de.jcup.asciidoctoreditor.provider.AsciiDoctorProviderContext; public class AsciiDoctorWrapper { - private LogAdapter logAdapter; @@ -41,39 +40,45 @@ public class AsciiDoctorWrapper { private AsciiDoctorProviderContext context; - public AsciiDoctorWrapper(long tempIdentifier, LogAdapter logAdapter) { - if (logAdapter==null){ + public AsciiDoctorWrapper(long tempIdentifier, LogAdapter logAdapter, boolean useInstalled) { + if (logAdapter == null) { throw new IllegalArgumentException("log adapter may not be null!"); } - this.logAdapter=logAdapter; + this.logAdapter = logAdapter; initTempFolderOrFail(tempIdentifier); - this.context = new AsciiDoctorProviderContext(AsciiDoctorOSGIWrapper.INSTANCE.getAsciidoctor(), AsciiDoctorEclipseLogAdapter.INSTANCE); + Asciidoctor asciidoctor = null; + if (useInstalled) { + asciidoctor = new InstalledAsciidoctor(); + } else { + asciidoctor = AsciiDoctorOSGIWrapper.INSTANCE.getAsciidoctor(); + } + this.context = new AsciiDoctorProviderContext(asciidoctor, AsciiDoctorEclipseLogAdapter.INSTANCE); context.setOutputFolder(tempFolder); - + } - + public AsciiDoctorProviderContext getContext() { return context; } - public void convertToHTML(File asciiDocFile) throws Exception{ + public void convertToHTML(File asciiDocFile) throws Exception { context.setAsciidocFile(asciiDocFile); AsciiDoctorEditorPreferences preferences = AsciiDoctorEditorPreferences.getInstance(); int tocLevels = preferences.getIntegerPreference(AsciiDoctorEditorPreferenceConstants.P_EDITOR_TOC_LEVELS); context.setTocLevels(tocLevels); - try{ + try { AsciiDoctorOptionsProvider optionsProvider = context.getOptionsProvider(); Map defaultOptions = optionsProvider.createDefaultOptions(); - + Asciidoctor asciiDoctor = context.getAsciiDoctor(); asciiDoctor.convertFile(asciiDocFile, defaultOptions); - }catch(Exception e){ - logAdapter.logError("Cannot convert to html:"+asciiDocFile, e); + + } catch (Exception e) { + logAdapter.logError("Cannot convert to html:" + asciiDocFile, e); throw e; } } - /** * Resets cached values: baseDir, imagesDir */ @@ -82,14 +87,13 @@ public void resetCaches() { context.setOutputFolder(tempFolder); } - - public String buildHTMLWithCSS(String html, int refreshAutomaticallyInSeconds) { StringBuilder sb = new StringBuilder(); sb.append(buildPrefixHTML(refreshAutomaticallyInSeconds)); sb.append(html); if (refreshAutomaticallyInSeconds > 0) { - sb.append(""); + sb.append(""); } sb.append(""); sb.append(""); @@ -123,8 +127,7 @@ private String buildPrefixHTML(int refreshAutomaticallyInSeconds) { prefixSb.append(createLinkToFile(file)); } prefixSb.append("\n"); - - + prefixSb.append(""); @@ -152,13 +155,15 @@ protected void initTempFolderOrFail(long tempIdentifier) { } /** - * Returns temp folder which cannot be null because of {@link #initTempFolderOrFail(long)} called on constructor time + * Returns temp folder which cannot be null because of + * {@link #initTempFolderOrFail(long)} called on constructor time + * * @return temp folder never null */ public Path getTempFolder() { return tempFolder; } - + public File getTempFileFor(File editorFile, TemporaryFileType type) { File parent = null; if (tempFolder == null) { @@ -197,4 +202,8 @@ public void setTocVisible(boolean tocVisible) { public boolean isTocVisible() { return context.isTOCVisible(); } + + public File getAddonsFolder() { + return AsciiDoctorOSGIWrapper.INSTANCE.getAddonsFolder(); + } } diff --git a/asciidoctor-editor-plugin/src/main/java-eclipse/de/jcup/asciidoctoreditor/InstalledAsciidoctor.java b/asciidoctor-editor-plugin/src/main/java-eclipse/de/jcup/asciidoctoreditor/InstalledAsciidoctor.java new file mode 100644 index 00000000..7eb5ae61 --- /dev/null +++ b/asciidoctor-editor-plugin/src/main/java-eclipse/de/jcup/asciidoctoreditor/InstalledAsciidoctor.java @@ -0,0 +1,430 @@ +package de.jcup.asciidoctoreditor; + +import java.io.File; +import java.io.IOException; +import java.io.Reader; +import java.io.Writer; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import org.asciidoctor.Asciidoctor; +import org.asciidoctor.DirectoryWalker; +import org.asciidoctor.Options; +import org.asciidoctor.OptionsBuilder; +import org.asciidoctor.ast.Document; +import org.asciidoctor.ast.DocumentHeader; +import org.asciidoctor.ast.StructuredDocument; +import org.asciidoctor.converter.JavaConverterRegistry; +import org.asciidoctor.extension.ExtensionGroup; +import org.asciidoctor.extension.JavaExtensionRegistry; +import org.asciidoctor.extension.RubyExtensionRegistry; + +import com.kenai.jffi.internal.StubLoader.OS; + +import de.jcup.asciidoctoreditor.preferences.AsciiDoctorEditorPreferences; + +/** + * Special variant of an Asciidoctor instance - uses native installation. But it + * works ony with the editor, because not all parts are implemented... + * + * @author Albert Tregnaghi + * + */ +public class InstalledAsciidoctor implements Asciidoctor { + + /* + * ------------------------------------------------------------------------- + */ + /* + * +++++++++++++++++++++++++++++++ used++ ++++++++++++++++++++++++++++++++++ + */ + /* + * ------------------------------------------------------------------------- + */ + + @Override + public DocumentHeader readDocumentHeader(File filename) { + return AsciiDoctorOSGIWrapper.INSTANCE.getAsciidoctor().readDocumentHeader(filename); + } + @Override + public String convertFile(File filename, Map options) { + + List commands = new ArrayList(); + if (OSUtil.isWindows()){ + commands.add("cmd.exe"); + commands.add("/C"); + } + commands.add("asciidoctor"); +// for (String key : options.keySet()) { +// commands.add("-"+key); +// commands.add(""+options.get(key)); +// } + + String outDir = null; + + @SuppressWarnings("unchecked") + Mapattributes =(Map) options.get("attributes"); + for (String key : attributes.keySet()) { + Object value = attributes.get(key); + if (value==null){ + continue; + } + String v= value.toString(); + String attrib = key; + if (v.isEmpty()){ + continue; + } + commands.add("-a"); + String safeValue = toWindowsSafeVariant(value); + if (key.equals("outdir")){ + outDir=safeValue; + } + attrib+="="+safeValue; + commands.add(attrib); + } + +// commands.add("-b"); +// commands.add("html5"); +// commands.add("-s"); +// commands.add("unsafe"); + +// commands.add("--base-dir"); +// commands.add(toWindowsSafeVariant(options.get("base_dir"))); + +// commands.add("--source-dir"); +// commands.add(""+options.get("base_dir")); + List preferenceCLICommands = CLITextUtil.convertToList(AsciiDoctorEditorPreferences.getInstance().getArgumentsForInstalledAsciidoctor()); + commands.addAll(preferenceCLICommands); + if (outDir!=null){ + commands.add("-D"); + commands.add(outDir); + } + +// commands.add("--no-header-footer"); +// commands.add("-r"); +// commands.add("asciidoctor-diagram"); + + commands.add(toWindowsSafeVariant(filename.getAbsolutePath())); + StringBuilder sb = new StringBuilder(); + for (String command: commands){ + if ("cmd.exe".equals(command) || "/C".equals(command)){ + continue; + } + sb.append(command); + sb.append(" "); + } + System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>"); + System.out.println("installed ascidoctor >>>> executing:"+sb.toString()); + ProcessBuilder pb = new ProcessBuilder(commands); + pb.inheritIO(); + try { + Process process = pb.start(); + process.waitFor(2, TimeUnit.MINUTES); + } catch (InterruptedException | IOException e) { + e.printStackTrace(); + } + + return null; + } + + private String toWindowsSafeVariant(Object obj){ + String command = ""+obj; + boolean windowsPath = command.indexOf('\\')!=-1; + if (!windowsPath){ + return command; + } + return "\""+command+"\""; + } + + /* + * ------------------------------------------------------------------------- + */ + /* + * +++++++++++++++++++++++++++++++ unused ++++++++++++++++++++++++++++++++++ + */ + /* + * ------------------------------------------------------------------------- + */ + + @Override + public String render(String content, Map options) { + throw new NotImplementedException(); + + } + + @Override + public String render(String content, Options options) { + throw new NotImplementedException(); + + } + + @Override + public String render(String content, OptionsBuilder options) { + throw new NotImplementedException(); + + } + + @Override + public void render(Reader contentReader, Writer rendererWriter, Map options) throws IOException { + throw new NotImplementedException(); + + } + + @Override + public void render(Reader contentReader, Writer rendererWriter, Options options) throws IOException { + throw new NotImplementedException(); + + } + + @Override + public void render(Reader contentReader, Writer rendererWriter, OptionsBuilder options) throws IOException { + throw new NotImplementedException(); + + } + + @Override + public String renderFile(File filename, Map options) { + throw new NotImplementedException(); + + } + + @Override + public String renderFile(File filename, Options options) { + throw new NotImplementedException(); + + } + + @Override + public String renderFile(File filename, OptionsBuilder options) { + throw new NotImplementedException(); + + } + + @Override + public String[] renderDirectory(DirectoryWalker directoryWalker, Map options) { + throw new NotImplementedException(); + + } + + @Override + public String[] renderDirectory(DirectoryWalker directoryWalker, Options options) { + throw new NotImplementedException(); + + } + + @Override + public String[] renderDirectory(DirectoryWalker directoryWalker, OptionsBuilder options) { + throw new NotImplementedException(); + + } + + @Override + public String[] renderFiles(Collection asciidoctorFiles, Map options) { + throw new NotImplementedException(); + + } + + @Override + public String[] renderFiles(Collection asciidoctorFiles, Options options) { + throw new NotImplementedException(); + + } + + @Override + public String[] renderFiles(Collection asciidoctorFiles, OptionsBuilder options) { + throw new NotImplementedException(); + + } + + @Override + public String convert(String content, Map options) { + throw new NotImplementedException(); + + } + + @Override + public String convert(String content, Options options) { + throw new NotImplementedException(); + + } + + @Override + public String convert(String content, OptionsBuilder options) { + throw new NotImplementedException(); + + } + + @Override + public void convert(Reader contentReader, Writer rendererWriter, Map options) throws IOException { + throw new NotImplementedException(); + + } + + @Override + public void convert(Reader contentReader, Writer rendererWriter, Options options) throws IOException { + throw new NotImplementedException(); + + } + + @Override + public void convert(Reader contentReader, Writer rendererWriter, OptionsBuilder options) throws IOException { + throw new NotImplementedException(); + + } + + @Override + public String convertFile(File filename, Options options) { + throw new NotImplementedException(); + + } + + @Override + public String convertFile(File filename, OptionsBuilder options) { + throw new NotImplementedException(); + + } + + @Override + public String[] convertDirectory(DirectoryWalker directoryWalker, Map options) { + throw new NotImplementedException(); + + } + + @Override + public String[] convertDirectory(DirectoryWalker directoryWalker, Options options) { + throw new NotImplementedException(); + + } + + @Override + public String[] convertDirectory(DirectoryWalker directoryWalker, OptionsBuilder options) { + throw new NotImplementedException(); + + } + + @Override + public String[] convertFiles(Collection asciidoctorFiles, Map options) { + throw new NotImplementedException(); + + } + + @Override + public String[] convertFiles(Collection asciidoctorFiles, Options options) { + throw new NotImplementedException(); + + } + + @Override + public String[] convertFiles(Collection asciidoctorFiles, OptionsBuilder options) { + throw new NotImplementedException(); + + } + + @Override + public StructuredDocument readDocumentStructure(File filename, Map options) { + throw new NotImplementedException(); + + } + + @Override + public StructuredDocument readDocumentStructure(String content, Map options) { + throw new NotImplementedException(); + + } + + @Override + public StructuredDocument readDocumentStructure(Reader contentReader, Map options) { + throw new NotImplementedException(); + + } + + @Override + public DocumentHeader readDocumentHeader(String content) { + throw new NotImplementedException(); + + } + + @Override + public DocumentHeader readDocumentHeader(Reader contentReader) { + throw new NotImplementedException(); + + } + + @Override + public void requireLibrary(String... requiredLibraries) { + throw new NotImplementedException(); + + } + + @Override + public void requireLibraries(Collection requiredLibraries) { + throw new NotImplementedException(); + + } + + @Override + public JavaExtensionRegistry javaExtensionRegistry() { + throw new NotImplementedException(); + + } + + @Override + public RubyExtensionRegistry rubyExtensionRegistry() { + throw new NotImplementedException(); + + } + + @Override + public JavaConverterRegistry javaConverterRegistry() { + throw new NotImplementedException(); + + } + + @Override + public ExtensionGroup createGroup() { + throw new NotImplementedException(); + + } + + @Override + public ExtensionGroup createGroup(String groupName) { + throw new NotImplementedException(); + + } + + @Override + public void unregisterAllExtensions() { + throw new NotImplementedException(); + + } + + @Override + public void shutdown() { + throw new NotImplementedException(); + + } + + @Override + public String asciidoctorVersion() { + return "installed version"; + } + + @Override + public Document load(String content, Map options) { + throw new NotImplementedException(); + } + + @Override + public Document loadFile(File file, Map options) { + throw new NotImplementedException(); + } + + public static class NotImplementedException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + } +} diff --git a/asciidoctor-editor-plugin/src/main/java-eclipse/de/jcup/asciidoctoreditor/preferences/AsciiDoctorEditorPreferenceConstants.java b/asciidoctor-editor-plugin/src/main/java-eclipse/de/jcup/asciidoctoreditor/preferences/AsciiDoctorEditorPreferenceConstants.java index 92fe8551..04a3126a 100644 --- a/asciidoctor-editor-plugin/src/main/java-eclipse/de/jcup/asciidoctoreditor/preferences/AsciiDoctorEditorPreferenceConstants.java +++ b/asciidoctor-editor-plugin/src/main/java-eclipse/de/jcup/asciidoctoreditor/preferences/AsciiDoctorEditorPreferenceConstants.java @@ -44,6 +44,10 @@ public enum AsciiDoctorEditorPreferenceConstants implements PreferenceIdentifiab P_EDITOR_TOC_LEVELS("tocLevels"), P_EDITOR_AUTOBUILD_FOR_EXTERNAL_PREVIEW_ENABLED("autoBuildForExternalPreviewEnabled"), + + P_USE_INSTALLED_ASCIIDOCTOR_ENABLED("useInstalledAsciidoctorEnabled"), + + P_INSTALLED_ASCIICDOCTOR_ARGUMENTS("installedAsciidoctorArguments") ; private String id; diff --git a/asciidoctor-editor-plugin/src/main/java-eclipse/de/jcup/asciidoctoreditor/preferences/AsciiDoctorEditorPreferenceInitializer.java b/asciidoctor-editor-plugin/src/main/java-eclipse/de/jcup/asciidoctoreditor/preferences/AsciiDoctorEditorPreferenceInitializer.java index 642e47d3..052e2ad4 100644 --- a/asciidoctor-editor-plugin/src/main/java-eclipse/de/jcup/asciidoctoreditor/preferences/AsciiDoctorEditorPreferenceInitializer.java +++ b/asciidoctor-editor-plugin/src/main/java-eclipse/de/jcup/asciidoctoreditor/preferences/AsciiDoctorEditorPreferenceInitializer.java @@ -70,6 +70,9 @@ public void initializeDefaultPreferences() { store.setDefault(P_EDITOR_TOC_LEVELS.getId(), 6); store.setDefault(P_EDITOR_AUTOREFRESH_EXTERNAL_BROWSER_IN_SECONDS.getId(), 0); // per default auto refresh is turned off store.setDefault(P_EDITOR_AUTOBUILD_FOR_EXTERNAL_PREVIEW_ENABLED.getId(), false); + store.setDefault(P_USE_INSTALLED_ASCIIDOCTOR_ENABLED.getId(), false); + store.setDefault(P_INSTALLED_ASCIICDOCTOR_ARGUMENTS.getId(), + "-r asciidoctor-diagram\n--no-header-footer\n"); /* +++++++++++++++++ */ /* + Editor Colors + */ diff --git a/asciidoctor-editor-plugin/src/main/java-eclipse/de/jcup/asciidoctoreditor/preferences/AsciiDoctorEditorPreferencePage.java b/asciidoctor-editor-plugin/src/main/java-eclipse/de/jcup/asciidoctoreditor/preferences/AsciiDoctorEditorPreferencePage.java index 08282b0f..b8049516 100644 --- a/asciidoctor-editor-plugin/src/main/java-eclipse/de/jcup/asciidoctoreditor/preferences/AsciiDoctorEditorPreferencePage.java +++ b/asciidoctor-editor-plugin/src/main/java-eclipse/de/jcup/asciidoctoreditor/preferences/AsciiDoctorEditorPreferencePage.java @@ -25,6 +25,7 @@ import org.eclipse.jface.preference.ComboFieldEditor; import org.eclipse.jface.preference.FieldEditorPreferencePage; import org.eclipse.jface.preference.IntegerFieldEditor; +import org.eclipse.jface.preference.StringFieldEditor; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; @@ -61,19 +62,6 @@ protected static void indent(Control control) { private ArrayList masterSlaveListeners = new ArrayList<>(); - private BooleanFieldEditor codeAssistWithAsciiDoctorKeywords; - private BooleanFieldEditor codeAssistWithSimpleWords; - private BooleanFieldEditor toolTipsEnabled; - - private BooleanFieldEditor linkEditorWithPreviewEnabled; - - private ComboFieldEditor previewDefaultTypeRadioButton; - - private IntegerFieldEditor autorefreshSeconds; - - private IntegerFieldEditor tocLevels; - - private AccessibleBooleanFieldEditor autobuildForExternalPreviewEnabled; public AsciiDoctorEditorPreferencePage() { super(GRID); @@ -88,6 +76,8 @@ public void init(IWorkbench workbench) { @Override public void performDefaults() { super.performDefaults(); + masterSlaveListeners.forEach( (a)->a.updateSlaveComponent()); + } @Override @@ -106,12 +96,63 @@ protected void createDependency(Button master, Control slave) { @Override protected void createFieldEditors() { - Composite appearanceComposite = new Composite(getFieldEditorParent(), SWT.NONE); + Composite composite = createComposite(); + + createUIGroup(composite); + createExternalPreviewParts(composite); + createAsciidoctorGroup(composite); + createSpacer(composite); + createCodeAssistencGroup(composite); + + } + + protected Composite createComposite() { + Composite composite = new Composite(getFieldEditorParent(), SWT.NONE); GridLayout layout = new GridLayout(); layout.numColumns = 2; - appearanceComposite.setLayout(layout); + composite.setLayout(layout); + return composite; + } + + protected void createSpacer(Composite composite) { + Label spacer = new Label(composite, SWT.LEFT); + GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL); + gd.horizontalSpan = 2; + gd.heightHint = convertHeightInCharsToPixels(1) / 2; + spacer.setLayoutData(gd); + } + + protected void createCodeAssistencGroup(Composite composite) { + + GridData codeAssistGroupLayoutData = new GridData(); + codeAssistGroupLayoutData.horizontalSpan = 2; + codeAssistGroupLayoutData.widthHint = 400; + + Group codeAssistGroup = new Group(composite, SWT.NONE); + codeAssistGroup.setText("Code assistence"); + codeAssistGroup.setLayout(new GridLayout()); + codeAssistGroup.setLayoutData(codeAssistGroupLayoutData); + + BooleanFieldEditor codeAssistWithAsciiDoctorKeywords = new BooleanFieldEditor(P_CODE_ASSIST_ADD_KEYWORDS.getId(), + "AsciiDoctor keywords", codeAssistGroup); + codeAssistWithAsciiDoctorKeywords.getDescriptionControl(codeAssistGroup).setToolTipText( + "When enabled the standard keywords supported by asciidoctor editor are always automatically available as code proposals"); + addField(codeAssistWithAsciiDoctorKeywords); + + BooleanFieldEditor codeAssistWithSimpleWords = new BooleanFieldEditor(P_CODE_ASSIST_ADD_SIMPLEWORDS.getId(), "Existing words", + codeAssistGroup); + codeAssistWithSimpleWords.getDescriptionControl(codeAssistGroup).setToolTipText( + "When enabled the current source will be scanned for words. The existing words will be available as code proposals"); + addField(codeAssistWithSimpleWords); + + BooleanFieldEditor toolTipsEnabled = new BooleanFieldEditor(P_TOOLTIPS_ENABLED.getId(), "Tooltips for keywords", codeAssistGroup); + toolTipsEnabled.getDescriptionControl(codeAssistGroup) + .setToolTipText("When enabled tool tips will occure for keywords"); + addField(toolTipsEnabled); + } - Composite uiComposite = new Composite(appearanceComposite, SWT.NONE); + protected void createUIGroup(Composite composite) { + Composite uiComposite = new Composite(composite, SWT.NONE); GridLayout uiLayout = new GridLayout(); uiLayout.marginWidth = 0; uiLayout.marginHeight = 0; @@ -121,12 +162,12 @@ protected void createFieldEditors() { new String[] { "Horizontal", PreviewLayout.HORIZONTAL.getId() }, new String[] { "Hide preview, use external browser", PreviewLayout.EXTERNAL_BROWSER.getId() } }; /* @formatter:on */ - previewDefaultTypeRadioButton = new ComboFieldEditor(P_EDITOR_NEWEDITOR_PREVIEW_LAYOUT.getId(), + ComboFieldEditor previewDefaultTypeRadioButton = new ComboFieldEditor(P_EDITOR_NEWEDITOR_PREVIEW_LAYOUT.getId(), "Default preview layout", entryNamesAndValues, uiComposite); addField(previewDefaultTypeRadioButton); - tocLevels = new IntegerFieldEditor(P_EDITOR_TOC_LEVELS.getId(), "TOC levels shown in preview", uiComposite); + IntegerFieldEditor tocLevels = new IntegerFieldEditor(P_EDITOR_TOC_LEVELS.getId(), "TOC levels shown in preview", uiComposite); tocLevels.setValidRange(0, 7); tocLevels.setTextLimit(1); tocLevels.getLabelControl(uiComposite).setToolTipText( @@ -134,25 +175,24 @@ protected void createFieldEditors() { addField(tocLevels); - linkEditorWithPreviewEnabled = new BooleanFieldEditor(P_LINK_EDITOR_WITH_PREVIEW.getId(), "Link editor with internal preview", uiComposite); + BooleanFieldEditor linkEditorWithPreviewEnabled = new BooleanFieldEditor(P_LINK_EDITOR_WITH_PREVIEW.getId(), "Link editor with internal preview", uiComposite); linkEditorWithPreviewEnabled.getDescriptionControl(uiComposite) .setToolTipText("When enabled editor caret movements are scrolled in internal preview.\n" + "This works only in some situations e.g. when cursor moves to a headline"); addField(linkEditorWithPreviewEnabled); + } - /* --------------------- */ - /* -- External preview-- */ - /* --------------------- */ + protected void createExternalPreviewParts(Composite composite) { GridData externalPreviewGroupLayoutData = new GridData(); externalPreviewGroupLayoutData.horizontalSpan = 2; externalPreviewGroupLayoutData.widthHint = 400; - Group externalPreviewGroup = new Group(appearanceComposite, SWT.NONE); + Group externalPreviewGroup = new Group(composite, SWT.NONE); externalPreviewGroup.setText("External preview"); externalPreviewGroup.setLayout(new GridLayout()); externalPreviewGroup.setLayoutData(externalPreviewGroupLayoutData); - autobuildForExternalPreviewEnabled = new AccessibleBooleanFieldEditor( + AccessibleBooleanFieldEditor autobuildForExternalPreviewEnabled = new AccessibleBooleanFieldEditor( P_EDITOR_AUTOBUILD_FOR_EXTERNAL_PREVIEW_ENABLED.getId(), "Auto build for external preview", externalPreviewGroup); autobuildForExternalPreviewEnabled.getDescriptionControl(externalPreviewGroup).setToolTipText( @@ -160,7 +200,7 @@ protected void createFieldEditors() { + "If disabled only a click to 'refresh' or 'show in external browser' buttons inside the toolbar will rebuild the document.\n\n"); addField(autobuildForExternalPreviewEnabled); - autorefreshSeconds = new IntegerFieldEditor(P_EDITOR_AUTOREFRESH_EXTERNAL_BROWSER_IN_SECONDS.getId(), + IntegerFieldEditor autorefreshSeconds = new IntegerFieldEditor(P_EDITOR_AUTOREFRESH_EXTERNAL_BROWSER_IN_SECONDS.getId(), "Auto refresh in external preview (in seconds)", externalPreviewGroup); autorefreshSeconds.setValidRange(0, 30); autorefreshSeconds.setTextLimit(2); @@ -170,62 +210,41 @@ protected void createFieldEditors() { createDependency(autobuildForExternalPreviewEnabled.getChangeControl(externalPreviewGroup), autorefreshSeconds.getTextControl(externalPreviewGroup)); + } - /* OTHER */ - Composite otherComposite = new Composite(appearanceComposite, SWT.NONE); - GridLayout otherLayout = new GridLayout(); - otherLayout.marginWidth = 0; - otherLayout.marginHeight = 0; - otherComposite.setLayout(otherLayout); - - // /* linking with outline */ - // linkEditorWithOutline = new - // BooleanFieldEditor(P_LINK_OUTLINE_WITH_EDITOR.getId(), - // "New opened editors are linked with outline", otherComposite); - // linkEditorWithOutline.getDescriptionControl(otherComposite) - // .setToolTipText("Via this setting the default behaviour for new - // opened outlines is set"); - // addField(linkEditorWithOutline); - - Label spacer = new Label(appearanceComposite, SWT.LEFT); - GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL); - gd.horizontalSpan = 2; - gd.heightHint = convertHeightInCharsToPixels(1) / 2; - spacer.setLayoutData(gd); - - /* --------------------- */ - /* -- Code assistance -- */ - /* --------------------- */ - - GridData codeAssistGroupLayoutData = new GridData(); - codeAssistGroupLayoutData.horizontalSpan = 2; - codeAssistGroupLayoutData.widthHint = 400; - - Group codeAssistGroup = new Group(appearanceComposite, SWT.NONE); - codeAssistGroup.setText("Code assistence"); - codeAssistGroup.setLayout(new GridLayout()); - codeAssistGroup.setLayoutData(codeAssistGroupLayoutData); - - codeAssistWithAsciiDoctorKeywords = new BooleanFieldEditor(P_CODE_ASSIST_ADD_KEYWORDS.getId(), - "AsciiDoctor keywords", codeAssistGroup); - codeAssistWithAsciiDoctorKeywords.getDescriptionControl(codeAssistGroup).setToolTipText( - "When enabled the standard keywords supported by asciidoctor editor are always automatically available as code proposals"); - addField(codeAssistWithAsciiDoctorKeywords); - - codeAssistWithSimpleWords = new BooleanFieldEditor(P_CODE_ASSIST_ADD_SIMPLEWORDS.getId(), "Existing words", - codeAssistGroup); - codeAssistWithSimpleWords.getDescriptionControl(codeAssistGroup).setToolTipText( - "When enabled the current source will be scanned for words. The existing words will be available as code proposals"); - addField(codeAssistWithSimpleWords); - - toolTipsEnabled = new BooleanFieldEditor(P_TOOLTIPS_ENABLED.getId(), "Tooltips for keywords", codeAssistGroup); - toolTipsEnabled.getDescriptionControl(codeAssistGroup) - .setToolTipText("When enabled tool tips will occure for keywords"); - addField(toolTipsEnabled); - - - + protected void createAsciidoctorGroup(Composite composite) { + GridData groupLayoutData = new GridData(); + groupLayoutData.horizontalSpan = 2; + groupLayoutData.widthHint = 400; + + Group group = new Group(composite, SWT.NONE); + group.setText("Asciidoctor"); + group.setLayout(new GridLayout()); + group.setLayoutData(groupLayoutData); + + AccessibleBooleanFieldEditor useInstalledAsciidoctor = new AccessibleBooleanFieldEditor( + P_USE_INSTALLED_ASCIIDOCTOR_ENABLED.getId(), "Use installed asciidoctor", + group); + useInstalledAsciidoctor.getDescriptionControl(group).setToolTipText( + "When enabled the asciidoctor will be used instead of embedded variant.\n\n" + + "Using the installed version enables you to use templates, newer asciidoctor features etc.\n\n"); + addField(useInstalledAsciidoctor); + + MultiLineStringFieldEditor cliArguments = new MultiLineStringFieldEditor(P_INSTALLED_ASCIICDOCTOR_ARGUMENTS.getId(), + "Additional\nCLI-Arguments", group); + cliArguments.getTextControl().setToolTipText("Setup arguments which shall be added to CLI call of installed asciidoctor instance.\n\nYou can use multiple lines."); + GridData data = new GridData(); + data.verticalAlignment = SWT.CENTER; + data.grabExcessHorizontalSpace = true; + data.grabExcessVerticalSpace = true; + data.heightHint=75; + data.widthHint=250; + cliArguments.getTextControl().setLayoutData(data); + addField(cliArguments); + + createDependency(useInstalledAsciidoctor.getChangeControl(group), + cliArguments.getTextControl(group)); } @Override @@ -264,6 +283,8 @@ private void updateSlaveComponents() { listener.updateSlaveComponent(); } } + + private class MasterButtonSlaveSelectionListener implements SelectionListener { private Button master; diff --git a/asciidoctor-editor-plugin/src/main/java-eclipse/de/jcup/asciidoctoreditor/preferences/AsciiDoctorEditorPreferences.java b/asciidoctor-editor-plugin/src/main/java-eclipse/de/jcup/asciidoctoreditor/preferences/AsciiDoctorEditorPreferences.java index 553fc948..ce047407 100644 --- a/asciidoctor-editor-plugin/src/main/java-eclipse/de/jcup/asciidoctoreditor/preferences/AsciiDoctorEditorPreferences.java +++ b/asciidoctor-editor-plugin/src/main/java-eclipse/de/jcup/asciidoctoreditor/preferences/AsciiDoctorEditorPreferences.java @@ -204,4 +204,12 @@ public PreviewLayout getInitialLayoutModeForNewEditors() { return layout; } + public boolean isUsingInstalledAsciidoctor() { + return getBooleanPreference(P_USE_INSTALLED_ASCIIDOCTOR_ENABLED); + } + + public String getArgumentsForInstalledAsciidoctor(){ + return getStringPreference(P_INSTALLED_ASCIICDOCTOR_ARGUMENTS); + } + } diff --git a/asciidoctor-editor-plugin/src/main/java-eclipse/de/jcup/asciidoctoreditor/preferences/MultiLineStringFieldEditor.java b/asciidoctor-editor-plugin/src/main/java-eclipse/de/jcup/asciidoctoreditor/preferences/MultiLineStringFieldEditor.java new file mode 100644 index 00000000..bd03c5b9 --- /dev/null +++ b/asciidoctor-editor-plugin/src/main/java-eclipse/de/jcup/asciidoctoreditor/preferences/MultiLineStringFieldEditor.java @@ -0,0 +1,505 @@ +package de.jcup.asciidoctoreditor.preferences; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.jface.preference.FieldEditor; +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.FocusAdapter; +import org.eclipse.swt.events.FocusEvent; +import org.eclipse.swt.events.KeyAdapter; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Text; + +/** + * A field editor for a string type preference, adopted from org.eclipse.jface.preference.StringFieldEditor, + * but with multiline support + *

+ * This class may be used as is, or subclassed as required. + *

+ */ +public class MultiLineStringFieldEditor extends FieldEditor { + + /** + * Validation strategy constant (value 0) indicating that + * the editor should perform validation after every key stroke. + * + * @see #setValidateStrategy + */ + public static final int VALIDATE_ON_KEY_STROKE = 0; + + /** + * Validation strategy constant (value 1) indicating that + * the editor should perform validation only when the text widget + * loses focus. + * + * @see #setValidateStrategy + */ + public static final int VALIDATE_ON_FOCUS_LOST = 1; + + /** + * Text limit constant (value -1) indicating unlimited + * text limit and width. + */ + public static int UNLIMITED = -1; + + /** + * Cached valid state. + */ + private boolean isValid; + + /** + * Old text value. + * @since 3.4 this field is protected. + */ + protected String oldValue; + + /** + * The text field, or null if none. + */ + Text textField; + + /** + * Width of text field in characters; initially unlimited. + */ + private int widthInChars = UNLIMITED; + + /** + * Text limit of text field in characters; initially unlimited. + */ + private int textLimit = UNLIMITED; + + /** + * The error message, or null if none. + */ + private String errorMessage; + + /** + * Indicates whether the empty string is legal; + * true by default. + */ + private boolean emptyStringAllowed = true; + + /** + * The validation strategy; + * VALIDATE_ON_KEY_STROKE by default. + */ + private int validateStrategy = VALIDATE_ON_KEY_STROKE; + + /** + * Creates a new string field editor + */ + protected MultiLineStringFieldEditor() { + } + + /** + * Creates a string field editor. + * Use the method setTextLimit to limit the text. + * + * @param name the name of the preference this field editor works on + * @param labelText the label text of the field editor + * @param width the width of the text input field in characters, + * or UNLIMITED for no limit + * @param strategy either VALIDATE_ON_KEY_STROKE to perform + * on the fly checking (the default), or VALIDATE_ON_FOCUS_LOST to + * perform validation only after the text has been typed in + * @param parent the parent of the field editor's control + * @since 2.0 + */ + public MultiLineStringFieldEditor(String name, String labelText, int width, + int strategy, Composite parent) { + init(name, labelText); + widthInChars = width; + setValidateStrategy(strategy); + isValid = false; + errorMessage = JFaceResources + .getString("MultiLineStringFieldEditor.errorMessage");//$NON-NLS-1$ + createControl(parent); + } + + /** + * Creates a string field editor. + * Use the method setTextLimit to limit the text. + * + * @param name the name of the preference this field editor works on + * @param labelText the label text of the field editor + * @param width the width of the text input field in characters, + * or UNLIMITED for no limit + * @param parent the parent of the field editor's control + */ + public MultiLineStringFieldEditor(String name, String labelText, int width, + Composite parent) { + this(name, labelText, width, VALIDATE_ON_KEY_STROKE, parent); + } + + /** + * Creates a string field editor of unlimited width. + * Use the method setTextLimit to limit the text. + * + * @param name the name of the preference this field editor works on + * @param labelText the label text of the field editor + * @param parent the parent of the field editor's control + */ + public MultiLineStringFieldEditor(String name, String labelText, Composite parent) { + this(name, labelText, UNLIMITED, parent); + } + + @Override + protected void adjustForNumColumns(int numColumns) { + GridData gd = (GridData) textField.getLayoutData(); + gd.horizontalSpan = numColumns - 1; + // We only grab excess space if we have to + // If another field editor has more columns then + // we assume it is setting the width. + gd.grabExcessHorizontalSpace = gd.horizontalSpan == 1; + } + + /** + * Checks whether the text input field contains a valid value or not. + * + * @return true if the field value is valid, + * and false if invalid + */ + protected boolean checkState() { + boolean result = false; + if (emptyStringAllowed) { + result = true; + } + + if (textField == null) { + result = false; + } else { + String txt = textField.getText(); + result = (txt.trim().length() > 0) || emptyStringAllowed; + } + + // call hook for subclasses + result = result && doCheckState(); + + if (result) { + clearErrorMessage(); + } else { + showErrorMessage(errorMessage); + } + + return result; + } + + /** + * Hook for subclasses to do specific state checks. + *

+ * The default implementation of this framework method does + * nothing and returns true. Subclasses should + * override this method to specific state checks. + *

+ * + * @return true if the field value is valid, + * and false if invalid + */ + protected boolean doCheckState() { + return true; + } + + /** + * Fills this field editor's basic controls into the given parent. + *

+ * The string field implementation of this FieldEditor + * framework method contributes the text field. Subclasses may override + * but must call super.doFillIntoGrid. + *

+ */ + @Override + protected void doFillIntoGrid(Composite parent, int numColumns) { + getLabelControl(parent); + + textField = getTextControl(parent); + GridData gd = new GridData(); + gd.horizontalSpan = numColumns - 1; + if (widthInChars != UNLIMITED) { + GC gc = new GC(textField); + try { + Point extent = gc.textExtent("X");//$NON-NLS-1$ + gd.widthHint = widthInChars * extent.x; + } finally { + gc.dispose(); + } + } else { + gd.horizontalAlignment = GridData.FILL; + gd.grabExcessHorizontalSpace = true; + } + textField.setLayoutData(gd); + } + + @Override + protected void doLoad() { + if (textField != null) { + String value = getPreferenceStore().getString(getPreferenceName()); + textField.setText(value); + oldValue = value; + } + } + + @Override + protected void doLoadDefault() { + if (textField != null) { + String value = getPreferenceStore().getDefaultString( + getPreferenceName()); + textField.setText(value); + } + valueChanged(); + } + + @Override + protected void doStore() { + getPreferenceStore().setValue(getPreferenceName(), textField.getText()); + } + + /** + * Returns the error message that will be displayed when and if + * an error occurs. + * + * @return the error message, or null if none + */ + public String getErrorMessage() { + return errorMessage; + } + + @Override + public int getNumberOfControls() { + return 2; + } + + /** + * Returns the field editor's value. + * + * @return the current value + */ + public String getStringValue() { + if (textField != null) { + return textField.getText(); + } + + return getPreferenceStore().getString(getPreferenceName()); + } + + /** + * Returns this field editor's text control. + * + * @return the text control, or null if no + * text field is created yet + */ + protected Text getTextControl() { + return textField; + } + + /** + * Returns this field editor's text control. + *

+ * The control is created if it does not yet exist + *

+ * + * @param parent the parent + * @return the text control + */ + public Text getTextControl(Composite parent) { + if (textField == null) { + textField = new Text(parent, SWT.MULTI | SWT.V_SCROLL | SWT.BORDER); + textField.setFont(parent.getFont()); + switch (validateStrategy) { + case VALIDATE_ON_KEY_STROKE: + textField.addKeyListener(new KeyAdapter() { + + @Override + public void keyReleased(KeyEvent e) { + valueChanged(); + } + }); + textField.addFocusListener(new FocusAdapter() { + // Ensure that the value is checked on focus loss in case we + // missed a keyRelease or user hasn't released key. + // See https://bugs.eclipse.org/bugs/show_bug.cgi?id=214716 + @Override + public void focusLost(FocusEvent e) { + valueChanged(); + } + }); + + + break; + case VALIDATE_ON_FOCUS_LOST: + textField.addKeyListener(new KeyAdapter() { + @Override + public void keyPressed(KeyEvent e) { + clearErrorMessage(); + } + }); + textField.addFocusListener(new FocusAdapter() { + @Override + public void focusGained(FocusEvent e) { + refreshValidState(); + } + + @Override + public void focusLost(FocusEvent e) { + valueChanged(); + clearErrorMessage(); + } + }); + break; + default: + Assert.isTrue(false, "Unknown validate strategy");//$NON-NLS-1$ + } + textField.addDisposeListener(event -> textField = null); + if (textLimit > 0) {//Only set limits above 0 - see SWT spec + textField.setTextLimit(textLimit); + } + } else { + checkParent(textField, parent); + } + return textField; + } + + /** + * Returns whether an empty string is a valid value. + * + * @return true if an empty string is a valid value, and + * false if an empty string is invalid + * @see #setEmptyStringAllowed + */ + public boolean isEmptyStringAllowed() { + return emptyStringAllowed; + } + + @Override + public boolean isValid() { + return isValid; + } + + @Override + protected void refreshValidState() { + isValid = checkState(); + } + + /** + * Sets whether the empty string is a valid value or not. + * + * @param b true if the empty string is allowed, + * and false if it is considered invalid + */ + public void setEmptyStringAllowed(boolean b) { + emptyStringAllowed = b; + } + + /** + * Sets the error message that will be displayed when and if + * an error occurs. + * + * @param message the error message + */ + public void setErrorMessage(String message) { + errorMessage = message; + } + + @Override + public void setFocus() { + if (textField != null) { + textField.setFocus(); + } + } + + /** + * Sets this field editor's value. + * + * @param value the new value, or null meaning the empty string + */ + public void setStringValue(String value) { + if (textField != null) { + if (value == null) { + value = "";//$NON-NLS-1$ + } + oldValue = textField.getText(); + if (!oldValue.equals(value)) { + textField.setText(value); + valueChanged(); + } + } + } + + /** + * Sets this text field's text limit. + * + * @param limit the limit on the number of character in the text + * input field, or UNLIMITED for no limit + + */ + public void setTextLimit(int limit) { + textLimit = limit; + if (textField != null) { + textField.setTextLimit(limit); + } + } + + /** + * Sets the strategy for validating the text. + *

+ * Calling this method has no effect after createPartControl + * is called. Thus this method is really only useful for subclasses to call + * in their constructor. However, it has public visibility for backward + * compatibility. + *

+ * + * @param value either VALIDATE_ON_KEY_STROKE to perform + * on the fly checking (the default), or VALIDATE_ON_FOCUS_LOST to + * perform validation only after the text has been typed in + */ + public void setValidateStrategy(int value) { + Assert.isTrue(value == VALIDATE_ON_FOCUS_LOST + || value == VALIDATE_ON_KEY_STROKE); + validateStrategy = value; + } + + /** + * Shows the error message set via setErrorMessage. + */ + public void showErrorMessage() { + showErrorMessage(errorMessage); + } + + /** + * Informs this field editor's listener, if it has one, about a change + * to the value (VALUE property) provided that the old and + * new values are different. + *

+ * This hook is not called when the text is initialized + * (or reset to the default value) from the preference store. + *

+ */ + protected void valueChanged() { + setPresentsDefaultValue(false); + boolean oldState = isValid; + refreshValidState(); + + if (isValid != oldState) { + fireStateChanged(IS_VALID, oldState, isValid); + } + + String newValue = textField.getText(); + if (!newValue.equals(oldValue)) { + fireValueChanged(VALUE, oldValue, newValue); + oldValue = newValue; + } + } + + /* + * @see FieldEditor.setEnabled(boolean,Composite). + */ + @Override + public void setEnabled(boolean enabled, Composite parent) { + super.setEnabled(enabled, parent); + getTextControl(parent).setEnabled(enabled); + } +} + diff --git a/asciidoctor-editor-plugin/src/main/java/de/jcup/asciidoctoreditor/CLITextUtil.java b/asciidoctor-editor-plugin/src/main/java/de/jcup/asciidoctoreditor/CLITextUtil.java new file mode 100644 index 00000000..2f356a96 --- /dev/null +++ b/asciidoctor-editor-plugin/src/main/java/de/jcup/asciidoctoreditor/CLITextUtil.java @@ -0,0 +1,25 @@ +package de.jcup.asciidoctoreditor; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Pattern; + +public class CLITextUtil { + private static final Pattern P = Pattern.compile("[\n\t]"); + + public static List convertToList(String string) { + List list = new ArrayList(); + if (string==null){ + return list; + } + String transformed = P.matcher(string).replaceAll(" "); + String[] lines = transformed.split(" "); + for (String line: lines){ + if (!line.isEmpty()){ + list.add(line); + } + } + return list; + } + +} diff --git a/asciidoctor-editor-plugin/src/main/java/de/jcup/asciidoctoreditor/OSUtil.java b/asciidoctor-editor-plugin/src/main/java/de/jcup/asciidoctoreditor/OSUtil.java new file mode 100644 index 00000000..dc6c8306 --- /dev/null +++ b/asciidoctor-editor-plugin/src/main/java/de/jcup/asciidoctoreditor/OSUtil.java @@ -0,0 +1,17 @@ +package de.jcup.asciidoctoreditor; + +public class OSUtil { + + private static Boolean isWindows; + static{ + String os = System.getProperty("os.name"); + if (os==null || os.toLowerCase().indexOf("windows")!=-1){ + isWindows=Boolean.TRUE; + }else{ + isWindows=Boolean.FALSE; + } + } + public static boolean isWindows() { + return isWindows.booleanValue(); + } +} diff --git a/asciidoctor-editor-plugin/src/test/java/de/jcup/asciidoctoreditor/CLITextUtilTest.java b/asciidoctor-editor-plugin/src/test/java/de/jcup/asciidoctoreditor/CLITextUtilTest.java new file mode 100644 index 00000000..b158a81e --- /dev/null +++ b/asciidoctor-editor-plugin/src/test/java/de/jcup/asciidoctoreditor/CLITextUtilTest.java @@ -0,0 +1,87 @@ +package de.jcup.asciidoctoreditor; + +import static org.junit.Assert.*; + +import java.util.Arrays; +import java.util.List; + +import org.junit.Test; + +public class CLITextUtilTest { + + + @Test + public void alpha_newline_omega_results_in_two_entries() { + List commands = CLITextUtil.convertToList("alpha\nomega"); + assertContains(commands, "alpha","omega"); + } + @Test + public void newline_alpha_newline_omega_results_in_two_entries() { + List commands = CLITextUtil.convertToList("\nalpha\nomega"); + assertContains(commands, "alpha","omega"); + } + + @Test + public void alpha_newline_omega_newline_results_in_two_entries() { + List commands = CLITextUtil.convertToList("alpha\nomega\n"); + assertContains(commands, "alpha","omega"); + } + @Test + public void alpha_newline_newline_omega_results_in_two_entries() { + List commands = CLITextUtil.convertToList("alpha\n\nomega"); + assertContains(commands, "alpha","omega"); + } + + @Test + public void alpha_gamma_newline_newline_omega_results_in_three_entries() { + List commands = CLITextUtil.convertToList("alpha gamma\n\nomega"); + assertContains(commands, "alpha","gamma","omega"); + } + + @Test + public void _5spaces_alpha_gamma_newline_newline_omega_results_in_three_entries() { + List commands = CLITextUtil.convertToList(" alpha gamma\n\nomega"); + assertContains(commands, "alpha","gamma","omega"); + } + @Test + public void _5spaces_alpha_2tabs_gamma_newline_newline_omega_results_in_three_entries() { + List commands = CLITextUtil.convertToList(" alpha gamma\n\nomega"); + assertContains(commands, "alpha","gamma","omega"); + } + + @Test + public void realWorld_example() { + List commands = CLITextUtil.convertToList("-r asciidoctor-diagram -r asciidoctor-pdf\n-r asciidoctor-rouge -a source-highlighter=rouge"); + assertContains(commands, "-r","asciidoctor-diagram","-r","asciidoctor-pdf","-r","asciidoctor-rouge","-a","source-highlighter=rouge"); + } + + + @Test + public void null_is_empty_list() { + List commands = CLITextUtil.convertToList(null); + + assertNotNull(commands); + assertTrue(commands.isEmpty()); + } + + @Test + public void spaces_string_is_empty_list() { + List commands = CLITextUtil.convertToList(" "); + + assertNotNull(commands); + assertTrue(commands.isEmpty()); + } + + @Test + public void emty_string_is_empty_list() { + List commands = CLITextUtil.convertToList(""); + + assertNotNull(commands); + assertTrue(commands.isEmpty()); + } + + private void assertContains(List commands, String ...expected){ + assertEquals(Arrays.asList(expected),commands); + } + +}