diff --git a/CHANGELOG.md b/CHANGELOG.md index 1293942..16b02f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,24 @@ *** +### [v3.5.0] + +**Fixed**: + - Source ref parser encoding bug for iar_stm8 compiler. + +**Optimized**: + - Replace `arch` command by `uname -m` for `arch-linux`. + - Auto search executable path in system env when default tool path is invalid. + - Use monospaced font for `*.mapView`. + - Disable online tool installer for `linux` platform. + +**Changed**: + - Remove `extensionDependencies` and built-in auto active extensionDependencies. + - Force use unix path for virtual source path to compat old project. + - Adjust default `project templates repo`, now it's: 'https://github.com/github0null/eide-templates'. + +*** + ### [v3.4.0] **Optimized**: diff --git a/README.md b/README.md index 8fb2230..fd0e92b 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ ## Summary 📑 -> Supported Platforms: **Windows (Windows 7 SP1 and later)**, **Linux x86_64 (Ubuntu)** +> Supported Platforms: **Windows (Windows 7 SP1 and later)**, **Linux x86_64** An embedded development environment for `8051/AVR/STM8/Cortex-M[0/0+/3/4/7]/RISC-V/Universal-Gcc` on VsCode. diff --git a/README_ZH-CN.md b/README_ZH-CN.md index 1abbda5..da5f55d 100644 --- a/README_ZH-CN.md +++ b/README_ZH-CN.md @@ -6,7 +6,7 @@ ## 简述 📑 -> 受支持的平台: **Windows (Windows 7 SP1 and later)**, **Linux x86_64 (Ubuntu)** +> 受支持的平台: **Windows (Windows 7 SP1 and later)**, **Linux x86_64** 一款适用于 8051/STM8/Cortex-M/RISC-V 的单片机开发环境。 diff --git a/package.json b/package.json index 30ffdb1..a454b64 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "homepage": "https://github.com/github0null/eide/blob/master/README.md", "license": "MIT", "description": "An embedded development environment for 8051/AVR/STM8/Cortex-M/RISC-V", - "version": "3.4.0", + "version": "3.5.0", "preview": false, "engines": { "vscode": "^1.63.0" @@ -97,9 +97,6 @@ "x2js": "3.4.1", "yaml": "^1.10.2" }, - "extensionDependencies": [ - "ms-vscode.cpptools" - ], "contributes": { "terminal": { "profiles": [ @@ -293,7 +290,7 @@ "type": "string", "scope": "machine", "markdownDescription": "%settings.template.repo.url%", - "default": "github0null/eide-resource/contents/eide-template-list" + "default": "github0null/eide-templates/contents" }, "EIDE.Repository.Template.GithubPersonalToken": { "type": "string", diff --git a/src/EIDEProject.ts b/src/EIDEProject.ts index ab880be..1d63707 100644 --- a/src/EIDEProject.ts +++ b/src/EIDEProject.ts @@ -64,6 +64,7 @@ import { import { SettingManager } from './SettingManager'; import { ExeCmd } from '../lib/node-utility/Executable'; import { jsonc } from 'jsonc'; +import * as iconv from 'iconv-lite'; export class CheckError extends Error { } @@ -772,67 +773,71 @@ export abstract class AbstractProject implements CustomConfigurationProvider { // create log folder this.getLogDir().CreateDir(); - // rename old 'deps' folder name for old eide version - const depsFolder = new File(this.rootDirWatcher.file.path + File.sep + DependenceManager.DEPENDENCE_DIR); - if (!depsFolder.IsDir()) { // if 'deps' folder is not exist - - // these folder is for old eide version - const oldDepsFolders = [ - new File(this.rootDirWatcher.file.path + File.sep + 'deps'), - new File(this.rootDirWatcher.file.path + File.sep + 'dependence') - ]; - - // create new 'deps' folder - // fs.mkdirSync(depsFolder.path); - - // copy dependence data from old version deps folder - for (const folder of oldDepsFolders) { - if (folder.IsDir()) { - - // copy dependence data - fs.renameSync(folder.path, depsFolder.path); - - // reset exclude info - const excludeList = this.GetConfiguration().config.excludeList; - const pathMatcher = `.${File.sep}${folder.name}${File.sep}`; - const pathReplacer = `${DependenceManager.DEPENDENCE_DIR}/`; - for (let index = 0; index < excludeList.length; index++) { - const element = excludeList[index]; - if (element.startsWith(pathMatcher)) { - excludeList[index] = element.replace(pathMatcher, pathReplacer); + // compat old project + if (this.isOldVersionProject) { + + // rename old 'deps' folder name for old eide version + const depsFolder = new File(this.rootDirWatcher.file.path + File.sep + DependenceManager.DEPENDENCE_DIR); + if (!depsFolder.IsDir()) { // if 'deps' folder is not exist + + // these folder is for old eide version + const oldDepsFolders = [ + new File(this.rootDirWatcher.file.path + File.sep + 'deps'), + new File(this.rootDirWatcher.file.path + File.sep + 'dependence') + ]; + + // create new 'deps' folder + // fs.mkdirSync(depsFolder.path); + + // copy dependence data from old version deps folder + for (const folder of oldDepsFolders) { + if (folder.IsDir()) { + + // copy dependence data + fs.renameSync(folder.path, depsFolder.path); + + // reset exclude info + const excludeList = this.GetConfiguration().config.excludeList; + const pathMatcher = `.${File.sep}${folder.name}${File.sep}`; + const pathReplacer = `${DependenceManager.DEPENDENCE_DIR}/`; + for (let index = 0; index < excludeList.length; index++) { + const element = excludeList[index]; + if (element.startsWith(pathMatcher)) { + excludeList[index] = element.replace(pathMatcher, pathReplacer); + } } - } - break; // exit, when copy done + break; // exit, when copy done + } } } - } - // merge old 'env.ini' files for v2.15.3^ - const envFile: File = this.getEnvFile(true); - if (!envFile.IsFile()) { // if 'env.ini' file is not existed, we try to merge it - const oldEnv: string[] = []; - this.eideDir.GetList([/[^\.]+\.env\.ini$/], File.EMPTY_FILTER) - .forEach((file) => { - const tName = NodePath.basename(file.path, '.env.ini'); - if (tName) { - try { - const cfg = ini.parse(file.Read()); - if (cfg['workspace']) { // merge old prj order cfg - cfg['EIDE_BUILD_ORDER'] = cfg['workspace']['order']; - delete cfg['workspace']; + // merge old 'env.ini' files for v2.15.3^ + const envFile: File = this.getEnvFile(true); + if (!envFile.IsFile()) { // if 'env.ini' file is not existed, we try to merge it + const oldEnv: string[] = []; + this.eideDir.GetList([/[^\.]+\.env\.ini$/], File.EMPTY_FILTER) + .forEach((file) => { + const tName = NodePath.basename(file.path, '.env.ini'); + if (tName) { + try { + const cfg = ini.parse(file.Read()); + if (cfg['workspace']) { // merge old prj order cfg + cfg['EIDE_BUILD_ORDER'] = cfg['workspace']['order']; + delete cfg['workspace']; + } + const cfg_str = ini.stringify(cfg); + fs.unlinkSync(file.path); // delete file before + oldEnv.push(`[${tName}]`, `${cfg_str}`); + } catch (error) { + // nothing todo } - const cfg_str = ini.stringify(cfg); - fs.unlinkSync(file.path); // delete file before - oldEnv.push(`[${tName}]`, `${cfg_str}`); - } catch (error) { - // nothing todo } - } - }); - if (oldEnv.length > 0) { - const cont = this.getEnvFileDefCont().concat(oldEnv); - envFile.Write(cont.join(os.EOL)); + }); + if (oldEnv.length > 0) { + const cont = this.getEnvFileDefCont().concat(oldEnv); + envFile.Write(cont.join(os.EOL)); + } } } } @@ -858,6 +863,16 @@ export abstract class AbstractProject implements CustomConfigurationProvider { && !(new File(this.ToAbsolutePath(prjConfig.config.packDir))).IsDir()) { prjConfig.config.packDir = null; } + + // use unix path for source path + if (this.isNewProject || this.isOldVersionProject) { + const dStack = [prjConfig.config.virtualFolder]; + while (dStack.length > 0) { + const vFolder = dStack.pop(); + vFolder.files.forEach(vFile => vFile.path = File.ToUnixPath(vFile.path)); + vFolder.folders.forEach(d => dStack.push(d)); + } + } } private initProjectComponents() { @@ -1657,7 +1672,8 @@ export abstract class AbstractProject implements CustomConfigurationProvider { //--- - protected isAnNewProject?: boolean | undefined; + protected isNewProject?: boolean | undefined; + protected isOldVersionProject?: boolean | undefined; protected async BeforeLoad(wsFile: File): Promise { @@ -1673,13 +1689,14 @@ export abstract class AbstractProject implements CustomConfigurationProvider { } else if (prjv_vs_eidev < 0) { // prj version < eide, update it conf.version = EIDE_CONF_VERSION; eideFile.Write(JSON.stringify(conf)); + this.isOldVersionProject = true; } } // check is an new project ? if (conf.miscInfo == undefined || conf.miscInfo.uid == undefined) { - this.isAnNewProject = true; + this.isNewProject = true; } } @@ -2023,7 +2040,9 @@ class EIDEProject extends AbstractProject { for (let i = startIndex; i < lines.length; i++) { const sepIndex = lines[i].indexOf(": "); if (sepIndex > 0) { - const line = lines[i].substring(sepIndex + 1).trim(); + const line = lines[i].substring(sepIndex + 1) + .replace(/\\ /g, " ") + .replace(/\\:/g, ":").trim(); resultList.push(this.ToAbsolutePath(line)); } } @@ -2033,7 +2052,15 @@ class EIDEProject extends AbstractProject { private parseRefFile(dFile: File, toolchain: ToolchainName): string[] { - const lines: string[] = dFile.Read() + let cont: string | undefined; + + if (platform.osType() == 'win32' && ResManager.getLocalCodePage() == '936') { // win32 gbk + cont = iconv.decode(fs.readFileSync(dFile.path), '936'); + } else { + cont = fs.readFileSync(dFile.path, 'utf8'); + } + + const lines: string[] = cont .split(/\r\n|\n/) .filter((line) => line.trim() != ''); @@ -2237,7 +2264,7 @@ class EIDEProject extends AbstractProject { await super.BeforeLoad(wsFile); // run pre-install.sh - if (this.isAnNewProject) { + if (this.isNewProject) { const name = 'pre-install.sh'; const prjRoot = new File(wsFile.dir); const ok = await this.runInstallScript(prjRoot, name, `Running 'post-install' ...`); @@ -2250,7 +2277,7 @@ class EIDEProject extends AbstractProject { await super.AfterLoad(); /* update workspace settings */ - if (this.isAnNewProject) { + if (this.isNewProject) { const workspaceConfig = this.GetWorkspaceConfig(); const settings = workspaceConfig.config.settings; @@ -2451,7 +2478,7 @@ class EIDEProject extends AbstractProject { } // run post-install.sh - if (this.isAnNewProject) { + if (this.isNewProject) { this.runInstallScript(this.GetRootDir(), 'post-install.sh', `Running 'post-install' ...`) .then((done) => { if (!done) { diff --git a/src/EIDETypeDefine.ts b/src/EIDETypeDefine.ts index d848731..3a1aab7 100644 --- a/src/EIDETypeDefine.ts +++ b/src/EIDETypeDefine.ts @@ -71,7 +71,7 @@ import * as utility from './utility'; //////////////////////////////////////////////////////// // eide project config file version -export const EIDE_CONF_VERSION = '3.0'; +export const EIDE_CONF_VERSION = '3.1'; //////////////////////////////////////////////////////// diff --git a/src/OperationExplorer.ts b/src/OperationExplorer.ts index 7e709e6..9b2e448 100644 --- a/src/OperationExplorer.ts +++ b/src/OperationExplorer.ts @@ -631,7 +631,8 @@ export class OperationExplorer { /* select install mode */ const resInstaller = ResInstaller.instance(); - if (resInstaller.hasTool(item.type)) { /* have online package */ + const tool = resInstaller.getTool(item.type); + if (tool && !tool.no_binaries) { /* have online package */ const pickItems: vscode.QuickPickItem[] = [ { @@ -832,7 +833,7 @@ export class OperationExplorer { const res = await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification, - title: 'Searching from ' + hostName + ' ...', + title: `Connect repo '${rawUrl}' ...`, cancellable: true }, (_, token): Thenable> => { return new Promise(async (resolve) => { @@ -895,7 +896,7 @@ export class OperationExplorer { // load index.json const indexFileBuf = await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification, - title: 'Downloading "index.json" ...', + title: 'Fetching templates index ...', cancellable: false }, (_, __): Thenable => { return new Promise(async (resolve) => { diff --git a/src/ResInstaller.ts b/src/ResInstaller.ts index cdb7224..a348829 100644 --- a/src/ResInstaller.ts +++ b/src/ResInstaller.ts @@ -127,7 +127,7 @@ export class ResInstaller { this.toolsMap.set(name.toLowerCase(), info); } - private getTool(name: ExternalToolName): ExternalToolInfo | undefined { + getTool(name: ExternalToolName): ExternalToolInfo | undefined { return this.toolsMap.get(name.toLowerCase()); } diff --git a/src/SettingManager.ts b/src/SettingManager.ts index 3ef04aa..bf3b5c9 100644 --- a/src/SettingManager.ts +++ b/src/SettingManager.ts @@ -162,11 +162,14 @@ export class SettingManager { const path = this.getConfiguration().get(confName); if (path) { - return Utility.formatPath(this.replaceEnvVariable(path)); + const absPath = Utility.formatPath(this.replaceEnvVariable(path)); + if (File.IsExist(absPath)) { + return absPath; + } } - else if (this.envPathCache.has(execName)) { - return this.envPathCache.get(execName) + if (this.envPathCache.has(execName)) { + return this.envPathCache.get(execName); } else { @@ -183,10 +186,13 @@ export class SettingManager { const path = this.getConfiguration().get(confName); if (path) { - return Utility.formatPath(this.replaceEnvVariable(path)); + const absPath = Utility.formatPath(this.replaceEnvVariable(path)); + if (File.IsExist(absPath)) { + return absPath; + } } - else if (this.envPathCache.has(execName)) { + if (this.envPathCache.has(execName)) { return this.envPathCache.get(execName); } @@ -309,10 +315,13 @@ export class SettingManager { const execName = 'JLink'; if (path) { - return Utility.formatPath(this.replaceEnvVariable(path)); + const absPath = Utility.formatPath(this.replaceEnvVariable(path)); + if (File.IsExist(absPath)) { + return absPath; + } } - else if (this.envPathCache.has(execName)) { + if (this.envPathCache.has(execName)) { return this.envPathCache.get(execName) } @@ -366,10 +375,13 @@ export class SettingManager { const execName = 'iccstm8'; if (path) { - return new File(Utility.formatPath(this.replaceEnvVariable(path))); + const absPath = Utility.formatPath(this.replaceEnvVariable(path)); + if (File.IsExist(absPath)) { + return new File(absPath); + } } - else if (this.envPathCache.has(execName)) { + if (this.envPathCache.has(execName)) { return new File(this.envPathCache.get(execName)) } diff --git a/src/extension.ts b/src/extension.ts index 2ceaa53..57eb068 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -46,6 +46,10 @@ import { VirtualDocument } from './VirtualDocsProvider'; import * as utility from './utility'; import * as platform from './Platform'; +const extension_deps: string[] = [ + "ms-vscode.cpptools" +]; + let projectExplorer: ProjectExplorer; let platformArch: string = 'x86_64'; let platformType: string = 'win32'; @@ -64,7 +68,7 @@ export async function activate(context: vscode.ExtensionContext) { // check linux arch, we only support x86-64 const archLi = [`x86_64`]; if (os.platform() == 'linux') { - platformArch = ChildProcess.execSync(`arch`).toString().trim(); + platformArch = ChildProcess.execSync(`uname -m`).toString().trim(); platformType = `linux-${platformArch}`; if (!archLi.includes(platformArch)) { vscode.window.showErrorMessage(`${ERROR} : This plug-in is only support '${archLi.join('/')}' arch, your pc is '${platformArch}' !`); @@ -72,19 +76,37 @@ export async function activate(context: vscode.ExtensionContext) { } } + // init event emiter RegisterGlobalEvent(); RegisterMsgListener(); GlobalEvent.emit('globalLog', newMessage('Info', 'Embedded IDE launch begin')); - /* init eide components */ + // try active dependence plug-ins + for (const name of extension_deps) { + const extension = vscode.extensions.getExtension(name); + if (extension) { + if (!extension.isActive) { + try { + GlobalEvent.emit('globalLog', newMessage('Info', `Active extension: '${name}'`)); + await extension.activate(); + } catch (error) { + GlobalEvent.emit('globalLog', ExceptionToMessage(error, 'Warning')); + } + } + } else { + GlobalEvent.emit('globalLog', newMessage('Warning', `The extension '${name}' is not enabled or installed !`)); + } + } + + // init eide components const done = await InitComponents(context); if (!done) { vscode.window.showErrorMessage(`${ERROR} : Install eide binaries failed !, You can download offline [vsix package](https://github.com/github0null/eide/releases) and install it !`); return; } - /* register vscode commands */ + // register vscode commands const subscriptions = context.subscriptions; // global user commands @@ -692,7 +714,7 @@ async function InitComponents(context: vscode.ExtensionContext): Promise${title}