Skip to content

Commit 77945c8

Browse files
committed
updated to handle the eim cli wizard properly in IDE
1 parent 87c8ecf commit 77945c8

11 files changed

Lines changed: 629 additions & 33 deletions

bundles/com.espressif.idf.ui/META-INF/MANIFEST.MF

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,12 @@ Require-Bundle: org.eclipse.core.runtime,
3030
org.eclipse.ltk.core.refactoring,
3131
org.eclipse.tools.templates.core,
3232
org.eclipse.tools.templates.ui,
33-
org.eclipse.ui.intro
33+
org.eclipse.ui.intro,
34+
org.eclipse.jface,
35+
org.eclipse.terminal.view.ui;bundle-version="[1.0.0,2.0.0)",
36+
org.eclipse.terminal.view.core;bundle-version="[1.0.0,2.0.0)",
37+
org.eclipse.terminal.connector.process;bundle-version="[1.0.0,2.0.0)",
38+
org.eclipse.terminal.control;bundle-version="[1.0.0,2.0.0)"
3439
Automatic-Module-Name: com.espressif.idf.ui
3540
Bundle-ActivationPolicy: lazy
3641
Bundle-RequiredExecutionEnvironment: JavaSE-21
@@ -45,6 +50,7 @@ Bundle-ClassPath: .,
4550
lib/gson-2.8.7.jar,
4651
lib/commonmark-0.24.0.jar,
4752
lib/jfreechart-1.5.5.jar
48-
Import-Package: org.eclipse.core.expressions,
53+
Import-Package: org.eclipse.cdt.utils.pty;mandatory:=native,
54+
org.eclipse.core.expressions,
4955
org.eclipse.tools.templates.freemarker,
5056
org.eclipse.ui.editors.text

bundles/com.espressif.idf.ui/plugin.xml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -904,4 +904,21 @@
904904
parentId="org.eclipse.ui.textEditorScope">
905905
</context>
906906
</extension>
907+
<extension
908+
point="org.eclipse.terminal.control.connectors">
909+
<connector
910+
class="com.espressif.idf.ui.tools.eim.terminal.EimCliTerminalConnector"
911+
hidden="true"
912+
id="com.espressif.idf.ui.eimCliTerminalConnector"
913+
name="EIM CLI">
914+
</connector>
915+
</extension>
916+
<extension
917+
point="org.eclipse.terminal.view.ui.launcherDelegates">
918+
<delegate
919+
class="com.espressif.idf.ui.tools.eim.terminal.EimCliTerminalLauncherDelegate"
920+
id="com.espressif.idf.ui.launcher.eimCliTerminal"
921+
label="EIM CLI Wizard">
922+
</delegate>
923+
</extension>
907924
</plugin>

bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/EimButtonLaunchListener.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
import com.espressif.idf.core.tools.EimLoader;
2929
import com.espressif.idf.core.tools.ToolInitializer;
3030
import com.espressif.idf.core.tools.exceptions.EimVersionMismatchException;
31-
import com.espressif.idf.core.tools.launch.LaunchResult;
3231
import com.espressif.idf.core.tools.vo.EimJson;
3332
import com.espressif.idf.ui.UIPlugin;
3433
import com.espressif.idf.ui.handlers.EclipseHandler;
@@ -88,8 +87,9 @@ protected IStatus run(IProgressMonitor monitor)
8887
{
8988
try
9089
{
91-
var launchResult = eimLoader.launchEimWithResult(idfEnvironmentVariables.getEnvValue(IDFEnvironmentVariables.EIM_PATH));
92-
eimLoader.waitForEimClosure(launchResult, EimButtonLaunchListener.this::refreshAfterEimClose);
90+
EimGuiOrCliLauncher.launch(toolInitializer, eimLoader,
91+
idfEnvironmentVariables.getEnvValue(IDFEnvironmentVariables.EIM_PATH), standardConsoleStream,
92+
display, EimButtonLaunchListener.this::refreshAfterEimClose);
9393
}
9494
catch (IOException e)
9595
{
@@ -199,8 +199,8 @@ public void onCompleted(String filePath)
199199
try
200200
{
201201
idfEnvironmentVariables.addEnvVariable(IDFEnvironmentVariables.EIM_PATH, appToLaunch);
202-
LaunchResult launchResult = eimLoader.launchEimWithResult(appToLaunch);
203-
eimLoader.waitForEimClosure(launchResult, EimButtonLaunchListener.this::refreshAfterEimClose);
202+
EimGuiOrCliLauncher.launch(toolInitializer, eimLoader, appToLaunch, standardConsoleStream, display,
203+
EimButtonLaunchListener.this::refreshAfterEimClose);
204204
}
205205
catch (IOException e)
206206
{
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/*******************************************************************************
2+
* Copyright 2026 Espressif Systems (Shanghai) PTE LTD. All rights reserved.
3+
* Use is subject to license terms.
4+
*******************************************************************************/
5+
package com.espressif.idf.ui.tools;
6+
7+
import java.io.IOException;
8+
9+
import org.eclipse.swt.widgets.Display;
10+
import org.eclipse.ui.console.MessageConsoleStream;
11+
12+
import com.espressif.idf.core.logging.Logger;
13+
import com.espressif.idf.core.tools.EimLoader;
14+
import com.espressif.idf.core.tools.ToolInitializer;
15+
import com.espressif.idf.core.tools.launch.LaunchResult;
16+
import com.espressif.idf.core.tools.watcher.EimJsonWatchService;
17+
import com.espressif.idf.ui.tools.eim.terminal.EimCliTerminalLaunchSupport;
18+
19+
/**
20+
* Launches EIM as a GUI app when the binary supports it; otherwise runs the CLI wizard in the integrated terminal.
21+
*
22+
* @author Ali Azam Rana <ali.azamrana@espressif.com>
23+
*/
24+
public final class EimGuiOrCliLauncher
25+
{
26+
private EimGuiOrCliLauncher()
27+
{
28+
}
29+
30+
/**
31+
* @param afterEimClosed invoked after EIM exits (GUI or CLI terminal), on a thread appropriate for the launch mode;
32+
* for the CLI path the runnable is executed on the SWT UI thread after the terminal process ends
33+
*/
34+
public static void launch(ToolInitializer toolInitializer, EimLoader eimLoader, String eimPath,
35+
MessageConsoleStream standardConsoleStream, Display display, Runnable afterEimClosed) throws IOException
36+
{
37+
if (toolInitializer.isEimGuiCapable(eimPath))
38+
{
39+
LaunchResult launchResult = eimLoader.launchEimWithResult(eimPath);
40+
eimLoader.waitForEimClosure(launchResult, afterEimClosed);
41+
return;
42+
}
43+
44+
EimJsonWatchService.getInstance().pauseListeners();
45+
display.syncExec(() -> {
46+
try
47+
{
48+
standardConsoleStream.write(Messages.EimCliTerminalOpeningWizard + "\n"); //$NON-NLS-1$
49+
EimCliTerminalLaunchSupport.launch(eimPath, () -> display.asyncExec(() -> {
50+
try
51+
{
52+
standardConsoleStream.write(Messages.EimCliTerminalWizardCompleted + "\n"); //$NON-NLS-1$
53+
}
54+
catch (IOException e)
55+
{
56+
Logger.log(e);
57+
}
58+
try
59+
{
60+
afterEimClosed.run();
61+
}
62+
finally
63+
{
64+
EimJsonWatchService.getInstance().unpauseListeners();
65+
}
66+
}));
67+
}
68+
catch (IOException e)
69+
{
70+
Logger.log(e);
71+
EimJsonWatchService.getInstance().unpauseListeners();
72+
}
73+
catch (RuntimeException e)
74+
{
75+
Logger.log(e);
76+
EimJsonWatchService.getInstance().unpauseListeners();
77+
}
78+
});
79+
}
80+
}

bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/EspressifToolStartup.java

Lines changed: 22 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,11 @@
4545
import com.espressif.idf.ui.IDFConsole;
4646
import com.espressif.idf.ui.UIPlugin;
4747
import com.espressif.idf.ui.handlers.EclipseHandler;
48+
import com.espressif.idf.ui.tools.EimGuiOrCliLauncher;
4849
import com.espressif.idf.ui.tools.manager.ESPIDFManagerEditor;
4950
import com.espressif.idf.ui.tools.manager.EimEditorInput;
5051
import com.espressif.idf.ui.tools.watcher.EimJsonUiChangeHandler;
5152

52-
import com.espressif.idf.core.tools.launch.LaunchResult;
53-
5453
/**
5554
* Startup class to handle the tools
5655
*
@@ -367,7 +366,6 @@ public void onCompleted(String filePath)
367366
}
368367
});
369368

370-
LaunchResult launchResult = null;
371369
String appToLaunch = filePath;
372370
try
373371
{
@@ -377,33 +375,31 @@ public void onCompleted(String filePath)
377375
}
378376

379377
idfEnvironmentVariables.addEnvVariable(IDFEnvironmentVariables.EIM_PATH, appToLaunch);
380-
launchResult = eimLoader.launchEimWithResult(appToLaunch);
378+
EimGuiOrCliLauncher.launch(toolInitializer, eimLoader, appToLaunch, standardConsoleStream,
379+
Display.getDefault(), () -> {
380+
if (toolInitializer.isOldEspIdfConfigPresent() && !toolInitializer.isOldConfigExported())
381+
{
382+
Logger.log("Old configuration found and not converted");
383+
handleOldConfigExport();
384+
}
385+
try
386+
{
387+
eimJson = toolInitializer.loadEimJson();
388+
}
389+
catch (EimVersionMismatchException e)
390+
{
391+
Logger.log(e);
392+
MessageDialog.openError(Display.getDefault().getActiveShell(), e.msgTitle(),
393+
e.getMessage());
394+
return;
395+
}
396+
openEspIdfManager(eimJson);
397+
});
381398
}
382-
catch (
383-
IOException
384-
| InterruptedException e)
399+
catch (IOException | InterruptedException e)
385400
{
386401
Logger.log(e);
387402
}
388-
389-
eimLoader.waitForEimClosure(launchResult, () -> {
390-
if (toolInitializer.isOldEspIdfConfigPresent() && !toolInitializer.isOldConfigExported())
391-
{
392-
Logger.log("Old configuration found and not converted");
393-
handleOldConfigExport();
394-
}
395-
try
396-
{
397-
eimJson = toolInitializer.loadEimJson();
398-
}
399-
catch (EimVersionMismatchException e)
400-
{
401-
Logger.log(e);
402-
MessageDialog.openError(Display.getDefault().getActiveShell(), e.msgTitle(), e.getMessage());
403-
return;
404-
}
405-
openEspIdfManager(eimJson);
406-
});
407403
}
408404

409405
@Override

bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/Messages.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ public class Messages extends NLS
6666

6767
public static String MsgYes;
6868
public static String MsgNo;
69+
70+
public static String EimCliTerminalWizardTitle;
71+
public static String EimCliTerminalOpeningWizard;
72+
public static String EimCliTerminalWizardCompleted;
6973

7074
static
7175
{
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/*******************************************************************************
2+
* Copyright 2026 Espressif Systems (Shanghai) PTE LTD. All rights reserved.
3+
* Use is subject to license terms.
4+
*******************************************************************************/
5+
package com.espressif.idf.ui.tools.eim.terminal;
6+
7+
import java.io.IOException;
8+
import java.io.OutputStream;
9+
import java.nio.charset.StandardCharsets;
10+
11+
import org.eclipse.core.runtime.Platform;
12+
import org.eclipse.terminal.connector.ISettingsStore;
13+
import org.eclipse.terminal.connector.ITerminalControl;
14+
import org.eclipse.terminal.connector.process.ProcessConnector;
15+
16+
import com.espressif.idf.core.logging.Logger;
17+
18+
/**
19+
* Opens a login shell, sends the EIM CLI executable as the first command, and notifies
20+
* {@link EimCliTerminalLaunchSupport} when the process exits.
21+
*
22+
* @author Ali Azam Rana <ali.azamrana@espressif.com>
23+
*/
24+
public final class EimCliTerminalConnector extends ProcessConnector
25+
{
26+
/**
27+
* Key used to round-trip the EIM executable path through the settings store.
28+
* Must match the key used in {@link EimCliTerminalLauncherDelegate#createTerminalConnector}.
29+
*/
30+
static final String SETTINGS_KEY_EIM_PATH = "eim.cli.executable"; //$NON-NLS-1$
31+
32+
private String eimExecutablePath;
33+
34+
@Override
35+
public void load(ISettingsStore store)
36+
{
37+
super.load(store);
38+
eimExecutablePath = store.get(SETTINGS_KEY_EIM_PATH, null);
39+
}
40+
41+
@Override
42+
public void connect(ITerminalControl control)
43+
{
44+
super.connect(control);
45+
var process = getProcess();
46+
if (process == null)
47+
{
48+
Logger.log("EIM CLI terminal: no process after connect"); //$NON-NLS-1$
49+
EimCliTerminalLaunchSupport.invokeCompletionIfArmed();
50+
return;
51+
}
52+
53+
if (eimExecutablePath != null && !eimExecutablePath.isBlank())
54+
{
55+
sendEimCommand(process.getOutputStream());
56+
}
57+
58+
Thread waiter = new Thread(() -> {
59+
try
60+
{
61+
int code = process.waitFor();
62+
Logger.log("EIM CLI terminal process exited with code " + code); //$NON-NLS-1$
63+
}
64+
catch (InterruptedException e)
65+
{
66+
Thread.currentThread().interrupt();
67+
}
68+
finally
69+
{
70+
EimCliTerminalLaunchSupport.invokeCompletionIfArmed();
71+
}
72+
}, "EimCliTerminalWait"); //$NON-NLS-1$
73+
waiter.setDaemon(true);
74+
waiter.start();
75+
}
76+
77+
private void sendEimCommand(OutputStream out)
78+
{
79+
String command;
80+
if (Platform.OS_WIN32.equals(Platform.getOS()))
81+
{
82+
String escaped = eimExecutablePath.replace("'", "''"); //$NON-NLS-1$ //$NON-NLS-2$
83+
command = "& '" + escaped + "' wizard; exit\r\n"; //$NON-NLS-1$ //$NON-NLS-2$
84+
}
85+
else
86+
{
87+
String quoted = "'" + eimExecutablePath.replace("'", "'\\''") + "'"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
88+
command = quoted + " wizard; exit\r\n"; //$NON-NLS-1$
89+
}
90+
try
91+
{
92+
out.write(command.getBytes(StandardCharsets.UTF_8));
93+
out.flush();
94+
Logger.log("EIM CLI terminal sent command: " + command.trim()); //$NON-NLS-1$
95+
}
96+
catch (IOException e)
97+
{
98+
Logger.log(e);
99+
}
100+
}
101+
}

0 commit comments

Comments
 (0)