diff --git a/CHANGELOG.md b/CHANGELOG.md index ee1de8dcd..ac5502946 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,59 @@ All notable changes to the "Espressif IDF" extension will be documented in this file. +## [1.11.0](https://github.com/espressif/vscode-esp-idf-extension/releases/tag/v1.11.0) + +## Features and enhancements + +- [Add DevKits support](https://github.com/espressif/vscode-esp-idf-extension/pull/1557) +- [Add gitignore on project creation](https://github.com/espressif/vscode-esp-idf-extension/pull/1578) +- [Pre-Release branch docs](https://github.com/espressif/vscode-esp-idf-extension/pull/1599) +- [Modify event activation for file types](https://github.com/espressif/vscode-esp-idf-extension/pull/1568) +- [Add classic menuconfig in Editor Panel](https://github.com/espressif/vscode-esp-idf-extension/pull/1598) +- [Update webviews to VS Code UI Style](https://github.com/espressif/vscode-esp-idf-extension/pull/1554) +- [Allow customize Pytest glob pattern and unit test services](https://github.com/espressif/vscode-esp-idf-extension/pull/1593) +- [CLang install prompt if not installed](https://github.com/espressif/vscode-esp-idf-extension/pull/1615) +- [Allow additional files and directories for Full Clean commands](https://github.com/espressif/vscode-esp-idf-extension/pull/1613) +- [Extend JTAG flash arguments as configuration setting](https://github.com/espressif/vscode-esp-idf-extension/pull/1583) +- [Range support for downloads in Setup Wizard](https://github.com/espressif/vscode-esp-idf-extension/pull/1625) +- [Check OpenOCD is running before debug is launched](https://github.com/espressif/vscode-esp-idf-extension/pull/1638) +- [Add function names in Disassembly view](https://github.com/espressif/vscode-esp-idf-extension/pull/1634) +- [OpenOCD Hints in Hints Viewer](https://github.com/espressif/vscode-esp-idf-extension/pull/1476) +- [Add detect as default serial port option and use esptool.py to find serial port](https://github.com/espressif/vscode-esp-idf-extension/pull/1632) +- [Pre-release campaign notification](https://github.com/espressif/vscode-esp-idf-extension/pull/1643) +- [Prefer gdbinit prefix_map with fallback to prefix_map_gdbinit](https://github.com/espressif/vscode-esp-idf-extension/pull/1660) +- [AI Integration with Copilot Chat using Language Tool API](https://github.com/espressif/vscode-esp-idf-extension/pull/1621) +- [Allow customize PyPi Index URL in setup wizard](https://github.com/espressif/vscode-esp-idf-extension/pull/1692) +- [Add create empty project command](https://github.com/espressif/vscode-esp-idf-extension/pull/1698) +- [Add Unity Runner and Parser, Remove Pytest](https://github.com/espressif/vscode-esp-idf-extension/pull/1681) + + +### Bug Fixes + +- [Update disassemble screenshot](https://github.com/espressif/vscode-esp-idf-extension/pull/1588) +- [JTAG acronym issues](https://github.com/espressif/vscode-esp-idf-extension/pull/1604) +- [Fix IDF_TARGET in multiple project configuration profiles](https://github.com/espressif/vscode-esp-idf-extension/pull/1579) +- [Fix Partial encryption in encrypted flashing](https://github.com/espressif/vscode-esp-idf-extension/pull/1373) +- [Close OpenOCD after JTAG flash end](https://github.com/espressif/vscode-esp-idf-extension/pull/1601) +- [NodeJS 20 in CI](https://github.com/espressif/vscode-esp-idf-extension/pull/1611) +- [Update build message](https://github.com/espressif/vscode-esp-idf-extension/pull/1603) +- [Fix append git and pigweed to PATH instead of prepend](https://github.com/espressif/vscode-esp-idf-extension/pull/1614) +- [Use latest in master in docs](https://github.com/espressif/vscode-esp-idf-extension/pull/1636) +- [Fix fileExists check in Setup panel](https://github.com/espressif/vscode-esp-idf-extension/pull/1609) Thanks @jonsambro ! +- [Use mon program_esp instead of load for Symbol loading in debug](https://github.com/espressif/vscode-esp-idf-extension/pull/1556) Thanks @wormyrocks ! +- [Move Status bar items to the left](https://github.com/espressif/vscode-esp-idf-extension/pull/1626) +- [Fix set target preview targets](https://github.com/espressif/vscode-esp-idf-extension/pull/1652) +- [Fix App trace and Heap Trace](https://github.com/espressif/vscode-esp-idf-extension/pull/1656) +- [Setup wizard misleading idf.py not found message fix](https://github.com/espressif/vscode-esp-idf-extension/pull/1642) +- [Clang and OpenOCD in PATH validation](https://github.com/espressif/vscode-esp-idf-extension/pull/1666) +- [Telemetry issues bugfixes](https://github.com/espressif/vscode-esp-idf-extension/pull/1675) +- [Fix openOCDRulesPath in addOpenOCDRules](https://github.com/espressif/vscode-esp-idf-extension/pull/1685) +- [Add contrainsts in pytest install step](https://github.com/espressif/vscode-esp-idf-extension/pull/1686) +- [Add double quoutes around gdbinit file path](https://github.com/espressif/vscode-esp-idf-extension/pull/1684) + + + + ## [1.10.1](https://github.com/espressif/vscode-esp-idf-extension/releases/tag/v1.10.1) ## Features and enhancements diff --git a/docs/TROUBLESHOOTING.md b/docs/TROUBLESHOOTING.md new file mode 100644 index 000000000..2513d3e5b --- /dev/null +++ b/docs/TROUBLESHOOTING.md @@ -0,0 +1,7 @@ +# Documentation has moved to: + +# [English](https://docs.espressif.com/projects/vscode-esp-idf-extension/en/latest/troubleshooting.html) + +# 文档已移至 + +# [中文](https://docs.espressif.com/projects/vscode-esp-idf-extension/zh_CN/latest/troubleshooting.html) diff --git a/docs_espressif/en/debugproject.rst b/docs_espressif/en/debugproject.rst index 6fdfc57ae..39daf3b8e 100644 --- a/docs_espressif/en/debugproject.rst +++ b/docs_espressif/en/debugproject.rst @@ -144,6 +144,7 @@ You can modify the configuration to suit your needs. Let's describe the configur Some additional arguments you might use are: +- ``buildFlashMonitor``: (Default: false). Build, flash and launch IDF Monitor before starting the debug session. Use ``idf.monitorDelay`` to set a delay, in milliseconds, after starting the monitor (Default is ``1000``). - ``debugPort``: (Default: 43476) The port to launch the Eclipse CDT GDB Debug Adapter server. If not specified, it will use the default value of 43476. - ``runOpenOCD``: (Default: true). Run extension OpenOCD Server. - ``verifyAppBinBeforeDebug``: (Default: false) Verify that current ESP-IDF project binary is the same as binary in chip. diff --git a/docs_espressif/zh_CN/debugproject.rst b/docs_espressif/zh_CN/debugproject.rst index 7056da4f0..f07e811ac 100644 --- a/docs_espressif/zh_CN/debugproject.rst +++ b/docs_espressif/zh_CN/debugproject.rst @@ -89,6 +89,110 @@ 其中 ``0x20000`` 是分区表中使用的应用程序镜像偏移量。 +调试配置 +-------- + +要配置调试会话,请打开项目的 ``.vscode/launch.json`` 文件。此文件包含调试会话的配置。默认配置如下: + +.. code-block:: JSON + + { + "configurations": [ + { + "type": "gdbtarget", + "request": "attach", + "name": "Eclipse CDT GDB Adapter" + } + ] + } + +你可以根据需要修改配置。以下是配置选项的说明: + +- ``type``: 调试配置的类型。应设置为 ``gdbtarget``。 +- ``program``: 项目构建目录中的 ELF 文件,用于执行调试会话。可以使用命令 ``${command:espIdf.getProjectName}`` 查询扩展以查找当前构建目录的项目名称。 +- ``initCommands``: 用于初始化 GDB 和目标设备的 GDB 命令。默认值为 ``["set remote hardware-watchpoint-limit IDF_TARGET_CPU_WATCHPOINT_NUM", "mon reset halt", "maintenance flush register-cache"]``。 +- ``initialBreakpoint``: 当未定义 ``initCommands`` 时,此命令将在默认 ``initCommands`` 中添加指定函数名的硬件断点。例如 app_main(默认值)将在默认 initCommands 中添加 ``thb app_main``。如果设置为 ""(空字符串),则不会设置初始断点;如果未定义,则使用默认值 thb app_main。 +- ``gdb``: 要使用的 GDB 可执行文件。默认情况下,"${command:espIdf.getToolchainGdb}" 将查询扩展以查找当前 ESP-IDF 项目的 IDF_TARGET(esp32、esp32c6 等)对应的 ESP-IDF 工具链 GDB。 + +.. note:: + **IDF_TARGET_CPU_WATCHPOINT_NUM** 由扩展根据当前 ESP-IDF 项目的 ``IDF_TARGET`` (esp32、esp32c6 等)解析。 + +你可能使用的其他参数包括: + +- ``buildFlashMonitor``: (默认值:false)。在启动调试会话之前构建、烧录并启动 IDF Monitor。使用 ``idf.monitorDelay`` 设置启动监视器后的延迟时间(以毫秒为单位,默认值为 ``1000``)。 +- ``debugPort``: (默认值:43476)启动 Eclipse CDT GDB 调试适配器服务器的端口。如果未指定,将使用默认值 43476。 +- ``runOpenOCD``: (默认值:true)。运行扩展 OpenOCD 服务器。 +- ``verifyAppBinBeforeDebug``: (默认值:false)验证当前 ESP-IDF 项目二进制文件是否与芯片中的二进制文件相同。 +- ``logFile``: 用于记录与 gdb 交互的文件的绝对路径。示例:${workspaceFolder}/gdb.log。 +- ``verbose``: 生成详细的日志输出。 +- ``environment``: 应用于 ESP-IDF 调试适配器的环境变量。它将替换全局环境变量和扩展使用的环境变量。 + +.. code-block:: JSON + + { + "environment": { + "VAR": "Value" + } + } + +- ``imageAndSymbols`` : + +.. code-block:: JSON + + { + "imageAndSymbols": { + "symbolFileName": "如果指定,则在给定(可选)偏移量处加载的符号文件", + "symbolOffset": "如果指定了 symbolFileName,则使用的偏移量", + "imageFileName": "如果指定,则在给定(可选)偏移量处加载的镜像文件", + "imageOffset": "如果指定了 imageFileName,则使用的偏移量" + } + } + +- ``target``: 要附加的目标配置。指定如何连接到要调试的设备。通常 OpenOCD 将芯片作为端口 3333 上的远程目标公开。 + +.. code-block:: JSON + + { + "target": { + "type": "要执行的目标调试类型。传递给 -target-select(默认为 remote)", + "host": "要连接的目标主机(默认为 'localhost',如果设置了 parameters 则忽略)", + "port": "要连接的目标端口(默认为 serverPortRegExp 捕获的值,如果设置了 parameters 则忽略)", + "parameters": "目标类型的目标参数。通常是类似 localhost:12345 的内容。(默认为 `${host}:${port}`)", + "connectCommands": "替换所有先前的参数,指定用于建立连接的命令数组" + } + } + +下面显示了一个修改后的 launch.json 文件示例: + +.. code-block:: JSON + + { + "configurations": [ + { + "type": "gdbtarget", + "request": "attach", + "name": "Eclipse CDT GDB Adapter", + "program": "${workspaceFolder}/build/${command:espIdf.getProjectName}.elf", + "initCommands": [ + "set remote hardware-watchpoint-limit IDF_TARGET_CPU_WATCHPOINT_NUM", + "mon reset halt", + "maintenance flush register-cache" + ], + "gdb": "${command:espIdf.getToolchainGdb}", + "target": { + "connectCommands": [ + "set remotetimeout 20", + "-target-select extended-remote localhost:3333" + ] + } + } + ] + } + +虽然前面的示例明确使用了默认值,但可以根据需要进行自定义。 + +ESP-IDF VS Code 扩展的 package.json gdbtarget 调试器贡献中记录了其他较少使用的参数。 + 浏览代码、调用栈和线程 ---------------------- diff --git a/package.json b/package.json index 48cc9abe3..3b8376159 100644 --- a/package.json +++ b/package.json @@ -1943,6 +1943,11 @@ "description": "Port for Debug Adapter server. Default: 43476", "default": 43476 }, + "buildFlashMonitor": { + "type": "boolean", + "description": "Build, Flash and Monitor the device before debugging", + "default": false + }, "runOpenOCD": { "type": "boolean", "description": "Run OpenOCD Server", @@ -2217,6 +2222,11 @@ "description": "Port for Debug Adapter server. Default: 43476", "default": 43476 }, + "buildFlashMonitor": { + "type": "boolean", + "description": "Build, Flash and Monitor the device before debugging", + "default": false + }, "runOpenOCD": { "type": "boolean", "description": "Run OpenOCD Server", diff --git a/src/build/buildCmd.ts b/src/build/buildCmd.ts index 08320a1c1..da50900a2 100644 --- a/src/build/buildCmd.ts +++ b/src/build/buildCmd.ts @@ -185,8 +185,8 @@ export async function buildCommand( false ); } + continueFlag = false; } - continueFlag = false; return continueFlag; } diff --git a/src/buildFlashMonitor/index.ts b/src/buildFlashMonitor/index.ts new file mode 100644 index 000000000..121f0c6d5 --- /dev/null +++ b/src/buildFlashMonitor/index.ts @@ -0,0 +1,127 @@ +/* + * Project: ESP-IDF VSCode Extension + * File Created: Wednesday, 26th November 2025 10:54:44 am + * Copyright 2025 Espressif Systems (Shanghai) CO LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + CancellationToken, + commands, + env, + l10n, + Progress, + ProgressLocation, + UIKind, + Uri, + window, +} from "vscode"; +import { openFolderCheck } from "../common/PreCheck"; +import { NotificationMode, readParameter } from "../idfConfiguration"; +import { PreCheck, shouldDisableMonitorReset } from "../utils"; +import { IDFWebCommandKeys } from "../cmdTreeView/cmdStore"; +import { isFlashEncryptionEnabled } from "../flash/verifyFlashEncryption"; +import { ESP } from "../config"; +import { IDFMonitor } from "../espIdf/monitor"; +import { buildCommand } from "../build/buildCmd"; +import { startFlashing } from "../flash/startFlashing"; +import { createNewIdfMonitor } from "../espIdf/monitor/command"; + +export async function buildFlashAndMonitor( + workspaceFolderUri: Uri, + noResetMonitor?: boolean +) { + await PreCheck.perform([openFolderCheck], async () => { + const notificationMode = readParameter( + "idf.notificationMode", + workspaceFolderUri + ) as string; + const currentProgressLocation = + notificationMode === NotificationMode.All || + notificationMode === NotificationMode.Notifications + ? ProgressLocation.Notification + : ProgressLocation.Window; + + await window.withProgress( + { + cancellable: true, + location: currentProgressLocation, + title: l10n.t("ESP-IDF: Building project"), + }, + async ( + progress: Progress<{ message: string; increment: number }>, + cancelToken: CancellationToken + ) => { + progress.report({ message: "Building project...", increment: 20 }); + const flashType = readParameter("idf.flashType", workspaceFolderUri); + let canContinue = await buildCommand( + workspaceFolderUri, + cancelToken, + flashType + ); + if (!canContinue) { + return; + } + // Re route to ESP-IDF Web extension if using Codespaces or Browser + if (env.uiKind === UIKind.Web) { + commands.executeCommand(IDFWebCommandKeys.FlashAndMonitor); + return; + } + progress.report({ + message: "Flashing project into device...", + increment: 60, + }); + + let encryptPartitions = await isFlashEncryptionEnabled( + workspaceFolderUri + ); + + let partitionToUse = readParameter( + "idf.flashPartitionToUse", + workspaceFolderUri + ) as ESP.BuildType; + + if ( + partitionToUse && + !["app", "bootloader", "partition-table"].includes(partitionToUse) + ) { + partitionToUse = undefined; + } + + canContinue = await startFlashing( + workspaceFolderUri, + cancelToken, + flashType, + encryptPartitions, + partitionToUse + ); + if (!canContinue) { + return; + } + progress.report({ + message: "Launching monitor...", + increment: 10, + }); + if (IDFMonitor.terminal) { + IDFMonitor.terminal.sendText(ESP.CTRL_RBRACKET); + } + const noReset = + typeof noResetMonitor !== "undefined" + ? noResetMonitor + : await shouldDisableMonitorReset(workspaceFolderUri); + await createNewIdfMonitor(workspaceFolderUri, noReset); + } + ); + }); +} diff --git a/src/cdtDebugAdapter/debugConfProvider.ts b/src/cdtDebugAdapter/debugConfProvider.ts index e232ca5d6..dcf0949ef 100644 --- a/src/cdtDebugAdapter/debugConfProvider.ts +++ b/src/cdtDebugAdapter/debugConfProvider.ts @@ -35,6 +35,7 @@ import { Logger } from "../logger/logger"; import { getConfigValueFromSDKConfig, getToolchainPath } from "../utils"; import { createNewIdfMonitor } from "../espIdf/monitor/command"; import { ESP } from "../config"; +import { buildFlashAndMonitor } from "../buildFlashMonitor"; export class CDTDebugConfigurationProvider implements DebugConfigurationProvider { @@ -58,6 +59,19 @@ export class CDTDebugConfigurationProvider } } } + const useMonitorWithDebug = readParameter( + "idf.launchMonitorOnDebugSession", + folder + ); + if (config.buildFlashMonitor) { + await buildFlashAndMonitor(folder.uri, true); + } else if ( + config.sessionID !== "core-dump.debug.session.ws" && + config.sessionID !== "gdbstub.debug.session.ws" && + useMonitorWithDebug + ) { + await createNewIdfMonitor(folder.uri, true); + } if (!config.program) { const buildDirPath = readParameter("idf.buildPath", folder) as string; const projectName = await getProjectName(buildDirPath); @@ -170,17 +184,6 @@ export class CDTDebugConfigurationProvider ); } } - const useMonitorWithDebug = readParameter( - "idf.launchMonitorOnDebugSession", - folder - ); - if ( - config.sessionID !== "core-dump.debug.session.ws" && - config.sessionID !== "gdbstub.debug.session.ws" && - useMonitorWithDebug - ) { - await createNewIdfMonitor(folder.uri, true); - } const openOCDManager = OpenOCDManager.init(); if ( !openOCDManager.isRunning() && diff --git a/src/common/PreCheck.ts b/src/common/PreCheck.ts new file mode 100644 index 000000000..f389ea2ce --- /dev/null +++ b/src/common/PreCheck.ts @@ -0,0 +1,44 @@ +/* + * Project: ESP-IDF VSCode Extension + * File Created: Wednesday, 26th November 2025 10:51:20 am + * Copyright 2025 Espressif Systems (Shanghai) CO LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { l10n } from "vscode"; +import { PreCheck, PreCheckInput } from "../utils"; + +const openFolderFirstMsg = l10n.t("Open a folder first."); +const cmdNotForWebIdeMsg = l10n.t( + "Selected command is not available in {envName}", + { envName: "Codespaces" } +); +const cmdNotDockerContainerMsg = l10n.t( + "Selected command is not available in {envName}", + { envName: "Docker container" } +); +export const openFolderCheck = [ + PreCheck.isWorkspaceFolderOpen, + openFolderFirstMsg, +] as PreCheckInput; + +export const webIdeCheck = [ + PreCheck.notUsingWebIde, + cmdNotForWebIdeMsg, +] as PreCheckInput; + +export const isNotDockerContainerCheck = [ + PreCheck.isNotDockerContainer, + cmdNotDockerContainerMsg, +] as PreCheckInput; \ No newline at end of file diff --git a/src/espIdf/debugAdapter/checkPyReqs.ts b/src/espIdf/debugAdapter/checkPyReqs.ts index 99ca49c36..10a7f2e7a 100644 --- a/src/espIdf/debugAdapter/checkPyReqs.ts +++ b/src/espIdf/debugAdapter/checkPyReqs.ts @@ -25,6 +25,7 @@ import { getVirtualEnvPythonPath } from "../../pythonManager"; export async function checkDebugAdapterRequirements(workspaceFolder: Uri) { const idfPath = readParameter("idf.espIdfPath", workspaceFolder); + const espIdfToolsPath = readParameter("idf.espIdfToolsPath", workspaceFolder); const pythonBinPath = await getVirtualEnvPythonPath(workspaceFolder); let requirementsPath = join( extensionContext.extensionPath, @@ -40,6 +41,7 @@ export async function checkDebugAdapterRequirements(workspaceFolder: Uri) { checkResult = await startPythonReqsProcess( pythonBinPath, idfPath, + espIdfToolsPath, requirementsPath ); } catch (error) { diff --git a/src/espIdf/monitor/command.ts b/src/espIdf/monitor/command.ts index b975ed6c0..3e9e22276 100644 --- a/src/espIdf/monitor/command.ts +++ b/src/espIdf/monitor/command.ts @@ -138,14 +138,10 @@ export async function createNewIdfMonitor( } IDFMonitor.start(); if (noReset) { - const idfPath = readParameter("idf.espIdfPath", workspaceFolder) as string; - const idfVersion = await utils.getEspIdfFromCMake(idfPath); - if (idfVersion <= "5.0") { - const monitorDelay = readParameter( - "idf.monitorDelay", - workspaceFolder - ) as number; - await utils.sleep(monitorDelay); - } + const monitorDelay = readParameter( + "idf.monitorDelay", + workspaceFolder + ) as number; + await utils.sleep(monitorDelay); } } diff --git a/src/espIdf/serial/serialPort.ts b/src/espIdf/serial/serialPort.ts index ac0ae756e..cc794c6eb 100644 --- a/src/espIdf/serial/serialPort.ts +++ b/src/espIdf/serial/serialPort.ts @@ -153,6 +153,9 @@ export class SerialPort { const portMatch = line.match(/Serial port\s+(\S+)/); if (portMatch) { currentPort = portMatch[1]; + if (currentPort.endsWith(":")) { + currentPort = currentPort.slice(0, -1); + } testedPorts++; progress.report({ message: vscode.l10n.t( @@ -167,7 +170,9 @@ export class SerialPort { } // Look for "Chip is" lines to identify successful connections - const chipMatch = line.match(/Chip is\s+([^(]+)/); + const chipMatch = + line.match(/Connected to\s+([^\s]+)\s+on/) || + line.match(/Chip is\s+([^\s(]+)/); if (chipMatch && currentPort) { const chipType = chipMatch[1] .trim() diff --git a/src/extension.ts b/src/extension.ts index ab439d9db..8d177e11d 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -142,11 +142,7 @@ import { PeripheralBaseNode } from "./espIdf/debugAdapter/nodes/base"; import { ExtensionConfigStore } from "./common/store"; import { projectConfigurationPanel } from "./project-conf/projectConfPanel"; import { ProjectConfigStore } from "./project-conf"; -import { - clearPreviousIdfSetups, - getPreviousIdfSetups, - loadIdfSetupsFromEspIdfJson, -} from "./setup/existingIdfSetups"; +import { clearPreviousIdfSetups } from "./setup/existingIdfSetups"; import { getEspRainmaker } from "./rainmaker/download/espRainmakerDownload"; import { UnitTest } from "./espIdf/unitTest/adapter"; import { @@ -177,7 +173,6 @@ import { createCommandDictionary, IDFWebCommandKeys, } from "./cmdTreeView/cmdStore"; -import { IdfSetup } from "./views/setup/types"; import { asyncRemoveEspIdfSettings } from "./uninstall"; import { clearSelectedProjectConfiguration, @@ -194,6 +189,13 @@ import { OpenOCDErrorMonitor } from "./espIdf/hints/openocdhint"; import { updateHintsStatusBarItem } from "./statusBar"; import { activateLanguageTool, deactivateLanguageTool } from "./langTools"; import { readSerialPort } from "./idfConfiguration"; +import { + openFolderCheck, + isNotDockerContainerCheck, + webIdeCheck, +} from "./common/PreCheck"; +import { buildFlashAndMonitor } from "./buildFlashMonitor"; +import { selectFlashMethod, startFlashing } from "./flash/startFlashing"; // Global variables shared by commands let workspaceRoot: vscode.Uri; @@ -243,28 +245,6 @@ let wsServer: WSServer; // Precheck methods and their messages -const openFolderFirstMsg = vscode.l10n.t("Open a folder first."); -const cmdNotForWebIdeMsg = vscode.l10n.t( - "Selected command is not available in {envName}", - { envName: "Codespaces" } -); -const cmdNotDockerContainerMsg = vscode.l10n.t( - "Selected command is not available in {envName}", - { envName: "Docker container" } -); -const openFolderCheck = [ - PreCheck.isWorkspaceFolderOpen, - openFolderFirstMsg, -] as utils.PreCheckInput; -const webIdeCheck = [ - PreCheck.notUsingWebIde, - cmdNotForWebIdeMsg, -] as utils.PreCheckInput; -const isNotDockerContainerCheck = [ - PreCheck.isNotDockerContainer, - cmdNotDockerContainerMsg, -] as utils.PreCheckInput; - const minIdfVersionCheck = async function ( minVersion: string, workspace: vscode.Uri @@ -597,6 +577,25 @@ export async function activate(context: vscode.ExtensionContext) { debugAdapterManager.stop(); }); + const kconfigMenusWatcher = vscode.workspace.createFileSystemWatcher( + "**/config/kconfig_menus.json", + true, + false, + false + ); + context.subscriptions.push( + kconfigMenusWatcher.onDidChange(async (e) => { + if (ConfserverProcess.exists()) { + ConfserverProcess.dispose(); + } + }), + kconfigMenusWatcher.onDidDelete(async (e) => { + if (ConfserverProcess.exists()) { + ConfserverProcess.dispose(); + } + }) + ); + const sdkconfigWatcher = vscode.workspace.createFileSystemWatcher( "**/sdkconfig", false, @@ -2074,7 +2073,9 @@ export async function activate(context: vscode.ExtensionContext) { registerIDFCommand("espIdf.flashAndEncryptDevice", () => flash(true)); registerIDFCommand("espIdf.buildDevice", build); registerIDFCommand("espIdf.monitorDevice", createMonitor); - registerIDFCommand("espIdf.buildFlashMonitor", buildFlashAndMonitor); + registerIDFCommand("espIdf.buildFlashMonitor", () => + buildFlashAndMonitor(workspaceRoot) + ); registerIDFCommand("espIdf.monitorQemu", createQemuMonitor); registerIDFCommand("espIdf.buildApp", () => @@ -3807,7 +3808,7 @@ export async function activate(context: vscode.ExtensionContext) { registerIDFCommand("espIdf.selectFlashMethodAndFlash", () => { PreCheck.perform([openFolderCheck, webIdeCheck], async () => { - await selectFlashMethod(); + await selectFlashMethod(workspaceRoot); }); }); @@ -4247,6 +4248,7 @@ const flash = ( } if ( await startFlashing( + workspaceRoot, cancelToken, flashType, encryptPartitions, @@ -4300,206 +4302,6 @@ function createQemuMonitor() { }); } -const buildFlashAndMonitor = async (runMonitor: boolean = true) => { - PreCheck.perform([openFolderCheck], async () => { - const notificationMode = idfConf.readParameter( - "idf.notificationMode", - workspaceRoot - ) as string; - const ProgressLocation = - notificationMode === idfConf.NotificationMode.All || - notificationMode === idfConf.NotificationMode.Notifications - ? vscode.ProgressLocation.Notification - : vscode.ProgressLocation.Window; - - await vscode.window.withProgress( - { - cancellable: true, - location: ProgressLocation, - title: vscode.l10n.t("ESP-IDF: Building project"), - }, - async ( - progress: vscode.Progress<{ message: string; increment: number }>, - cancelToken: vscode.CancellationToken - ) => { - progress.report({ message: "Building project...", increment: 20 }); - const flashType = idfConf.readParameter("idf.flashType", workspaceRoot); - let canContinue = await buildCommand( - workspaceRoot, - cancelToken, - flashType - ); - if (!canContinue) { - return; - } - // Re route to ESP-IDF Web extension if using Codespaces or Browser - if (vscode.env.uiKind === vscode.UIKind.Web) { - vscode.commands.executeCommand(IDFWebCommandKeys.FlashAndMonitor); - return; - } - progress.report({ - message: "Flashing project into device...", - increment: 60, - }); - - let encryptPartitions = await isFlashEncryptionEnabled(workspaceRoot); - - let partitionToUse = idfConf.readParameter( - "idf.flashPartitionToUse", - workspaceRoot - ) as ESP.BuildType; - - if ( - partitionToUse && - !["app", "bootloader", "partition-table"].includes(partitionToUse) - ) { - partitionToUse = undefined; - } - - canContinue = await startFlashing( - cancelToken, - flashType, - encryptPartitions, - partitionToUse - ); - if (!canContinue) { - return; - } - if (runMonitor) { - progress.report({ - message: "Launching monitor...", - increment: 10, - }); - if (IDFMonitor.terminal) { - IDFMonitor.terminal.sendText(ESP.CTRL_RBRACKET); - } - await createMonitor(); - } - } - ); - }); -}; - -async function selectFlashMethod() { - let curflashType = idfConf.readParameter( - "idf.flashType", - workspaceRoot - ) as ESP.FlashType; - let newFlashType = (await vscode.window.showQuickPick( - Object.keys(ESP.FlashType), - { - ignoreFocusOut: true, - placeHolder: vscode.l10n.t( - "Select flash method, you can modify the choice later from 'settings.json' (idf.flashType)" - ), - } - )) as ESP.FlashType; - if (!newFlashType) { - return curflashType; - } - await idfConf.writeParameter( - "idf.flashType", - newFlashType, - vscode.ConfigurationTarget.WorkspaceFolder, - workspaceRoot - ); - vscode.window.showInformationMessage( - `Flash method changed to ${newFlashType}.` - ); - return newFlashType; -} - -async function startFlashing( - cancelToken: vscode.CancellationToken, - flashType: ESP.FlashType, - encryptPartitions: boolean, - partitionToUse?: ESP.BuildType -): Promise { - if (!flashType) { - flashType = await selectFlashMethod(); - } - - if (IDFMonitor.terminal) { - IDFMonitor.terminal.sendText(ESP.CTRL_RBRACKET); - const monitorDelay = idfConf.readParameter( - "idf.monitorDelay", - workspaceRoot - ) as number; - await utils.sleep(monitorDelay); - } - - if (encryptPartitions) { - const encryptionValidationResult = await checkFlashEncryption( - flashType, - workspaceRoot - ); - if (!encryptionValidationResult.success) { - if ( - encryptionValidationResult.resultType === - FlashCheckResultType.ErrorEfuseNotSet - ) { - encryptPartitions = false; - } else { - return; - } - } - } - - const port = await idfConf.readSerialPort(workspaceRoot, false); - if (!port) { - Logger.warnNotify( - vscode.l10n.t( - "No serial port found for current IDF_TARGET: {0}", - await getIdfTargetFromSdkconfig(workspaceRoot) - ) - ); - return false; - } - const flashBaudRate = idfConf.readParameter( - "idf.flashBaudRate", - workspaceRoot - ); - const canFlash = await verifyCanFlash( - flashBaudRate, - port, - flashType, - workspaceRoot - ); - if (!canFlash) { - return false; - } - - if (flashType === ESP.FlashType.JTAG) { - const currOpenOcdVersion = await openOCDManager.version(); - const openOCDVersionIsValid = PreCheck.openOCDVersionValidator( - "v0.10.0-esp32-20201125", - currOpenOcdVersion - ); - if (!openOCDVersionIsValid) { - Logger.infoNotify( - `Minimum OpenOCD version v0.10.0-esp32-20201125 is required while you have ${currOpenOcdVersion} version installed` - ); - return; - } - return await jtagFlashCommand(workspaceRoot); - } else { - const idfPathDir = idfConf.readParameter( - "idf.espIdfPath", - workspaceRoot - ) as string; - return await flashCommand( - cancelToken, - flashBaudRate, - idfPathDir, - port, - workspaceRoot, - flashType, - encryptPartitions, - partitionToUse - ); - } -} - async function createEspIdfTerminal( extensionPath: string, terminalName: string, @@ -4775,7 +4577,7 @@ class IdfDebugConfigurationProvider "Build" ); if (startBuild === "Build") { - await buildFlashAndMonitor(false); + await buildFlashAndMonitor(workspaceRoot, false); return; } } diff --git a/src/flash/startFlashing.ts b/src/flash/startFlashing.ts new file mode 100644 index 000000000..f713ac30c --- /dev/null +++ b/src/flash/startFlashing.ts @@ -0,0 +1,157 @@ +/* + * Project: ESP-IDF VSCode Extension + * File Created: Wednesday, 26th November 2025 11:34:53 am + * Copyright 2025 Espressif Systems (Shanghai) CO LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + CancellationToken, + ConfigurationTarget, + l10n, + Uri, + window, +} from "vscode"; +import { + readParameter, + readSerialPort, + writeParameter, +} from "../idfConfiguration"; +import { ESP } from "../config"; +import { IDFMonitor } from "../espIdf/monitor"; +import { PreCheck, sleep } from "../utils"; +import { + checkFlashEncryption, + FlashCheckResultType, +} from "./verifyFlashEncryption"; +import { Logger } from "../logger/logger"; +import { getIdfTargetFromSdkconfig } from "../workspaceConfig"; +import { verifyCanFlash } from "./flashCmd"; +import { OpenOCDManager } from "../espIdf/openOcd/openOcdManager"; +import { jtagFlashCommand } from "./jtagCmd"; +import { flashCommand } from "./uartFlash"; + +export async function selectFlashMethod(workspaceFolderUri: Uri) { + let curflashType = readParameter( + "idf.flashType", + workspaceFolderUri + ) as ESP.FlashType; + let newFlashType = (await window.showQuickPick(Object.keys(ESP.FlashType), { + ignoreFocusOut: true, + placeHolder: l10n.t( + "Select flash method, you can modify the choice later from 'settings.json' (idf.flashType)" + ), + })) as ESP.FlashType; + if (!newFlashType) { + return curflashType; + } + await writeParameter( + "idf.flashType", + newFlashType, + ConfigurationTarget.WorkspaceFolder, + workspaceFolderUri + ); + window.showInformationMessage(`Flash method changed to ${newFlashType}.`); + return newFlashType; +} + +export async function startFlashing( + workspaceFolderUri: Uri, + cancelToken: CancellationToken, + flashType: ESP.FlashType, + encryptPartitions: boolean, + partitionToUse?: ESP.BuildType +): Promise { + if (!flashType) { + flashType = await selectFlashMethod(workspaceFolderUri); + } + + if (IDFMonitor.terminal) { + IDFMonitor.terminal.sendText(ESP.CTRL_RBRACKET); + const monitorDelay = readParameter( + "idf.monitorDelay", + workspaceFolderUri + ) as number; + await sleep(monitorDelay); + } + + if (encryptPartitions) { + const encryptionValidationResult = await checkFlashEncryption( + flashType, + workspaceFolderUri + ); + if (!encryptionValidationResult.success) { + if ( + encryptionValidationResult.resultType === + FlashCheckResultType.ErrorEfuseNotSet + ) { + encryptPartitions = false; + } else { + return; + } + } + } + + const port = await readSerialPort(workspaceFolderUri, false); + if (!port) { + Logger.warnNotify( + l10n.t( + "No serial port found for current IDF_TARGET: {0}", + await getIdfTargetFromSdkconfig(workspaceFolderUri) + ) + ); + return false; + } + const flashBaudRate = readParameter("idf.flashBaudRate", workspaceFolderUri); + const canFlash = await verifyCanFlash( + flashBaudRate, + port, + flashType, + workspaceFolderUri + ); + if (!canFlash) { + return false; + } + + if (flashType === ESP.FlashType.JTAG) { + const openOCDManager = OpenOCDManager.init(); + const currOpenOcdVersion = await openOCDManager.version(); + const openOCDVersionIsValid = PreCheck.openOCDVersionValidator( + "v0.10.0-esp32-20201125", + currOpenOcdVersion + ); + if (!openOCDVersionIsValid) { + Logger.infoNotify( + `Minimum OpenOCD version v0.10.0-esp32-20201125 is required while you have ${currOpenOcdVersion} version installed` + ); + return; + } + return await jtagFlashCommand(workspaceFolderUri); + } else { + const idfPathDir = readParameter( + "idf.espIdfPath", + workspaceFolderUri + ) as string; + return await flashCommand( + cancelToken, + flashBaudRate, + idfPathDir, + port, + workspaceFolderUri, + flashType, + encryptPartitions, + partitionToUse + ); + } +} diff --git a/src/newProject/newProjectPanel.ts b/src/newProject/newProjectPanel.ts index 55e5cddb9..dcf76c13f 100644 --- a/src/newProject/newProjectPanel.ts +++ b/src/newProject/newProjectPanel.ts @@ -195,6 +195,7 @@ export class NewProjectPanel { serialPortList: newProjectArgs.serialPortList, openOcdConfigFiles: defConfigFiles, templates: newProjectArgs.templates, + pathSep: path.sep, }); } break; diff --git a/src/setup/setupInit.ts b/src/setup/setupInit.ts index 3887d7d1e..b19458826 100644 --- a/src/setup/setupInit.ts +++ b/src/setup/setupInit.ts @@ -107,8 +107,13 @@ export async function checkPreviousInstall( gitPath = gitPathFromJson; } existingIdfSetups = await loadIdfSetupsFromEspIdfJson(toolsPath); - if (process.env.IDF_TOOLS_PATH && toolsPath !== process.env.IDF_TOOLS_PATH) { - const systemIdfSetups = await loadIdfSetupsFromEspIdfJson(process.env.IDF_TOOLS_PATH); + if ( + process.env.IDF_TOOLS_PATH && + toolsPath !== process.env.IDF_TOOLS_PATH + ) { + const systemIdfSetups = await loadIdfSetupsFromEspIdfJson( + process.env.IDF_TOOLS_PATH + ); existingIdfSetups = [...existingIdfSetups, ...systemIdfSetups]; } } @@ -169,10 +174,7 @@ export async function getSetupInitialValues( pythonVersions && pythonVersions.length > 0; - const canAccessCMake = await utils.isBinInPath( - "cmake", - process.env - ); + const canAccessCMake = await utils.isBinInPath("cmake", process.env); if (canAccessCMake === "") { setupInitArgs.onReqPkgs = setupInitArgs.onReqPkgs @@ -180,10 +182,7 @@ export async function getSetupInitialValues( : ["cmake"]; } - const canAccessNinja = await utils.isBinInPath( - "ninja", - process.env - ); + const canAccessNinja = await utils.isBinInPath("ninja", process.env); if (canAccessNinja === "") { setupInitArgs.onReqPkgs = setupInitArgs.onReqPkgs @@ -242,17 +241,11 @@ export async function isCurrentInstallValid(workspaceFolder: Uri) { ); let extraReqPaths = []; if (process.platform !== "win32") { - const canAccessCMake = await utils.isBinInPath( - "cmake", - process.env - ); + const canAccessCMake = await utils.isBinInPath("cmake", process.env); if (!canAccessCMake) { extraReqPaths.push("cmake"); } - const canAccessNinja = await utils.isBinInPath( - "ninja", - process.env - ); + const canAccessNinja = await utils.isBinInPath("ninja", process.env); if (!canAccessNinja) { extraReqPaths.push("ninja"); } @@ -290,7 +283,7 @@ export async function isCurrentInstallValid(workspaceFolder: Uri) { workspaceFolder ) as string; } - const isPyEnvValid = await checkPyVenv(pythonBinPath, espIdfPath); + const isPyEnvValid = await checkPyVenv(pythonBinPath, espIdfPath, toolsPath); return isPyEnvValid; } diff --git a/src/setup/setupValidation/espIdfSetup.ts b/src/setup/setupValidation/espIdfSetup.ts index ee888c4ce..dd107dea1 100644 --- a/src/setup/setupValidation/espIdfSetup.ts +++ b/src/setup/setupValidation/espIdfSetup.ts @@ -109,7 +109,11 @@ export async function checkIdfSetup( ); } - const pyEnvReqs = await checkPyVenv(virtualEnvPython, setupConf.idfPath); + const pyEnvReqs = await checkPyVenv( + virtualEnvPython, + setupConf.idfPath, + setupConf.toolsPath + ); return pyEnvReqs; } catch (error) { const msg = diff --git a/src/setup/setupValidation/pythonEnv.ts b/src/setup/setupValidation/pythonEnv.ts index 3c94cd13c..83ff6c747 100644 --- a/src/setup/setupValidation/pythonEnv.ts +++ b/src/setup/setupValidation/pythonEnv.ts @@ -20,7 +20,7 @@ import { pathExists } from "fs-extra"; import { join } from "path"; import { startPythonReqsProcess } from "../../utils"; -export async function checkPyVenv(pyVenvPath: string, espIdfPath: string) { +export async function checkPyVenv(pyVenvPath: string, espIdfPath: string, espIdfToolsPath: string): Promise { const pyExists = await pathExists(pyVenvPath); if (!pyExists) { return false; @@ -43,6 +43,7 @@ export async function checkPyVenv(pyVenvPath: string, espIdfPath: string) { const reqsResults = await startPythonReqsProcess( pyVenvPath, espIdfPath, + espIdfToolsPath, requirements ); if (reqsResults.indexOf("are not satisfied") > -1) { diff --git a/src/support/checkEspIdfRequirements.ts b/src/support/checkEspIdfRequirements.ts index 49a8e8ec9..6c53f5d88 100644 --- a/src/support/checkEspIdfRequirements.ts +++ b/src/support/checkEspIdfRequirements.ts @@ -27,10 +27,18 @@ export async function checkEspIdfRequirements( ) { try { let requirementsPath: string; - requirementsPath = join(reportedResult.configurationSettings.espIdfPath, "tools", "requirements", "requirements.core.txt"); + requirementsPath = join( + reportedResult.configurationSettings.espIdfPath, + "tools", + "requirements", + "requirements.core.txt" + ); const coreRequirementsExists = await pathExists(requirementsPath); if (!coreRequirementsExists) { - requirementsPath = join(reportedResult.configurationSettings.espIdfPath, "requirements.txt"); + requirementsPath = join( + reportedResult.configurationSettings.espIdfPath, + "requirements.txt" + ); const requirementsExists = await pathExists(requirementsPath); if (!requirementsExists) { throw new Error("Requirements doesn't exists."); @@ -63,9 +71,23 @@ export async function checkRequirements( Object.assign({}, process.env) ); modifiedEnv.IDF_PATH = reportedResult.configurationSettings.espIdfPath; + const majorMinorMatches = reportedResult.espIdfVersion.result.match(/([0-9]+\.[0-9]+).*/); + const espIdfVersion = + majorMinorMatches && majorMinorMatches.length > 0 + ? majorMinorMatches[1] + : "x.x"; + const constrainsFile = join( + reportedResult.configurationSettings.toolsPath, + `espidf.constraints.v${espIdfVersion}.txt` + ); + let checkPyArgs = [checkPythonDepsScript, "-r", requirementsPath]; + const constrainsFileExists = await pathExists(constrainsFile); + if (constrainsFileExists) { + checkPyArgs = checkPyArgs.concat(["--constraint", constrainsFile]); + } const requirementsResult = await execChildProcess( reportedResult.configurationSettings.pythonBinPath, - [checkPythonDepsScript, "-r", requirementsPath], + checkPyArgs, context.extensionPath, { env: modifiedEnv, cwd: context.extensionPath } ); diff --git a/src/utils.ts b/src/utils.ts index d88f2a5ae..7fbf56da9 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1378,6 +1378,7 @@ export async function isBinInPath( export async function startPythonReqsProcess( pythonBinPath: string, espIdfPath: string, + espIdfToolsPath: string, requirementsPath: string ) { const reqFilePath = path.join( @@ -1389,9 +1390,24 @@ export async function startPythonReqsProcess( Object.assign({}, process.env) ); modifiedEnv.IDF_PATH = espIdfPath; + const fullEspIdfVersion = await getEspIdfFromCMake(espIdfPath); + const majorMinorMatches = fullEspIdfVersion.match(/([0-9]+\.[0-9]+).*/); + const espIdfVersion = + majorMinorMatches && majorMinorMatches.length > 0 + ? majorMinorMatches[1] + : "x.x"; + const constrainsFile = path.join( + espIdfToolsPath, + `espidf.constraints.v${espIdfVersion}.txt` + ); + const constrainsFileExists = await pathExists(constrainsFile); + let checkPyArgs = [reqFilePath, "-r", requirementsPath]; + if (constrainsFileExists) { + checkPyArgs = checkPyArgs.concat(["--constraint", constrainsFile]); + } return execChildProcess( pythonBinPath, - [reqFilePath, "-r", requirementsPath], + checkPyArgs, extensionContext.extensionPath, OutputChannel.init(), { env: modifiedEnv, cwd: extensionContext.extensionPath } diff --git a/src/views/menuconfig/Menuconfig.vue b/src/views/menuconfig/Menuconfig.vue index 1be91034a..b7ba42946 100644 --- a/src/views/menuconfig/Menuconfig.vue +++ b/src/views/menuconfig/Menuconfig.vue @@ -46,7 +46,9 @@ function filterItems(items: Menu[], searchString: string) { const filteredChildren = filterItems(item.children, searchString); if (filteredChildren.length > 0) { const newItem = Object.assign({}, item); - newItem.children = filteredChildren; + if (item.type !== "choice") { + newItem.children = filteredChildren; + } filteredItems.push(newItem); } } @@ -71,7 +73,9 @@ function onScroll() { const configList = document.querySelector(".config-list") as HTMLElement; if (!configList) return; - const sections = Array.from(document.querySelectorAll(".submenu.form-group")) as HTMLElement[]; + const sections = Array.from( + document.querySelectorAll(".submenu.form-group") + ) as HTMLElement[]; if (sections.length === 0) return; const scrollTop = configList.scrollTop; @@ -102,28 +106,28 @@ const handleScroll = (event) => { function handleMenuSelect(value: string) { store.selectedMenu = value; - const secNew = document.querySelector('#' + value) as HTMLElement; + const secNew = document.getElementById(value); if (secNew) { - secNew.scrollIntoView({ behavior: 'auto', block: 'start' }); + secNew.scrollIntoView({ behavior: "auto", block: "start" }); } } function handleMouseDown(e: MouseEvent) { isDragging.value = true; - document.body.style.cursor = 'col-resize'; - document.body.style.userSelect = 'none'; + document.body.style.cursor = "col-resize"; + document.body.style.userSelect = "none"; e.preventDefault(); } function handleMouseMove(e: MouseEvent) { if (!isDragging.value) return; - - const mainElement = document.getElementById('main'); + + const mainElement = document.getElementById("main"); if (!mainElement) return; const mainRect = mainElement.getBoundingClientRect(); const newWidth = e.clientX - mainRect.left; - + if (newWidth >= minTreeWidth && newWidth <= maxTreeWidth) { treeWidth.value = newWidth; } @@ -132,8 +136,8 @@ function handleMouseMove(e: MouseEvent) { function handleMouseUp() { if (!isDragging.value) return; isDragging.value = false; - document.body.style.cursor = ''; - document.body.style.userSelect = ''; + document.body.style.cursor = ""; + document.body.style.userSelect = ""; } onMounted(() => { @@ -142,8 +146,8 @@ onMounted(() => { if (scrollableDiv) { scrollableDiv.addEventListener("scroll", handleScroll); } - window.addEventListener('mousemove', handleMouseMove); - window.addEventListener('mouseup', handleMouseUp); + window.addEventListener("mousemove", handleMouseMove); + window.addEventListener("mouseup", handleMouseUp); }); onUnmounted(() => { @@ -151,8 +155,8 @@ onUnmounted(() => { if (scrollableDiv) { scrollableDiv.removeEventListener("scroll", handleScroll); } - window.removeEventListener('mousemove', handleMouseMove); - window.removeEventListener('mouseup', handleMouseUp); + window.removeEventListener("mousemove", handleMouseMove); + window.removeEventListener("mouseup", handleMouseUp); }); @@ -160,13 +164,20 @@ onUnmounted(() => {
-
+
-
{ \ No newline at end of file diff --git a/src/views/menuconfig/components/StringInput.vue b/src/views/menuconfig/components/StringInput.vue index a9c8f009b..fe0f20665 100644 --- a/src/views/menuconfig/components/StringInput.vue +++ b/src/views/menuconfig/components/StringInput.vue @@ -59,12 +59,10 @@ function onChange(e: Event) { .form-group { padding-left: 30px; overflow: hidden; - margin-top: 9px; - margin-bottom: 9px; } .field { - margin-bottom: 0.5rem; + margin-bottom: 0.05rem; } .vscode-input { diff --git a/src/views/menuconfig/components/checkbox.vue b/src/views/menuconfig/components/checkbox.vue index 4f6585f56..bb2bf3e43 100644 --- a/src/views/menuconfig/components/checkbox.vue +++ b/src/views/menuconfig/components/checkbox.vue @@ -77,12 +77,10 @@ function onChange(e: Event) { .form-group { padding-left: 30px; overflow: hidden; - margin-top: 9px; - margin-bottom: 9px; } .field { - margin-bottom: 0.5rem; + margin-bottom: 0.05rem; } .checkbox-wrapper { diff --git a/src/views/menuconfig/components/configElement.vue b/src/views/menuconfig/components/configElement.vue index 934f614df..7063973d1 100644 --- a/src/views/menuconfig/components/configElement.vue +++ b/src/views/menuconfig/components/configElement.vue @@ -81,9 +81,8 @@ function onChange(e) { .form-group { padding-left: 30px; overflow: hidden; - margin-top: 9px; - margin-bottom: 9px; } + .config-el { width: 90%; } @@ -93,7 +92,6 @@ function onChange(e) { .submenu { padding-left: 0px; overflow: hidden; - padding: 10px 10px 10px 15px; } .menuconfig { padding-left: 0px; @@ -101,15 +99,16 @@ function onChange(e) { .menu-title { font-family: var(--vscode-font-family, "Segoe WPC", "Segoe UI", Tahoma, Geneva, Verdana, sans-serif); font-weight: 750; - font-size: 26px; + font-size: 16px; color: var(--vscode-settings-headerForeground, #888888); } .config-children .menu-title { - font-size: 22px; + font-size: 16px; } .config-children .config-children .menu-title { - font-size: 18px; + font-size: 14px; + font-weight: 600; } diff --git a/src/views/new-project/components/folderOpen.vue b/src/views/new-project/components/folderOpen.vue index fe5ee007c..ba16d944a 100644 --- a/src/views/new-project/components/folderOpen.vue +++ b/src/views/new-project/components/folderOpen.vue @@ -1,8 +1,11 @@