diff --git a/CHANGELOG.md b/CHANGELOG.md index 47e0ac4d..e84e7fb7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,11 +4,18 @@ ## [Unreleased] +## [2.1.0-beta.3] - 2022-12-28 + ### Changed - Improved syntax highlighting for f-strings, operators and numeric literals. ### Fixed - Fixed clipping of code completion popup by terminal. +- Fixed code completion for builtin types. +- Fixed code completion for names starting with `_`. +- Fixed code completion for `from ...` for user modules ([support#759]). + +[support#759]: https://github.com/pybricks/support/issues/759 ## [2.1.0-beta.2] - 2022-12-26 @@ -659,7 +666,8 @@ Prerelease changes are documented at [support#48]. -[Unreleased]: https://github.com/pybricks/pybricks-code/compare/v2.1.0-beta.2...HEAD +[Unreleased]: https://github.com/pybricks/pybricks-code/compare/v2.1.0-beta.3...HEAD +[2.1.0-beta.3]: https://github.com/pybricks/pybricks-code/compare/v2.1.0-beta.2...v2.1.0-beta.3 [2.1.0-beta.2]: https://github.com/pybricks/pybricks-code/compare/v2.1.0-beta.1...v2.1.0-beta.2 [2.1.0-beta.1]: https://github.com/pybricks/pybricks-code/compare/v2.0.1...v2.1.0-beta.1 [2.0.1]: https://github.com/pybricks/pybricks-code/compare/v2.0.0...v2.0.1 diff --git a/package.json b/package.json index 706cf653..5bbebf48 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@pybricks/pybricks-code", - "version": "2.1.0-beta.2", + "version": "2.1.0-beta.3", "license": "MIT", "author": "The Pybricks Authors", "repository": { @@ -16,7 +16,7 @@ "@pybricks/firmware": "6.6.0", "@pybricks/ide-docs": "2.7.0", "@pybricks/images": "^1.3.0", - "@pybricks/jedi": "1.6.0", + "@pybricks/jedi": "1.7.0", "@pybricks/mpy-cross-v5": "^2.0.0", "@pybricks/mpy-cross-v6": "^2.0.0", "@pybricks/python-program-analysis": "^2.0.0", diff --git a/src/editor/pybricksMicroPython.ts b/src/editor/pybricksMicroPython.ts index 185297f7..8e148c8f 100644 --- a/src/editor/pybricksMicroPython.ts +++ b/src/editor/pybricksMicroPython.ts @@ -224,7 +224,7 @@ export const language = { [/\b0[bB](0|1|_)+/, 'constant.numeric.bin'], [/\b0[oO]([0-7]|_)+/, 'constant.numeric.oct'], [/\b0[xX]([abcdef]|[ABCDEF]|\d|_)+/, 'constant.numeric.hex'], - [/\b([\d_]*\.)?[\d_]+([eE][+-]?[\d_]+)?[jJ]?/, 'constant.numeric'], + [/\b(\d[\d_]*\.|\.)?\d[\d_]*([eE][+-]?[\d_]+)?[jJ]?/, 'constant.numeric'], ], // Recognize strings, including those broken across lines with \ (but not without) diff --git a/src/editor/sagas.ts b/src/editor/sagas.ts index b83bdf89..9b93eb61 100644 --- a/src/editor/sagas.ts +++ b/src/editor/sagas.ts @@ -698,7 +698,15 @@ function* runJedi(): Generator { } if (pythonMessageDidComplete.matches(msg.data)) { - const list = JSON.parse(msg.data.completionListJson); + const list: monaco.languages.CompletionItem[] = JSON.parse( + msg.data.completionListJson, + ); + + // maintain sort order from jedi + for (const [i, item] of list.entries()) { + item.sortText = String(i).padStart(5, '0'); + } + console.debug(list); complete.resolve({ suggestions: list }); console.debug(`${id}: resolved: ${msg.data.type}`); diff --git a/src/pybricksMicropython/python-worker.ts b/src/pybricksMicropython/python-worker.ts index f2ecd5d1..da00fa36 100644 --- a/src/pybricksMicropython/python-worker.ts +++ b/src/pybricksMicropython/python-worker.ts @@ -43,12 +43,25 @@ function fixUpError(err: unknown): Error { return error; } +/** + * Naively converts a file system path to a python module name. + * + * Assumes `.py` file extension and no invalid characters. + * + * @param path The path. + */ +function pathToModule(path: string): string { + return path.slice(0, path.length - 3).replaceAll('/', '.'); +} + const setUpPythonEnvironment = ` import jedi import pybricks_jedi print('preloading pybricks_jedi...') pybricks_jedi.initialize() +# TODO: this could be moved to pybricks_jedi.initialize() +pybricks_jedi.complete("from ", 1, 6) print('preloading done.') `; @@ -68,16 +81,20 @@ async function init(): Promise { pyodide.FS.mkdir(mountDir); pyodide.FS.mount(pyodide.FS.filesystems.MEMFS, { root: '.' }, mountDir); + const userModules = new Set(); + self.addEventListener('message', async (e) => { if (pythonMessageWriteUserFile.matches(e.data)) { pyodide.FS.writeFile(`${mountDir}/${e.data.path}`, e.data.contents); console.debug('copied', e.data.path, 'to emscripten fs'); + userModules.add(pathToModule(e.data.path)); return; } if (pythonMessageDeleteUserFile.matches(e.data)) { pyodide.FS.unlink(`${mountDir}/${e.data.path}`); console.debug('removed', e.data.path, ' from emscripten fs'); + userModules.delete(pathToModule(e.data.path)); return; } }); @@ -103,6 +120,7 @@ async function init(): Promise { const complete = pyodide.runPython('pybricks_jedi.complete'); const getSignatures = pyodide.runPython('pybricks_jedi.get_signatures'); + const updateUserModules = pyodide.runPython('pybricks_jedi.update_user_modules'); self.addEventListener('message', async (e) => { if (pythonMessageSetInterruptBuffer.matches(e.data)) { @@ -113,6 +131,7 @@ async function init(): Promise { if (pythonMessageComplete.matches(e.data)) { console.debug('worker received complete message'); try { + updateUserModules(userModules); const { code, lineNumber, column } = e.data; const list = complete(code, lineNumber, column); self.postMessage(pythonMessageDidComplete(list)); @@ -125,6 +144,7 @@ async function init(): Promise { if (pythonMessageGetSignature.matches(e.data)) { console.debug('worker received getSignatures message'); try { + updateUserModules(userModules); const { code, lineNumber, column } = e.data; const list = getSignatures(code, lineNumber, column); self.postMessage(pythonMessageDidGetSignature(list)); diff --git a/yarn.lock b/yarn.lock index 09f30226..b88f63c4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2383,10 +2383,10 @@ __metadata: languageName: node linkType: hard -"@pybricks/jedi@npm:1.6.0": - version: 1.6.0 - resolution: "@pybricks/jedi@npm:1.6.0" - checksum: 982154fa8b3de0e8fcd023e89b6a6223c55948a673e47f25876eba18305d068d97f56012226eb2a217109dc924a43e8f912aae82f7c944eeb398448d90ff3f78 +"@pybricks/jedi@npm:1.7.0": + version: 1.7.0 + resolution: "@pybricks/jedi@npm:1.7.0" + checksum: 54a80640197ec674dcf99077a5a9906716b65361f6a8b22ebadc0f1d2716405c60cb0b76b14797b265e90ccac87a7b237d323399f8440d713c7850b2b37218f1 languageName: node linkType: hard @@ -2416,7 +2416,7 @@ __metadata: "@pybricks/firmware": 6.6.0 "@pybricks/ide-docs": 2.7.0 "@pybricks/images": ^1.3.0 - "@pybricks/jedi": 1.6.0 + "@pybricks/jedi": 1.7.0 "@pybricks/mpy-cross-v5": ^2.0.0 "@pybricks/mpy-cross-v6": ^2.0.0 "@pybricks/python-program-analysis": ^2.0.0