From 43dbad91fccb07ef25c5c1f03e88243b0a4b62d4 Mon Sep 17 00:00:00 2001 From: Denys Almazov Date: Fri, 19 Jul 2024 07:37:56 +0300 Subject: [PATCH] IEP-1276 Provide a configuration option in the launch configuration and open the serial monitor (#1013) * feat: open serial monitor after flashing --- .../idf/core/build/IDFLaunchConstants.java | 2 + .../META-INF/MANIFEST.MF | 7 +- .../SerialFlashLaunchConfigDelegate.java | 36 +++++- .../META-INF/MANIFEST.MF | 3 +- .../serial/ui/internal/CMakeMainTab2.java | 106 +++++++++++++++++- .../launch/serial/ui/internal/Messages.java | 12 +- .../serial/ui/internal/messages.properties | 3 + 7 files changed, 155 insertions(+), 14 deletions(-) diff --git a/bundles/com.espressif.idf.core/src/com/espressif/idf/core/build/IDFLaunchConstants.java b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/build/IDFLaunchConstants.java index de426384d..b4567f210 100644 --- a/bundles/com.espressif.idf.core/src/com/espressif/idf/core/build/IDFLaunchConstants.java +++ b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/build/IDFLaunchConstants.java @@ -17,4 +17,6 @@ public final class IDFLaunchConstants public static final String ATTR_LAUNCH_CONFIGURATION_NAME = "com.espressif.idf.debug.gdbjtag.openocd.launchConfigurationName"; //$NON-NLS-1$ public static final String ATTR_SERIAL_PORT = "com.espressif.idf.launch.serial.core.serialPort"; //$NON-NLS-1$ public static final String IDF_TARGET_TYPE = "com.espressif.idf.launch.serial.core.serialFlashTarget"; //$NON-NLS-1$ + public static final String OPEN_SERIAL_MONITOR = "OPEN_SERIAL_MONITOR"; //$NON-NLS-1$ + public static final String SERIAL_MONITOR_ENCODING = "SERIAL_MONITOR_ENCODING"; //$NON-NLS-1$ } diff --git a/bundles/com.espressif.idf.launch.serial.core/META-INF/MANIFEST.MF b/bundles/com.espressif.idf.launch.serial.core/META-INF/MANIFEST.MF index 6a3b4039f..bafe4b2ff 100644 --- a/bundles/com.espressif.idf.launch.serial.core/META-INF/MANIFEST.MF +++ b/bundles/com.espressif.idf.launch.serial.core/META-INF/MANIFEST.MF @@ -16,7 +16,8 @@ Require-Bundle: org.eclipse.core.runtime;bundle-version="3.13.0", com.espressif.idf.ui, com.espressif.idf.terminal.connector.serial, org.eclipse.launchbar.ui, - org.eclipse.embedcdt.core + org.eclipse.embedcdt.core, + org.eclipse.tm.terminal.view.core Export-Package: com.espressif.idf.launch.serial, com.espressif.idf.launch.serial.core, com.espressif.idf.launch.serial.internal, @@ -24,4 +25,6 @@ Export-Package: com.espressif.idf.launch.serial, Bundle-Activator: com.espressif.idf.launch.serial.internal.Activator Bundle-ActivationPolicy: lazy Automatic-Module-Name: org.eclipse.cdt.launch.serial.core -Import-Package: org.eclipse.cdt.dsf.gdb +Import-Package: org.eclipse.cdt.dsf.gdb, + org.eclipse.tm.terminal.view.core, + org.eclipse.tm.terminal.view.ui.launcher diff --git a/bundles/com.espressif.idf.launch.serial.core/src/com/espressif/idf/launch/serial/internal/SerialFlashLaunchConfigDelegate.java b/bundles/com.espressif.idf.launch.serial.core/src/com/espressif/idf/launch/serial/internal/SerialFlashLaunchConfigDelegate.java index 47e800d2a..448f6c3c2 100644 --- a/bundles/com.espressif.idf.launch.serial.core/src/com/espressif/idf/launch/serial/internal/SerialFlashLaunchConfigDelegate.java +++ b/bundles/com.espressif.idf.launch.serial.core/src/com/espressif/idf/launch/serial/internal/SerialFlashLaunchConfigDelegate.java @@ -19,6 +19,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -47,6 +48,8 @@ import org.eclipse.launchbar.ui.internal.Activator; import org.eclipse.launchbar.ui.target.ILaunchTargetUIManager; import org.eclipse.swt.widgets.Display; +import org.eclipse.tm.terminal.view.core.interfaces.constants.ITerminalsConnectorConstants; +import org.eclipse.ui.WorkbenchEncoding; import com.espressif.idf.core.IDFCorePlugin; import com.espressif.idf.core.IDFEnvironmentVariables; @@ -58,6 +61,8 @@ import com.espressif.idf.core.util.StringUtil; import com.espressif.idf.launch.serial.SerialFlashLaunchTargetProvider; import com.espressif.idf.launch.serial.util.ESPFlashUtil; +import com.espressif.idf.terminal.connector.serial.connector.SerialSettings; +import com.espressif.idf.terminal.connector.serial.launcher.SerialLauncherDelegate; /** * Flashing into esp32 board @@ -66,12 +71,6 @@ @SuppressWarnings("restriction") public class SerialFlashLaunchConfigDelegate extends CoreBuildGenericLaunchConfigDelegate { - private static final String OPENOCD_PREFIX = "com.espressif.idf.debug.gdbjtag.openocd"; //$NON-NLS-1$ - private static final String INSTALL_FOLDER = "install.folder"; //$NON-NLS-1$ - private static final String SERVER_EXECUTABLE = OPENOCD_PREFIX + ".openocd.gdbServerExecutable"; //$NON-NLS-1$ - private static final String DEFAULT_PATH = "${openocd_path}/"; //$NON-NLS-1$ - private static final String DEFAULT_EXECUTABLE = "bin/openocd"; //$NON-NLS-1$ - private static final String SYSTEM_PATH_PYTHON = "${system_path:python}"; //$NON-NLS-1$ private String serialPort; @Override @@ -188,6 +187,31 @@ protected void launchInternal(ILaunchConfiguration configuration, String mode, I String[] envArray = strings.toArray(new String[strings.size()]); Process p = DebugPlugin.exec(commands.toArray(new String[0]), workingDir, envArray); DebugPlugin.newProcess(launch, p, String.join(" ", commands)); //$NON-NLS-1$ + + try + { + p.waitFor(); + } + catch (InterruptedException e) + { + Thread.currentThread().interrupt(); + Logger.log(e); + } + if (configuration.getAttribute(IDFLaunchConstants.OPEN_SERIAL_MONITOR, true)) + openSerialMonitor(configuration); + + } + + private void openSerialMonitor(ILaunchConfiguration configuration) throws CoreException + { + Map map = new HashMap<>(); + map.put("delegateId", "com.espressif.idf.terminal.connector.serial.launcher.serial"); //$NON-NLS-1$//$NON-NLS-2$ + map.put(SerialSettings.PORT_NAME_ATTR, serialPort); + map.put("idf.monitor.project", configuration.getMappedResources()[0].getName()); //$NON-NLS-1$ + map.put(ITerminalsConnectorConstants.PROP_ENCODING, configuration.getAttribute( + IDFLaunchConstants.SERIAL_MONITOR_ENCODING, WorkbenchEncoding.getWorkbenchDefaultEncoding())); + map.put(ITerminalsConnectorConstants.PROP_FORCE_NEW, Boolean.FALSE); + new SerialLauncherDelegate().execute(map, null); } private boolean checkIfPortIsEmpty(ILaunchConfiguration configuration) diff --git a/bundles/com.espressif.idf.launch.serial.ui/META-INF/MANIFEST.MF b/bundles/com.espressif.idf.launch.serial.ui/META-INF/MANIFEST.MF index bd635e79b..bb915ec76 100644 --- a/bundles/com.espressif.idf.launch.serial.ui/META-INF/MANIFEST.MF +++ b/bundles/com.espressif.idf.launch.serial.ui/META-INF/MANIFEST.MF @@ -16,7 +16,8 @@ Require-Bundle: org.eclipse.core.runtime;bundle-version="3.13.0", com.espressif.idf.core, org.eclipse.cdt.core, org.eclipse.jface, - org.eclipse.core.variables + org.eclipse.core.variables, + org.eclipse.ui.ide Bundle-Activator: com.espressif.idf.launch.serial.ui.internal.Activator Bundle-ActivationPolicy: lazy Automatic-Module-Name: org.eclipse.cdt.launch.serial.ui diff --git a/bundles/com.espressif.idf.launch.serial.ui/src/com/espressif/idf/launch/serial/ui/internal/CMakeMainTab2.java b/bundles/com.espressif.idf.launch.serial.ui/src/com/espressif/idf/launch/serial/ui/internal/CMakeMainTab2.java index e863a7f26..7b745ca04 100644 --- a/bundles/com.espressif.idf.launch.serial.ui/src/com/espressif/idf/launch/serial/ui/internal/CMakeMainTab2.java +++ b/bundles/com.espressif.idf.launch.serial.ui/src/com/espressif/idf/launch/serial/ui/internal/CMakeMainTab2.java @@ -16,6 +16,8 @@ import java.io.File; import java.net.URI; +import java.nio.charset.Charset; +import java.nio.charset.IllegalCharsetNameException; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Arrays; @@ -43,6 +45,8 @@ import org.eclipse.core.variables.VariablesPlugin; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; +import org.eclipse.debug.internal.ui.SWTFactory; +import org.eclipse.debug.internal.ui.launchConfigurations.LaunchConfigurationsMessages; import org.eclipse.debug.ui.StringVariableSelectionDialog; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.viewers.ILabelProvider; @@ -50,6 +54,7 @@ import org.eclipse.launchbar.core.ILaunchBarManager; import org.eclipse.launchbar.core.target.ILaunchTargetManager; import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.ScrolledComposite; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridData; @@ -62,6 +67,7 @@ import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.dialogs.ElementListSelectionDialog; +import org.eclipse.ui.ide.IDEEncoding; import org.json.simple.JSONArray; import com.espressif.idf.core.DefaultBoardProvider; @@ -102,6 +108,8 @@ public class CMakeMainTab2 extends GenericMainTab private Combo comboTargets; private ILaunchBarManager launchBarManager = Activator.getService(ILaunchBarManager.class); private ILaunchTargetManager targetManager = Activator.getService(ILaunchTargetManager.class); + private Button checkOpenSerialMonitorButton; + private Combo fEncodingCombo; public enum FlashInterface { @@ -130,8 +138,9 @@ public void createControl(Composite parent) isJtagFlashAvailable = ESPFlashUtil.checkIfJtagIsAvailable(); setControl(mainComposite); createJtagFlashButton(mainComposite); - createDfuTargetComposite(mainComposite); + createOpenSerialMonitorGroup(mainComposite); createProjectGroup(mainComposite, 0); + createDfuTargetComposite(mainComposite); createUartComposite(mainComposite); createJtagflashComposite(mainComposite); createDfuArgumentField(mainComposite); @@ -535,6 +544,14 @@ private void switchUI(FlashInterface flashInterface) switchComposites.get(flashInterface).forEach(composite -> composite.setVisible(true)); mainComposite.requestLayout(); + + // Update the layout and size of the parent composite if it is a ScrolledComposite + if (mainComposite.getParent() instanceof ScrolledComposite sc) + { + mainComposite.setSize(mainComposite.computeSize(SWT.DEFAULT, SWT.DEFAULT)); + sc.setMinSize(mainComposite.computeSize(SWT.DEFAULT, SWT.DEFAULT)); + mainComposite.layout(true, true); + } } @Override @@ -582,7 +599,7 @@ public boolean isValid(ILaunchConfiguration launchConfig) } return false; } - return isConfigValid && hasProject; + return isConfigValid && hasProject && validateEncoding(); } @Override @@ -621,6 +638,9 @@ else if (isFlashOverJtag) wc.setAttribute(IDFLaunchConstants.ATTR_JTAG_FLASH_ARGUMENTS, jtagArgumentsField.getText()); wc.setAttribute(IDFLaunchConstants.ATTR_SERIAL_FLASH_ARGUMENTS, uartAgrumentsField.getText()); wc.setAttribute(IDFLaunchConstants.ATTR_DFU_FLASH_ARGUMENTS, dfuArgumentsField.getText()); + wc.setAttribute(IDFLaunchConstants.OPEN_SERIAL_MONITOR, checkOpenSerialMonitorButton.getSelection()); + if (checkOpenSerialMonitorButton.getSelection()) + wc.setAttribute(IDFLaunchConstants.SERIAL_MONITOR_ENCODING, fEncodingCombo.getText()); wc.doSave(); } catch (CoreException e) @@ -639,6 +659,7 @@ private void saveLaunchTargetName(ILaunchConfigurationWorkingCopy wc, String tar public void initializeFrom(ILaunchConfiguration configuration) { super.initializeFrom(configuration); + updateStartSerialMonitorGroup(configuration); updateProjetFromConfig(configuration); updateFlashOverStatus(configuration); updateArgumentsWithDefaultFlashCommand(configuration); @@ -918,4 +939,85 @@ private void scheduleApplyTargetJob() new NewSerialFlashTargetWizard()); applyTargetJob.schedule(JOB_DELAY_MS); } + + private void createOpenSerialMonitorGroup(Composite mainComposite) + { + Group group = SWTFactory.createGroup(mainComposite, Messages.CMakeMainTab2_SerialMonitorGroup, 2, 1, + GridData.FILL_HORIZONTAL); + checkOpenSerialMonitorButton = new Button(group, SWT.CHECK); + checkOpenSerialMonitorButton.setText(Messages.CMakeMainTab2_SerialMonitorBtn); + GridData gd = new GridData(SWT.FILL, SWT.FILL, false, false); + gd.horizontalSpan = 2; + checkOpenSerialMonitorButton.setLayoutData(gd); + Label encodingLbl = new Label(group, SWT.NONE); + encodingLbl.setText(Messages.CMakeMainTab2_SerialMonitorEncodingLbl); + fEncodingCombo = new Combo(group, SWT.READ_ONLY); + fEncodingCombo.setLayoutData(new GridData(GridData.BEGINNING)); + List allEncodings = IDEEncoding.getIDEEncodings(); + String[] encodingArray = allEncodings.toArray(new String[0]); + fEncodingCombo.setItems(encodingArray); + if (encodingArray.length > 0) + fEncodingCombo.select(0); + + fEncodingCombo.addModifyListener(e -> updateLaunchConfigurationDialog()); + checkOpenSerialMonitorButton.addSelectionListener(new SelectionAdapter() + { + @Override + public void widgetSelected(SelectionEvent e) + { + fEncodingCombo.setVisible(checkOpenSerialMonitorButton.getSelection()); + GridData data = (GridData) fEncodingCombo.getLayoutData(); + data.exclude = !fEncodingCombo.getVisible(); + encodingLbl.setVisible(checkOpenSerialMonitorButton.getSelection()); + data = (GridData) encodingLbl.getLayoutData(); + data.exclude = !encodingLbl.getVisible(); + mainComposite.layout(true, true); + updateLaunchConfigurationDialog(); + } + }); + } + + private void updateStartSerialMonitorGroup(ILaunchConfiguration configuration) + { + try + { + checkOpenSerialMonitorButton + .setSelection(configuration.getAttribute(IDFLaunchConstants.OPEN_SERIAL_MONITOR, true)); + checkOpenSerialMonitorButton.notifyListeners(SWT.Selection, null); + int encodingIndex = fEncodingCombo + .indexOf(configuration.getAttribute(IDFLaunchConstants.SERIAL_MONITOR_ENCODING, StringUtil.EMPTY)); + encodingIndex = encodingIndex == -1 ? 0 : encodingIndex; + fEncodingCombo.select(encodingIndex); + } + catch (CoreException e) + { + Logger.log(e); + } + + } + + private boolean validateEncoding() + { + if (checkOpenSerialMonitorButton.getSelection() && fEncodingCombo.getSelectionIndex() == -1 + && !isValidEncoding(fEncodingCombo.getText().trim())) + { + setErrorMessage(LaunchConfigurationsMessages.CommonTab_15); + return false; + } + return true; + } + + private boolean isValidEncoding(String enc) + { + try + { + return Charset.isSupported(enc); + } + catch (IllegalCharsetNameException e) + { + // This is a valid exception + return false; + } + } + } diff --git a/bundles/com.espressif.idf.launch.serial.ui/src/com/espressif/idf/launch/serial/ui/internal/Messages.java b/bundles/com.espressif.idf.launch.serial.ui/src/com/espressif/idf/launch/serial/ui/internal/Messages.java index 145ab23f3..bf9b12248 100644 --- a/bundles/com.espressif.idf.launch.serial.ui/src/com/espressif/idf/launch/serial/ui/internal/Messages.java +++ b/bundles/com.espressif.idf.launch.serial.ui/src/com/espressif/idf/launch/serial/ui/internal/Messages.java @@ -17,7 +17,8 @@ import org.eclipse.osgi.util.NLS; -public class Messages extends NLS { +public class Messages extends NLS +{ private static final String BUNDLE_NAME = "com.espressif.idf.launch.serial.ui.internal.messages"; //$NON-NLS-1$ public static String NewSerialFlashTargetWizard_Title; public static String NewSerialFlashTargetWizardPage_Description; @@ -47,17 +48,22 @@ public class Messages extends NLS { public static String IDFLaunchTargetNotFoundMsg2; public static String IDFLaunchTargetNotFoundIDFLaunchTargetNotFoundTitle; public static String IDFLaunchTargetNotFoundMsg3; + public static String CMakeMainTab2_SerialMonitorBtn; + public static String CMakeMainTab2_SerialMonitorGroup; + public static String CMakeMainTab2_SerialMonitorEncodingLbl; public static String TargetPortUpdatingMessage; public static String TargetPortInformationMessage; public static String TargetPortFoundMessage; public static String TargetPortNotFoundMessage; - static { + static + { // initialize resource bundle NLS.initializeMessages(BUNDLE_NAME, Messages.class); } - private Messages() { + private Messages() + { } } diff --git a/bundles/com.espressif.idf.launch.serial.ui/src/com/espressif/idf/launch/serial/ui/internal/messages.properties b/bundles/com.espressif.idf.launch.serial.ui/src/com/espressif/idf/launch/serial/ui/internal/messages.properties index 881d23440..85ec9250d 100644 --- a/bundles/com.espressif.idf.launch.serial.ui/src/com/espressif/idf/launch/serial/ui/internal/messages.properties +++ b/bundles/com.espressif.idf.launch.serial.ui/src/com/espressif/idf/launch/serial/ui/internal/messages.properties @@ -32,6 +32,9 @@ configBoardTooTip=Select a board based on ESP target CMakeMainTab2_OpeonOcdSetupGroupTitle=OpenOCD Setup: CMakeMainTab2_JtagFlashingNotSupportedMsg=(JTAG flash functionality isn't available, please update OpenOCD. The minimum required version is v0.10.0-esp32-20210401) CMakeMainTab2_SettingTargetJob=Setting a target in launch bar... +CMakeMainTab2_SerialMonitorBtn=Open Serial Monitor After Flashing +CMakeMainTab2_SerialMonitorGroup=Serial Monitor Settings +CMakeMainTab2_SerialMonitorEncodingLbl=Encoding: IDFLaunchTargetNotFoundMsg1=IDF Launch Target with IDFLaunchTargetNotFoundMsg2=\ is not found.