From e83b6fc7d277b1c4b83b7297d702d6ac525aacfe Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 9 Mar 2021 17:47:10 +0100 Subject: [PATCH 01/63] Move to @codemirror/buildhelper --- .gitignore | 3 --- package.json | 6 ++---- rollup.config.js | 22 ---------------------- tsconfig.local.json | 19 ------------------- 4 files changed, 2 insertions(+), 48 deletions(-) delete mode 100644 rollup.config.js delete mode 100644 tsconfig.local.json diff --git a/.gitignore b/.gitignore index 01bff1b..eebad72 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,6 @@ /node_modules package-lock.json /dist -/src/*.js -/src/*.d.ts -/src/*.d.ts.map /test/*.js /test/*.d.ts /test/*.d.ts.map diff --git a/package.json b/package.json index bc90561..0202daa 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "Python language support for the CodeMirror code editor", "scripts": { "test": "echo 'No tests'", - "prepare": "tsc -p tsconfig.local.json && rollup -c" + "prepare": "cm-buildhelper src/python.ts" }, "keywords": [ "editor", @@ -31,9 +31,7 @@ "lezer-python": "^0.13.0" }, "devDependencies": { - "rollup": "^2.35.1", - "rollup-plugin-dts": "^2.0.1", - "typescript": "^4.1.3" + "@codemirror/buildhelper": "^0.1.0" }, "repository": { "type": "git", diff --git a/rollup.config.js b/rollup.config.js deleted file mode 100644 index 096deef..0000000 --- a/rollup.config.js +++ /dev/null @@ -1,22 +0,0 @@ -import dts from "rollup-plugin-dts" - -export default [{ - input: "./src/python.js", - external: id => id != "tslib" && !/^(\.?\/|\w:)/.test(id), - output: [{ - format: "esm", - file: "./dist/index.js", - externalLiveBindings: false - }, { - format: "cjs", - file: "./dist/index.cjs" - }] -}, { - input: "./src/python.d.ts", - output: { - format: "esm", - file: "./dist/index.d.ts", - }, - plugins: [dts()], - onwarn(warning, warn) { if (warning.code != "CIRCULAR_DEPENDENCY") warn(warning) } -}] diff --git a/tsconfig.local.json b/tsconfig.local.json deleted file mode 100644 index 39f3353..0000000 --- a/tsconfig.local.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "compilerOptions": { - "lib": ["es6", "dom", "scripthost"], - "types": ["mocha"], - "stripInternal": true, - "noUnusedLocals": true, - "strict": true, - "target": "es6", - "module": "es2020", - "newLine": "lf", - "declaration": true, - "declarationMap": true, - "moduleResolution": "node", - "paths": { - "@codemirror/lang-python": ["./src/python.ts"] - } - }, - "include": ["src/*.ts", "test/*.ts"] -} From c7c96a4c7df16eca7d41069f3e89137b79633c4d Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 26 Apr 2021 18:27:12 +0200 Subject: [PATCH 02/63] Use cm-runtests as the test script --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0202daa..d6dcbac 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "0.18.0", "description": "Python language support for the CodeMirror code editor", "scripts": { - "test": "echo 'No tests'", + "test": "cm-runtests", "prepare": "cm-buildhelper src/python.ts" }, "keywords": [ From 7192ceb844a0c60ea112807da3666fa415f08ddf Mon Sep 17 00:00:00 2001 From: Matt Hillsdon <44397098+microbit-matt-hillsdon@users.noreply.github.com> Date: Mon, 24 May 2021 12:34:55 +0100 Subject: [PATCH 03/63] Fix typo in highlighting selector FIX: Fix highlighting of property names. --- src/python.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/python.ts b/src/python.ts index 5bc1782..ff02fa6 100644 --- a/src/python.ts +++ b/src/python.ts @@ -28,7 +28,7 @@ export const pythonLanguage = LezerLanguage.define({ "FunctionDefinition/VariableName": t.function(t.definition(t.variableName)), "ClassDefinition/VariableName": t.definition(t.className), PropertyName: t.propertyName, - "CallExpression/MemberExpression/ProperyName": t.function(t.propertyName), + "CallExpression/MemberExpression/PropertyName": t.function(t.propertyName), Comment: t.lineComment, Number: t.number, String: t.string, From 11078ad3fc08fac5eda676e363226eef2d65d0bb Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 20 Jul 2021 13:35:12 +0200 Subject: [PATCH 04/63] Improve indentation support FIX: Don't deindent when pressing enter at the end of the document. FIX: Properly indent else/elif/except syntax. Issue https://github.com/codemirror/codemirror.next/issues/538 --- src/python.ts | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/python.ts b/src/python.ts index ff02fa6..be689f4 100644 --- a/src/python.ts +++ b/src/python.ts @@ -9,7 +9,18 @@ export const pythonLanguage = LezerLanguage.define({ parser: parser.configure({ props: [ indentNodeProp.add({ - Body: continuedIndent() + Body: continuedIndent({except: /^\s*(else|elif|except|finally)\b/}), + Script: context => { + if (context.pos + /\s*/.exec(context.textAfter)![0].length < context.node.to) + return context.continue() + let endBody = null + for (let cur = context.node;;) { + let last = cur.lastChild + if (!last || last.type.name != "Body" || last.to != cur.to) break + endBody = cur = last + } + return endBody ? context.lineIndent(context.state.doc.lineAt(endBody.from)) + context.unit : null + } }), foldNodeProp.add({ "Body ArrayExpression DictionaryExpression": foldInside @@ -51,7 +62,7 @@ export const pythonLanguage = LezerLanguage.define({ languageData: { closeBrackets: {brackets: ["(", "[", "{", "'", '"', "'''", '"""']}, commentTokens: {line: "#"}, - indentOnInput: /^\s*[\}\]\)]$/ + indentOnInput: /^\s*([\}\]\)]|else:|elif |except |finally:)$/ } }) From dc79e548060277e049179ee6d8f98a37f283e566 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 20 Jul 2021 13:37:57 +0200 Subject: [PATCH 05/63] Mark version 0.18.1 --- CHANGELOG.md | 10 ++++++++++ package.json | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d8ebf0..698febe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ +## 0.18.1 (2021-07-20) + +### Bug fixes + +Fix highlighting of property names. Improve indentation support + +Don't deindent when pressing enter at the end of the document. + +Properly indent else/elif/except syntax. + ## 0.18.0 (2021-03-03) ### Breaking changes diff --git a/package.json b/package.json index d6dcbac..c205154 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@codemirror/lang-python", - "version": "0.18.0", + "version": "0.18.1", "description": "Python language support for the CodeMirror code editor", "scripts": { "test": "cm-runtests", From 88b3998c2ec38c65f8115dc6a24eee0df47947c8 Mon Sep 17 00:00:00 2001 From: Matt Davies Date: Tue, 20 Jul 2021 18:02:17 +0100 Subject: [PATCH 06/63] Add indentation in multiline dictionary, array or tuple FIX: Improve indentation for dictionaries, arrays, and tuples. --- src/python.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/python.ts b/src/python.ts index be689f4..c14998e 100644 --- a/src/python.ts +++ b/src/python.ts @@ -1,5 +1,5 @@ import {parser} from "lezer-python" -import {continuedIndent, indentNodeProp, foldNodeProp, foldInside, LezerLanguage, LanguageSupport} from "@codemirror/language" +import {continuedIndent, delimitedIndent, indentNodeProp, foldNodeProp, foldInside, LezerLanguage, LanguageSupport} from "@codemirror/language" import {styleTags, tags as t} from "@codemirror/highlight" /// A language provider based on the [Lezer Python @@ -10,6 +10,9 @@ export const pythonLanguage = LezerLanguage.define({ props: [ indentNodeProp.add({ Body: continuedIndent({except: /^\s*(else|elif|except|finally)\b/}), + TupleExpression: delimitedIndent(), + DictionaryExpression: delimitedIndent(), + ArrayExpression: delimitedIndent(), Script: context => { if (context.pos + /\s*/.exec(context.textAfter)![0].length < context.node.to) return context.continue() From 18462e73470c78bd061a232896dc145cf5403acd Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Sat, 24 Jul 2021 14:22:36 +0200 Subject: [PATCH 07/63] Fix delimitedIndent calls Issue https://github.com/codemirror/lang-python/pull/3 --- src/python.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/python.ts b/src/python.ts index c14998e..09e214f 100644 --- a/src/python.ts +++ b/src/python.ts @@ -10,9 +10,9 @@ export const pythonLanguage = LezerLanguage.define({ props: [ indentNodeProp.add({ Body: continuedIndent({except: /^\s*(else|elif|except|finally)\b/}), - TupleExpression: delimitedIndent(), - DictionaryExpression: delimitedIndent(), - ArrayExpression: delimitedIndent(), + TupleExpression: delimitedIndent({closing: ")"}), + DictionaryExpression: delimitedIndent({closing: "}"}), + ArrayExpression: delimitedIndent({closing: "]"}), Script: context => { if (context.pos + /\s*/.exec(context.textAfter)![0].length < context.node.to) return context.continue() From 32aad78e282cb1962bdbcc4b7da3e98f65e521f4 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Fri, 25 Jun 2021 19:07:37 +0200 Subject: [PATCH 08/63] Adjust to new Lezer package names --- package.json | 2 +- src/python.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index c205154..330ef35 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "dependencies": { "@codemirror/highlight": "^0.18.0", "@codemirror/language": "^0.18.0", - "lezer-python": "^0.13.0" + "@lezer/python": "^0.14.0" }, "devDependencies": { "@codemirror/buildhelper": "^0.1.0" diff --git a/src/python.ts b/src/python.ts index 09e214f..564b770 100644 --- a/src/python.ts +++ b/src/python.ts @@ -1,4 +1,4 @@ -import {parser} from "lezer-python" +import {parser} from "@lezer/python" import {continuedIndent, delimitedIndent, indentNodeProp, foldNodeProp, foldInside, LezerLanguage, LanguageSupport} from "@codemirror/language" import {styleTags, tags as t} from "@codemirror/highlight" From 81b681cf4af860ecf8ce60997d8b0f38a6a09254 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 9 Aug 2021 10:30:15 +0200 Subject: [PATCH 09/63] Improve indentation at end of blocks FIX: Indentation on deindented blank lines after a block will no longer return to the block's indentation level. Issue https://github.com/codemirror/lang-python/pull/4 --- src/python.ts | 45 ++++++++++++++++++++++++++++++------------ test/test-indent.ts | 48 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 13 deletions(-) create mode 100644 test/test-indent.ts diff --git a/src/python.ts b/src/python.ts index 564b770..07304bf 100644 --- a/src/python.ts +++ b/src/python.ts @@ -1,7 +1,22 @@ import {parser} from "@lezer/python" -import {continuedIndent, delimitedIndent, indentNodeProp, foldNodeProp, foldInside, LezerLanguage, LanguageSupport} from "@codemirror/language" +import {SyntaxNode} from "@lezer/common" +import {delimitedIndent, indentNodeProp, TreeIndentContext, + foldNodeProp, foldInside, LezerLanguage, LanguageSupport} from "@codemirror/language" import {styleTags, tags as t} from "@codemirror/highlight" +function indentBody(context: TreeIndentContext, node: SyntaxNode) { + let base = context.lineIndent(node.from) + let line = context.lineAt(context.pos, -1), to = line.from + line.text.length + // Don't consider blank, deindented lines at the end of the + // block part of the block + if (!/\S/.test(line.text) && + context.node.to < to + 100 && + !/\S/.test(context.state.sliceDoc(to, context.node.to)) && + context.lineIndent(context.pos, -1) <= base) + return null + return base + context.unit +} + /// A language provider based on the [Lezer Python /// parser](https://github.com/lezer-parser/python), extended with /// highlighting and indentation information. @@ -9,20 +24,24 @@ export const pythonLanguage = LezerLanguage.define({ parser: parser.configure({ props: [ indentNodeProp.add({ - Body: continuedIndent({except: /^\s*(else|elif|except|finally)\b/}), - TupleExpression: delimitedIndent({closing: ")"}), - DictionaryExpression: delimitedIndent({closing: "}"}), - ArrayExpression: delimitedIndent({closing: "]"}), + Body: context => indentBody(context, context.node) ?? context.continue(), + "TupleExpression ComprehensionExpression ParamList ArgList ParenthesizedExpression": delimitedIndent({closing: ")"}), + "DictionaryExpression DictionaryComprehensionExpression SetExpression SetComprehensionExpression": delimitedIndent({closing: "}"}), + "ArrayExpression ArrayComprehensionExpression": delimitedIndent({closing: "]"}), Script: context => { - if (context.pos + /\s*/.exec(context.textAfter)![0].length < context.node.to) - return context.continue() - let endBody = null - for (let cur = context.node;;) { - let last = cur.lastChild - if (!last || last.type.name != "Body" || last.to != cur.to) break - endBody = cur = last + if (context.pos + /\s*/.exec(context.textAfter)![0].length >= context.node.to) { + let endBody = null + for (let cur: SyntaxNode | null = context.node, to = cur.to;;) { + cur = cur.lastChild + if (!cur || cur.to != to) break + if (cur.type.name == "Body") endBody = cur + } + if (endBody) { + let bodyIndent = indentBody(context, endBody) + if (bodyIndent != null) return bodyIndent + } } - return endBody ? context.lineIndent(context.state.doc.lineAt(endBody.from)) + context.unit : null + return context.continue() } }), foldNodeProp.add({ diff --git a/test/test-indent.ts b/test/test-indent.ts new file mode 100644 index 0000000..e117984 --- /dev/null +++ b/test/test-indent.ts @@ -0,0 +1,48 @@ +import ist from "ist" +import {EditorState} from "@codemirror/state" +import {getIndentation} from "@codemirror/language" +import {python} from "@codemirror/lang-python" + +function check(code: string) { + return () => { + code = /^\n*([^]*)/.exec(code)![1] + let state = EditorState.create({doc: code, extensions: [python().language]}) + for (let pos = 0, lines = code.split("\n"), i = 0; i < lines.length; i++) { + let line = lines[i], indent = /^\s*/.exec(line)![0].length + ist(`${getIndentation(state, pos)} (${i + 1})`, `${indent} (${i + 1})`) + pos += line.length + 1 + } + } +} + +describe("python indentation", () => { + it("indents bodies", check(` +def foo(): + bar + baz + +`)) + + it("indents function arg lists", check(` +foo( + bar, + baz +)`)) + + it("indents nested bodies", check(` +def foo(): + if True: + a + elif False: + b + else: + c +`)) + + it("dedents except", check(` +try: + foo() +except e: + bar() +`)) +}) From d8f189d4a5da8993be3cdb7ec840b9a588fa9395 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 11 Aug 2021 08:33:07 +0200 Subject: [PATCH 10/63] Follow LezerLanguage -> LRLanguage rename --- src/python.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/python.ts b/src/python.ts index 07304bf..f261384 100644 --- a/src/python.ts +++ b/src/python.ts @@ -1,7 +1,7 @@ import {parser} from "@lezer/python" import {SyntaxNode} from "@lezer/common" import {delimitedIndent, indentNodeProp, TreeIndentContext, - foldNodeProp, foldInside, LezerLanguage, LanguageSupport} from "@codemirror/language" + foldNodeProp, foldInside, LRLanguage, LanguageSupport} from "@codemirror/language" import {styleTags, tags as t} from "@codemirror/highlight" function indentBody(context: TreeIndentContext, node: SyntaxNode) { @@ -20,7 +20,7 @@ function indentBody(context: TreeIndentContext, node: SyntaxNode) { /// A language provider based on the [Lezer Python /// parser](https://github.com/lezer-parser/python), extended with /// highlighting and indentation information. -export const pythonLanguage = LezerLanguage.define({ +export const pythonLanguage = LRLanguage.define({ parser: parser.configure({ props: [ indentNodeProp.add({ From a0c78c4662696de936c91a3b3ae3c3f34971f436 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 11 Aug 2021 14:24:27 +0200 Subject: [PATCH 11/63] Mark version 0.19.0 --- CHANGELOG.md | 8 ++++++++ package.json | 6 +++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 698febe..0a1fd00 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## 0.19.0 (2021-08-11) + +### Bug fixes + +Improve indentation for dictionaries, arrays, and tuples. Fix delimitedIndent calls + +Indentation on deindented blank lines after a block will no longer return to the block's indentation level. + ## 0.18.1 (2021-07-20) ### Bug fixes diff --git a/package.json b/package.json index 330ef35..763875b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@codemirror/lang-python", - "version": "0.18.1", + "version": "0.19.0", "description": "Python language support for the CodeMirror code editor", "scripts": { "test": "cm-runtests", @@ -26,8 +26,8 @@ "sideEffects": false, "license": "MIT", "dependencies": { - "@codemirror/highlight": "^0.18.0", - "@codemirror/language": "^0.18.0", + "@codemirror/highlight": "^0.19.0", + "@codemirror/language": "^0.19.0", "@lezer/python": "^0.14.0" }, "devDependencies": { From c78c4efb3df259ab557798bb82a2c8e0fbef9473 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 11 Aug 2021 15:25:26 +0200 Subject: [PATCH 12/63] Fix lezer dependency versions FIX: Fix incorrect versions for @lezer dependencies. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 763875b..27b7fd9 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "dependencies": { "@codemirror/highlight": "^0.19.0", "@codemirror/language": "^0.19.0", - "@lezer/python": "^0.14.0" + "@lezer/python": "^0.15.0" }, "devDependencies": { "@codemirror/buildhelper": "^0.1.0" From 5fde20b094528532fee12cdc9372aeb3d1ecaa0a Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 11 Aug 2021 15:27:08 +0200 Subject: [PATCH 13/63] Mark version 0.19.1 --- CHANGELOG.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a1fd00..1387ca4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 0.19.1 (2021-08-11) + +### Bug fixes + +Fix incorrect versions for @lezer dependencies. + ## 0.19.0 (2021-08-11) ### Bug fixes diff --git a/package.json b/package.json index 27b7fd9..451b4fb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@codemirror/lang-python", - "version": "0.19.0", + "version": "0.19.1", "description": "Python language support for the CodeMirror code editor", "scripts": { "test": "cm-runtests", From aec5ac8e482d9dcb1662e3ca52c174d02f5f5d49 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 11 Aug 2021 16:47:49 +0200 Subject: [PATCH 14/63] Further refine indentation behavior FIX: Make sure that indenting an else/elif/except/finally that's indented too deep moves it back up. --- src/python.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/python.ts b/src/python.ts index f261384..2ce87ae 100644 --- a/src/python.ts +++ b/src/python.ts @@ -14,6 +14,11 @@ function indentBody(context: TreeIndentContext, node: SyntaxNode) { !/\S/.test(context.state.sliceDoc(to, context.node.to)) && context.lineIndent(context.pos, -1) <= base) return null + // A normally deindenting keyword that appears at a higher + // indentation than the block should probably be handled by the next + // level + if (/^\s*(else:|elif |except |finally:)/.test(context.textAfter) && context.lineIndent(context.pos, -1) > base) + return null return base + context.unit } @@ -25,6 +30,8 @@ export const pythonLanguage = LRLanguage.define({ props: [ indentNodeProp.add({ Body: context => indentBody(context, context.node) ?? context.continue(), + IfStatement: cx => /^\s*(else:|elif )/.test(cx.textAfter) ? cx.baseIndent : cx.continue(), + TryStatement: cx => /^\s*(except |finally:)/.test(cx.textAfter) ? cx.baseIndent : cx.continue(), "TupleExpression ComprehensionExpression ParamList ArgList ParenthesizedExpression": delimitedIndent({closing: ")"}), "DictionaryExpression DictionaryComprehensionExpression SetExpression SetComprehensionExpression": delimitedIndent({closing: "}"}), "ArrayExpression ArrayComprehensionExpression": delimitedIndent({closing: "]"}), From 5c1aa7936ca579649026fd178934d2aa5e20c3e5 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 11 Aug 2021 16:47:53 +0200 Subject: [PATCH 15/63] Mark version 0.19.2 --- CHANGELOG.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1387ca4..a2298fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 0.19.2 (2021-08-11) + +### Bug fixes + +Make sure that indenting an else/elif/except/finally that's indented too deep moves it back up. + ## 0.19.1 (2021-08-11) ### Bug fixes diff --git a/package.json b/package.json index 451b4fb..07a087a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@codemirror/lang-python", - "version": "0.19.1", + "version": "0.19.2", "description": "Python language support for the CodeMirror code editor", "scripts": { "test": "cm-runtests", From cdeca5b8251460c56bcdd460d10dad436854b117 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 3 Jan 2022 08:52:44 +0100 Subject: [PATCH 16/63] Use moduleKeyword tag --- package.json | 2 +- src/python.ts | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 07a087a..546d8fc 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "sideEffects": false, "license": "MIT", "dependencies": { - "@codemirror/highlight": "^0.19.0", + "@codemirror/highlight": "^0.19.7", "@codemirror/language": "^0.19.0", "@lezer/python": "^0.15.0" }, diff --git a/src/python.ts b/src/python.ts index 2ce87ae..c80e0c7 100644 --- a/src/python.ts +++ b/src/python.ts @@ -58,7 +58,8 @@ export const pythonLanguage = LRLanguage.define({ "async '*' '**' FormatConversion": t.modifier, "for while if elif else try except finally return raise break continue with pass assert await yield": t.controlKeyword, "in not and or is del": t.operatorKeyword, - "import from def class global nonlocal lambda": t.definitionKeyword, + "from def class global nonlocal lambda": t.definitionKeyword, + import: t.moduleKeyword, "with as print": t.keyword, self: t.self, Boolean: t.bool, From f07ceef5be747af5b0e42aed67800bc41fde3378 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 20 Jan 2022 09:45:11 +0100 Subject: [PATCH 17/63] Fix fold logic for Body nodes FIX: Fix the way block bodies are folded. Closes https://github.com/codemirror/codemirror.next/issues/694 --- src/python.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/python.ts b/src/python.ts index c80e0c7..e73282e 100644 --- a/src/python.ts +++ b/src/python.ts @@ -52,7 +52,8 @@ export const pythonLanguage = LRLanguage.define({ } }), foldNodeProp.add({ - "Body ArrayExpression DictionaryExpression": foldInside + "ArrayExpression DictionaryExpression": foldInside, + Body: node => ({from: node.from + 1, to: node.to}) }), styleTags({ "async '*' '**' FormatConversion": t.modifier, From 44f7cfd6cf123f03a521e605db17b118ab4083fe Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 20 Jan 2022 09:45:15 +0100 Subject: [PATCH 18/63] Mark version 0.19.3 --- CHANGELOG.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a2298fa..3dbe004 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 0.19.3 (2022-01-20) + +### Bug fixes + +Fix the way block bodies are folded. + ## 0.19.2 (2021-08-11) ### Bug fixes diff --git a/package.json b/package.json index 546d8fc..307a018 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@codemirror/lang-python", - "version": "0.19.2", + "version": "0.19.3", "description": "Python language support for the CodeMirror code editor", "scripts": { "test": "cm-runtests", From 33ce6b5f7e704ce6cb7813839ca5871ee2f93d20 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 26 Jan 2022 08:15:30 +0100 Subject: [PATCH 19/63] Don't fold across newline after bodies FIX: Fix issue where folding body nodes folded away the newline after the body. Closes https://github.com/codemirror/lang-python/pull/5 --- src/python.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/python.ts b/src/python.ts index e73282e..5dab8ba 100644 --- a/src/python.ts +++ b/src/python.ts @@ -53,7 +53,7 @@ export const pythonLanguage = LRLanguage.define({ }), foldNodeProp.add({ "ArrayExpression DictionaryExpression": foldInside, - Body: node => ({from: node.from + 1, to: node.to}) + Body: (node, state) => ({from: node.from + 1, to: node.to - (node.to == state.doc.length ? 0 : 1)}) }), styleTags({ "async '*' '**' FormatConversion": t.modifier, From 5da5c854bc75027a5fb7251c1869fff8fac155e3 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 26 Jan 2022 08:36:06 +0100 Subject: [PATCH 20/63] Mark version 0.19.4 --- CHANGELOG.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3dbe004..fa0d857 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 0.19.4 (2022-01-26) + +### Bug fixes + +Fix issue where folding body nodes folded away the newline after the body. + ## 0.19.3 (2022-01-20) ### Bug fixes diff --git a/package.json b/package.json index 307a018..fef7f0c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@codemirror/lang-python", - "version": "0.19.3", + "version": "0.19.4", "description": "Python language support for the CodeMirror code editor", "scripts": { "test": "cm-runtests", From 7eb62a5f4ec41f3ad112bac25bf71185a4fdf010 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 17 Mar 2022 09:42:32 +0100 Subject: [PATCH 21/63] Fix some mistakes in the highlighting information FIX: Make sure * and ** modifiers are highlighted as such, add modifier tag for FormatSpec nodes. Issue https://github.com/codemirror/codemirror.next/issues/771 --- src/python.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/python.ts b/src/python.ts index 5dab8ba..2d7c9c2 100644 --- a/src/python.ts +++ b/src/python.ts @@ -56,13 +56,12 @@ export const pythonLanguage = LRLanguage.define({ Body: (node, state) => ({from: node.from + 1, to: node.to - (node.to == state.doc.length ? 0 : 1)}) }), styleTags({ - "async '*' '**' FormatConversion": t.modifier, + "async \"*\" \"**\" FormatConversion FormatSpec": t.modifier, "for while if elif else try except finally return raise break continue with pass assert await yield": t.controlKeyword, "in not and or is del": t.operatorKeyword, "from def class global nonlocal lambda": t.definitionKeyword, import: t.moduleKeyword, "with as print": t.keyword, - self: t.self, Boolean: t.bool, None: t.null, VariableName: t.variableName, From 805d6eac58489bc57aaa0d0d4975d6fccd167f0f Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 6 Apr 2022 08:44:39 +0200 Subject: [PATCH 22/63] Mark version 0.19.5 --- CHANGELOG.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fa0d857..5ea0dbe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 0.19.5 (2022-04-06) + +### Bug fixes + +Make sure * and ** modifiers are highlighted as such, add modifier tag for FormatSpec nodes. + ## 0.19.4 (2022-01-26) ### Bug fixes diff --git a/package.json b/package.json index fef7f0c..83e5f99 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@codemirror/lang-python", - "version": "0.19.4", + "version": "0.19.5", "description": "Python language support for the CodeMirror code editor", "scripts": { "test": "cm-runtests", From 4fc7033ebfc712abbdcfcdf0817c326d85419cee Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 24 Mar 2022 09:56:00 +0100 Subject: [PATCH 23/63] Move highlighting information into @lezer/python --- package.json | 1 - src/python.ts | 33 --------------------------------- 2 files changed, 34 deletions(-) diff --git a/package.json b/package.json index 83e5f99..62aa245 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,6 @@ "sideEffects": false, "license": "MIT", "dependencies": { - "@codemirror/highlight": "^0.19.7", "@codemirror/language": "^0.19.0", "@lezer/python": "^0.15.0" }, diff --git a/src/python.ts b/src/python.ts index 2d7c9c2..16efbc2 100644 --- a/src/python.ts +++ b/src/python.ts @@ -2,7 +2,6 @@ import {parser} from "@lezer/python" import {SyntaxNode} from "@lezer/common" import {delimitedIndent, indentNodeProp, TreeIndentContext, foldNodeProp, foldInside, LRLanguage, LanguageSupport} from "@codemirror/language" -import {styleTags, tags as t} from "@codemirror/highlight" function indentBody(context: TreeIndentContext, node: SyntaxNode) { let base = context.lineIndent(node.from) @@ -54,38 +53,6 @@ export const pythonLanguage = LRLanguage.define({ foldNodeProp.add({ "ArrayExpression DictionaryExpression": foldInside, Body: (node, state) => ({from: node.from + 1, to: node.to - (node.to == state.doc.length ? 0 : 1)}) - }), - styleTags({ - "async \"*\" \"**\" FormatConversion FormatSpec": t.modifier, - "for while if elif else try except finally return raise break continue with pass assert await yield": t.controlKeyword, - "in not and or is del": t.operatorKeyword, - "from def class global nonlocal lambda": t.definitionKeyword, - import: t.moduleKeyword, - "with as print": t.keyword, - Boolean: t.bool, - None: t.null, - VariableName: t.variableName, - "CallExpression/VariableName": t.function(t.variableName), - "FunctionDefinition/VariableName": t.function(t.definition(t.variableName)), - "ClassDefinition/VariableName": t.definition(t.className), - PropertyName: t.propertyName, - "CallExpression/MemberExpression/PropertyName": t.function(t.propertyName), - Comment: t.lineComment, - Number: t.number, - String: t.string, - FormatString: t.special(t.string), - UpdateOp: t.updateOperator, - ArithOp: t.arithmeticOperator, - BitOp: t.bitwiseOperator, - CompareOp: t.compareOperator, - AssignOp: t.definitionOperator, - Ellipsis: t.punctuation, - At: t.meta, - "( )": t.paren, - "[ ]": t.squareBracket, - "{ }": t.brace, - ".": t.derefOperator, - ", ;": t.separator }) ], }), From 8a085d967f6e6f4477287c96dc93323a6fb68b6d Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 19 Apr 2022 18:13:35 +0200 Subject: [PATCH 24/63] Allow set and tuple expressions to be folded FIX: Add folding information for set and tuple expressions. Closes https://github.com/codemirror/codemirror.next/issues/803 --- src/python.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/python.ts b/src/python.ts index 16efbc2..5b43a02 100644 --- a/src/python.ts +++ b/src/python.ts @@ -51,7 +51,7 @@ export const pythonLanguage = LRLanguage.define({ } }), foldNodeProp.add({ - "ArrayExpression DictionaryExpression": foldInside, + "ArrayExpression DictionaryExpression SetExpression TupleExpression": foldInside, Body: (node, state) => ({from: node.from + 1, to: node.to - (node.to == state.doc.length ? 0 : 1)}) }) ], From b92fa7945eda39067c64f362849a1e3ea8778e72 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 20 Apr 2022 15:54:51 +0200 Subject: [PATCH 25/63] Bump lezer version to 0.16.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 62aa245..c50bf9d 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "license": "MIT", "dependencies": { "@codemirror/language": "^0.19.0", - "@lezer/python": "^0.15.0" + "@lezer/python": "^0.16.0" }, "devDependencies": { "@codemirror/buildhelper": "^0.1.0" From 10c7a439f6f8141a3f91f2966759bea33be92244 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 20 Apr 2022 16:10:56 +0200 Subject: [PATCH 26/63] Mark version 0.20.0 --- CHANGELOG.md | 6 ++++++ package.json | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ea0dbe..d4f062b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 0.20.0 (2022-04-20) + +### Bug fixes + +Add folding information for set and tuple expressions. + ## 0.19.5 (2022-04-06) ### Bug fixes diff --git a/package.json b/package.json index c50bf9d..db5e312 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@codemirror/lang-python", - "version": "0.19.5", + "version": "0.20.0", "description": "Python language support for the CodeMirror code editor", "scripts": { "test": "cm-runtests", @@ -26,7 +26,7 @@ "sideEffects": false, "license": "MIT", "dependencies": { - "@codemirror/language": "^0.19.0", + "@codemirror/language": "^0.20.0", "@lezer/python": "^0.16.0" }, "devDependencies": { From 3b30be2b6d12d34cdb4c5e540c88412d8a815d52 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 8 Jun 2022 08:45:27 +0200 Subject: [PATCH 27/63] Mark version 6.0.0 --- CHANGELOG.md | 6 ++++++ package.json | 6 +++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d4f062b..8a5197b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 6.0.0 (2022-06-08) + +### Breaking changes + +Update dependencies to 6.0.0 + ## 0.20.0 (2022-04-20) ### Bug fixes diff --git a/package.json b/package.json index db5e312..656be0f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@codemirror/lang-python", - "version": "0.20.0", + "version": "6.0.0", "description": "Python language support for the CodeMirror code editor", "scripts": { "test": "cm-runtests", @@ -26,8 +26,8 @@ "sideEffects": false, "license": "MIT", "dependencies": { - "@codemirror/language": "^0.20.0", - "@lezer/python": "^0.16.0" + "@codemirror/language": "^6.0.0", + "@lezer/python": "^1.0.0" }, "devDependencies": { "@codemirror/buildhelper": "^0.1.0" From 9a16d237d36ace46b5c785f3f2cf93fdbb70756c Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 8 Jun 2022 10:02:41 +0200 Subject: [PATCH 28/63] Update website links in readme --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 3059c4a..e322f9e 100644 --- a/README.md +++ b/README.md @@ -2,14 +2,14 @@ # @codemirror/lang-python [![NPM version](https://img.shields.io/npm/v/@codemirror/lang-python.svg)](https://www.npmjs.org/package/@codemirror/lang-python) -[ [**WEBSITE**](https://codemirror.net/6/) | [**ISSUES**](https://github.com/codemirror/codemirror.next/issues) | [**FORUM**](https://discuss.codemirror.net/c/next/) | [**CHANGELOG**](https://github.com/codemirror/lang-python/blob/main/CHANGELOG.md) ] +[ [**WEBSITE**](https://codemirror.net/) | [**ISSUES**](https://github.com/codemirror/codemirror.next/issues) | [**FORUM**](https://discuss.codemirror.net/c/next/) | [**CHANGELOG**](https://github.com/codemirror/lang-python/blob/main/CHANGELOG.md) ] This package implements Python language support for the -[CodeMirror](https://codemirror.net/6/) code editor. +[CodeMirror](https://codemirror.net/) code editor. -The [project page](https://codemirror.net/6/) has more information, a -number of [examples](https://codemirror.net/6/examples/) and the -[documentation](https://codemirror.net/6/docs/). +The [project page](https://codemirror.net/) has more information, a +number of [examples](https://codemirror.net/examples/) and the +[documentation](https://codemirror.net/docs/). This code is released under an [MIT license](https://github.com/codemirror/lang-python/tree/main/LICENSE). @@ -22,12 +22,12 @@ to communication around the project. # API Reference
- python() → LanguageSupport
+ python() → LanguageSupport

Python language support.

- pythonLanguage: LezerLanguage
+ pythonLanguage: LezerLanguage

A language provider based on the Lezer Python parser, extended with From 8e5e499f5c1aa86c1932c0740d1599a52be035ff Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 8 Jun 2022 14:54:11 +0200 Subject: [PATCH 29/63] Follow repository rename --- .github/workflows/dispatch.yml | 2 +- README.md | 2 +- src/README.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/dispatch.yml b/.github/workflows/dispatch.yml index 9552050..d050072 100644 --- a/.github/workflows/dispatch.yml +++ b/.github/workflows/dispatch.yml @@ -11,6 +11,6 @@ jobs: with: # You should create a personal access token and store it in your repository token: ${{ secrets.DISPATCH_AUTH }} - repo: codemirror.next + repo: dev owner: codemirror event_type: push diff --git a/README.md b/README.md index e322f9e..388830b 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ # @codemirror/lang-python [![NPM version](https://img.shields.io/npm/v/@codemirror/lang-python.svg)](https://www.npmjs.org/package/@codemirror/lang-python) -[ [**WEBSITE**](https://codemirror.net/) | [**ISSUES**](https://github.com/codemirror/codemirror.next/issues) | [**FORUM**](https://discuss.codemirror.net/c/next/) | [**CHANGELOG**](https://github.com/codemirror/lang-python/blob/main/CHANGELOG.md) ] +[ [**WEBSITE**](https://codemirror.net/) | [**ISSUES**](https://github.com/codemirror/dev/issues) | [**FORUM**](https://discuss.codemirror.net/c/next/) | [**CHANGELOG**](https://github.com/codemirror/lang-python/blob/main/CHANGELOG.md) ] This package implements Python language support for the [CodeMirror](https://codemirror.net/) code editor. diff --git a/src/README.md b/src/README.md index 4fbafab..ea4b907 100644 --- a/src/README.md +++ b/src/README.md @@ -2,7 +2,7 @@ # @codemirror/lang-python [![NPM version](https://img.shields.io/npm/v/@codemirror/lang-python.svg)](https://www.npmjs.org/package/@codemirror/lang-python) -[ [**WEBSITE**](https://codemirror.net/6/) | [**ISSUES**](https://github.com/codemirror/codemirror.next/issues) | [**FORUM**](https://discuss.codemirror.net/c/next/) | [**CHANGELOG**](https://github.com/codemirror/lang-python/blob/main/CHANGELOG.md) ] +[ [**WEBSITE**](https://codemirror.net/6/) | [**ISSUES**](https://github.com/codemirror/dev/issues) | [**FORUM**](https://discuss.codemirror.net/c/next/) | [**CHANGELOG**](https://github.com/codemirror/lang-python/blob/main/CHANGELOG.md) ] This package implements Python language support for the [CodeMirror](https://codemirror.net/6/) code editor. From d9f9b1a443369f85409f999cf048d59f938eccc9 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 21 Jul 2022 11:13:49 +0200 Subject: [PATCH 30/63] Properly return null for indentation in template strings and comments FIX: Fix (non-)auto indentation in template strings and comments. Issue https://github.com/codemirror/dev/issues/909 --- src/python.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/python.ts b/src/python.ts index 5b43a02..f80c47a 100644 --- a/src/python.ts +++ b/src/python.ts @@ -34,6 +34,7 @@ export const pythonLanguage = LRLanguage.define({ "TupleExpression ComprehensionExpression ParamList ArgList ParenthesizedExpression": delimitedIndent({closing: ")"}), "DictionaryExpression DictionaryComprehensionExpression SetExpression SetComprehensionExpression": delimitedIndent({closing: "}"}), "ArrayExpression ArrayComprehensionExpression": delimitedIndent({closing: "]"}), + "String FormatString": () => null, Script: context => { if (context.pos + /\s*/.exec(context.textAfter)![0].length >= context.node.to) { let endBody = null From 57cc9c8d0d4224e6b4b928e9110f6debd4123aca Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 21 Jul 2022 14:06:30 +0200 Subject: [PATCH 31/63] Mark version 6.0.1 --- CHANGELOG.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a5197b..577cfc6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 6.0.1 (2022-07-21) + +### Bug fixes + +Fix (non-)auto indentation in template strings and comments. + ## 6.0.0 (2022-06-08) ### Breaking changes diff --git a/package.json b/package.json index 656be0f..ff39bd6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@codemirror/lang-python", - "version": "6.0.0", + "version": "6.0.1", "description": "Python language support for the CodeMirror code editor", "scripts": { "test": "cm-runtests", From a2115adcf9b1d70ab0e335a1eeae2d9ea1a2dfbc Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 22 Sep 2022 13:04:30 +0200 Subject: [PATCH 32/63] Add string prefix metadata FIX: Allow prefixed strings to be closed by `closeBrackets`. --- src/python.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/python.ts b/src/python.ts index f80c47a..f68b5a5 100644 --- a/src/python.ts +++ b/src/python.ts @@ -58,7 +58,11 @@ export const pythonLanguage = LRLanguage.define({ ], }), languageData: { - closeBrackets: {brackets: ["(", "[", "{", "'", '"', "'''", '"""']}, + closeBrackets: { + brackets: ["(", "[", "{", "'", '"', "'''", '"""'], + stringPrefixes: ["f", "fr", "rf", "r", "u", "b", "br", "rb", + "F", "FR", "RF", "R", "U", "B", "BR", "RB"] + }, commentTokens: {line: "#"}, indentOnInput: /^\s*([\}\]\)]|else:|elif |except |finally:)$/ } From e92951d84f1b5dcaaa6b4bd5cecb72f72791cbbc Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 22 Sep 2022 17:04:22 +0200 Subject: [PATCH 33/63] Mark version 6.0.2 --- CHANGELOG.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 577cfc6..6e2649e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 6.0.2 (2022-09-22) + +### Bug fixes + +Allow prefixed strings to be closed by `closeBrackets`. + ## 6.0.1 (2022-07-21) ### Bug fixes diff --git a/package.json b/package.json index ff39bd6..976b77b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@codemirror/lang-python", - "version": "6.0.1", + "version": "6.0.2", "description": "Python language support for the CodeMirror code editor", "scripts": { "test": "cm-runtests", From 9da3502f4c4bcbf7d8556941f3c77c6c59a9479c Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 19 Oct 2022 18:08:58 +0200 Subject: [PATCH 34/63] Properly indent else clauses in try statements FIX: Add proper indentation handling of `else` clauses in `try` statements. Closes https://github.com/codemirror/dev/issues/976 --- src/python.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/python.ts b/src/python.ts index f68b5a5..5a88892 100644 --- a/src/python.ts +++ b/src/python.ts @@ -30,7 +30,7 @@ export const pythonLanguage = LRLanguage.define({ indentNodeProp.add({ Body: context => indentBody(context, context.node) ?? context.continue(), IfStatement: cx => /^\s*(else:|elif )/.test(cx.textAfter) ? cx.baseIndent : cx.continue(), - TryStatement: cx => /^\s*(except |finally:)/.test(cx.textAfter) ? cx.baseIndent : cx.continue(), + TryStatement: cx => /^\s*(except |finally:|else:)/.test(cx.textAfter) ? cx.baseIndent : cx.continue(), "TupleExpression ComprehensionExpression ParamList ArgList ParenthesizedExpression": delimitedIndent({closing: ")"}), "DictionaryExpression DictionaryComprehensionExpression SetExpression SetComprehensionExpression": delimitedIndent({closing: "}"}), "ArrayExpression ArrayComprehensionExpression": delimitedIndent({closing: "]"}), From fa5898af9a71c747cb00dc22152c621eb7bf419a Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 19 Oct 2022 18:09:08 +0200 Subject: [PATCH 35/63] Mark version 6.0.3 --- CHANGELOG.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e2649e..5ac81b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 6.0.3 (2022-10-19) + +### Bug fixes + +Add proper indentation handling of `else` clauses in `try` statements. + ## 6.0.2 (2022-09-22) ### Bug fixes diff --git a/package.json b/package.json index 976b77b..da59a2e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@codemirror/lang-python", - "version": "6.0.2", + "version": "6.0.3", "description": "Python language support for the CodeMirror code editor", "scripts": { "test": "cm-runtests", From 4d019e554c8067252fd133bb1f2c4abeeca9a5c3 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 24 Oct 2022 13:56:15 +0200 Subject: [PATCH 36/63] Define a language name FIX: Make sure the language object has a name. --- src/python.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/python.ts b/src/python.ts index 5a88892..8067085 100644 --- a/src/python.ts +++ b/src/python.ts @@ -25,6 +25,7 @@ function indentBody(context: TreeIndentContext, node: SyntaxNode) { /// parser](https://github.com/lezer-parser/python), extended with /// highlighting and indentation information. export const pythonLanguage = LRLanguage.define({ + name: "python", parser: parser.configure({ props: [ indentNodeProp.add({ From bbb33acee911b2296e8a330f25939b5570c2ead1 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 24 Oct 2022 13:56:20 +0200 Subject: [PATCH 37/63] Mark version 6.0.4 --- CHANGELOG.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ac81b0..b85d15d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 6.0.4 (2022-10-24) + +### Bug fixes + +Make sure the language object has a name. + ## 6.0.3 (2022-10-19) ### Bug fixes diff --git a/package.json b/package.json index da59a2e..6612396 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@codemirror/lang-python", - "version": "6.0.3", + "version": "6.0.4", "description": "Python language support for the CodeMirror code editor", "scripts": { "test": "cm-runtests", From 3926dd85711899e6cc2048db00f74322a0e40cab Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Fri, 18 Nov 2022 18:57:10 +0100 Subject: [PATCH 38/63] Add autocompletion support FEATURE: The `globalCompletion` completion source (included in the language support returned from `python()`) completes standard Python globals and keywords. FEATURE: Export a `localCompletionSource` function that completes locally defined variables. Included in the support extensions returned from `python()`. --- package.json | 1 + src/complete.ts | 189 ++++++++++++++++++++++++++++++++++++++++++++++++ src/python.ts | 7 +- 3 files changed, 196 insertions(+), 1 deletion(-) create mode 100644 src/complete.ts diff --git a/package.json b/package.json index 6612396..862dc2d 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "sideEffects": false, "license": "MIT", "dependencies": { + "@codemirror/autocomplete": "^6.3.2", "@codemirror/language": "^6.0.0", "@lezer/python": "^1.0.0" }, diff --git a/src/complete.ts b/src/complete.ts new file mode 100644 index 0000000..ef9d76a --- /dev/null +++ b/src/complete.ts @@ -0,0 +1,189 @@ +import {NodeWeakMap, SyntaxNodeRef, SyntaxNode, IterMode} from "@lezer/common" +import {Completion, CompletionContext, CompletionResult, completeFromList, ifNotIn, + snippetCompletion as snip} from "@codemirror/autocomplete" +import {syntaxTree} from "@codemirror/language" +import {Text} from "@codemirror/state" + +const cache = new NodeWeakMap() + +const ScopeNodes = new Set([ + "Script", "Body", + "FunctionDefinition", "ClassDefinition", "LambdaExpression", + "ForStatement", "MatchClause" +]) + +function defID(type: string) { + return (node: SyntaxNodeRef, def: (node: SyntaxNodeRef, type: string) => void, outer: boolean) => { + if (outer) return false + let id = node.node.getChild("VariableName") + if (id) def(id, type) + return true + } +} + +const gatherCompletions: { + [node: string]: (node: SyntaxNodeRef, def: (node: SyntaxNodeRef, type: string) => void, outer: boolean) => void | boolean +} = { + FunctionDefinition: defID("function"), + ClassDefinition: defID("class"), + ForStatement(node, def, outer) { + if (outer) for (let child = node.node.firstChild; child; child = child.nextSibling) { + if (child.name == "VariableName") def(child, "variable") + else if (child.name == "in") break + } + }, + ImportStatement(_node, def) { + let {node} = _node + let isFrom = node.firstChild?.name == "from" + for (let ch = node.getChild("import"); ch; ch = ch.nextSibling) { + if (ch.name == "VariableName" && ch.nextSibling?.name != "as") + def(ch, isFrom ? "variable" : "namespace") + } + }, + AssignStatement(node, def) { + for (let child = node.node.firstChild; child; child = child.nextSibling) { + if (child.name == "VariableName") def(child, "variable") + else if (child.name == ":" || child.name == "AssignOp") break + } + }, + ParamList(node, def) { + for (let prev = null, child = node.node.firstChild; child; child = child.nextSibling) { + if (child.name == "VariableName" && (!prev || !/\*|AssignOp/.test(prev.name))) + def(child, "variable") + prev = child + } + }, + CapturePattern: defID("variable"), + AsPattern: defID("variable"), + __proto__: null as any +} + +function getScope(doc: Text, node: SyntaxNode) { + let cached = cache.get(node) + if (cached) return cached + + console.log("get scope for", node.name) + let completions: Completion[] = [], top = true + function def(node: SyntaxNodeRef, type: string) { + let name = doc.sliceString(node.from, node.to) + completions.push({label: name, type}) + } + node.cursor(IterMode.IncludeAnonymous).iterate(node => { + if (node.name) { + let gather = gatherCompletions[node.name] + if (gather && gather(node, def, top) || !top && ScopeNodes.has(node.name)) return console.log("bail for", node.name), false + top = false + } else if (node.to - node.from > 8192) { + // Allow caching for bigger internal nodes + for (let c of getScope(doc, node.node)) completions.push(c) + return false + } + }) + cache.set(node, completions) + return completions +} + +const Identifier = /^[\w\xa1-\uffff][\w\d\xa1-\uffff]*$/ + +const dontComplete = ["String", "FormatString", "Comment", "PropertyName"] + +/// Completion source that looks up locally defined names in +/// Python code. +export function localCompletionSource(context: CompletionContext): CompletionResult | null { + let inner = syntaxTree(context.state).resolveInner(context.pos, -1) + if (dontComplete.indexOf(inner.name) > -1) return null + let isWord = inner.name == "VariableName" || + inner.to - inner.from < 20 && Identifier.test(context.state.sliceDoc(inner.from, inner.to)) + if (!isWord && !context.explicit) return null + let options: Completion[] = [] + for (let pos: SyntaxNode | null = inner; pos; pos = pos.parent) { + if (ScopeNodes.has(pos.name)) options = options.concat(getScope(context.state.doc, pos)) + } + return { + options, + from: isWord ? inner.from : context.pos, + validFor: Identifier + } +} + +const globals: readonly Completion[] = [ + "__annotations__", "__builtins__", "__debug__", "__doc__", "__import__", "__name__", + "__loader__", "__package__", "__spec__", + "False", "None", "True" +].map(n => ({label: n, type: "constant"})).concat([ + "ArithmeticError", "AssertionError", "AttributeError", "BaseException", "BlockingIOError", + "BrokenPipeError", "BufferError", "BytesWarning", "ChildProcessError", "ConnectionAbortedError", + "ConnectionError", "ConnectionRefusedError", "ConnectionResetError", "DeprecationWarning", + "EOFError", "Ellipsis", "EncodingWarning", "EnvironmentError", "Exception", "FileExistsError", + "FileNotFoundError", "FloatingPointError", "FutureWarning", "GeneratorExit", "IOError", + "ImportError", "ImportWarning", "IndentationError", "IndexError", "InterruptedError", + "IsADirectoryError", "KeyError", "KeyboardInterrupt", "LookupError", "MemoryError", + "ModuleNotFoundError", "NameError", "NotADirectoryError", "NotImplemented", "NotImplementedError", + "OSError", "OverflowError", "PendingDeprecationWarning", "PermissionError", "ProcessLookupError", + "RecursionError", "ReferenceError", "ResourceWarning", "RuntimeError", "RuntimeWarning", + "StopAsyncIteration", "StopIteration", "SyntaxError", "SyntaxWarning", "SystemError", + "SystemExit", "TabError", "TimeoutError", "TypeError", "UnboundLocalError", "UnicodeDecodeError", + "UnicodeEncodeError", "UnicodeError", "UnicodeTranslateError", "UnicodeWarning", "UserWarning", + "ValueError", "Warning", "ZeroDivisionError" +].map(n => ({label: n, type: "type"}))).concat([ + "bool", "bytearray", "bytes", "classmethod", "complex", "float", "frozenset", "int", "list", + "map", "memoryview", "object", "range", "set", "staticmethod", "str", "super", "tuple", "type" +].map(n => ({label: n, type: "class"}))).concat([ + "abs", "aiter", "all", "anext", "any", "ascii", "bin", "breakpoint", "callable", "chr", + "compile", "delattr", "dict", "dir", "divmod", "enumerate", "eval", "exec", "exit", "filter", + "format", "getattr", "globals", "hasattr", "hash", "help", "hex", "id", "input", "isinstance", + "issubclass", "iter", "len", "license", "locals", "max", "min", "next", "oct", "open", + "ord", "pow", "print", "property", "quit", "repr", "reversed", "round", "setattr", "slice", + "sorted", "sum", "vars", "zip" +].map(n => ({label: n, type: "function"}))) + +export const snippets: readonly Completion[] = [ + snip("def ${name}(${params}):\n\t${}", { + label: "def", + detail: "function", + type: "keyword" + }), + snip("for ${name} in ${collection}:\n\t${}", { + label: "for", + detail: "loop", + type: "keyword" + }), + snip("while ${}:\n\t${}", { + label: "while", + detail: "loop", + type: "keyword" + }), + snip("try:\n\t${}\nexcept ${error}:\n\t${}", { + label: "try", + detail: "/ except block", + type: "keyword" + }), + snip("if ${}:\n\t\n", { + label: "if", + detail: "block", + type: "keyword" + }), + snip("if ${}:\n\t${}\nelse:\n\t${}", { + label: "if", + detail: "/ else block", + type: "keyword" + }), + snip("class ${name}:\n\tdef __init__(self, ${params}):\n\t\t\t${}", { + label: "class", + detail: "definition", + type: "keyword" + }), + snip("import ${module}", { + label: "import", + detail: "statement", + type: "keyword" + }), + snip("from ${module} import ${names}", { + label: "from", + detail: "import", + type: "keyword" + }) +] + +/// Autocompletion for built-in Python globals and keywords. +export const globalCompletion = ifNotIn(dontComplete, completeFromList(globals.concat(snippets))) diff --git a/src/python.ts b/src/python.ts index 8067085..1deaafb 100644 --- a/src/python.ts +++ b/src/python.ts @@ -2,6 +2,8 @@ import {parser} from "@lezer/python" import {SyntaxNode} from "@lezer/common" import {delimitedIndent, indentNodeProp, TreeIndentContext, foldNodeProp, foldInside, LRLanguage, LanguageSupport} from "@codemirror/language" +import {globalCompletion, localCompletionSource} from "./complete" +export {globalCompletion, localCompletionSource} function indentBody(context: TreeIndentContext, node: SyntaxNode) { let base = context.lineIndent(node.from) @@ -71,5 +73,8 @@ export const pythonLanguage = LRLanguage.define({ /// Python language support. export function python() { - return new LanguageSupport(pythonLanguage) + return new LanguageSupport(pythonLanguage, [ + pythonLanguage.data.of({autocomplete: localCompletionSource}), + pythonLanguage.data.of({autocomplete: globalCompletion}), + ]) } From 53af280c20e61ed34cff33aece8c6a3eee7f316b Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Fri, 18 Nov 2022 18:57:53 +0100 Subject: [PATCH 39/63] Mark version 6.1.0 --- CHANGELOG.md | 8 ++++++++ package.json | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b85d15d..5289513 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## 6.1.0 (2022-11-18) + +### New features + +The `globalCompletion` completion source (included in the language support returned from `python()`) completes standard Python globals and keywords. + +Export a `localCompletionSource` function that completes locally defined variables. Included in the support extensions returned from `python()`. + ## 6.0.4 (2022-10-24) ### Bug fixes diff --git a/package.json b/package.json index 862dc2d..39578e5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@codemirror/lang-python", - "version": "6.0.4", + "version": "6.1.0", "description": "Python language support for the CodeMirror code editor", "scripts": { "test": "cm-runtests", From eda7b8aa4f11e8bdf016cae618f4c7cdfabedbc6 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Sat, 24 Dec 2022 14:02:55 +0100 Subject: [PATCH 40/63] Remove debug statements FIX: Remove leftover log statements. Closes https://github.com/codemirror/dev/issues/1043 --- src/complete.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/complete.ts b/src/complete.ts index ef9d76a..8bcc566 100644 --- a/src/complete.ts +++ b/src/complete.ts @@ -62,7 +62,6 @@ function getScope(doc: Text, node: SyntaxNode) { let cached = cache.get(node) if (cached) return cached - console.log("get scope for", node.name) let completions: Completion[] = [], top = true function def(node: SyntaxNodeRef, type: string) { let name = doc.sliceString(node.from, node.to) @@ -71,7 +70,7 @@ function getScope(doc: Text, node: SyntaxNode) { node.cursor(IterMode.IncludeAnonymous).iterate(node => { if (node.name) { let gather = gatherCompletions[node.name] - if (gather && gather(node, def, top) || !top && ScopeNodes.has(node.name)) return console.log("bail for", node.name), false + if (gather && gather(node, def, top) || !top && ScopeNodes.has(node.name)) return false top = false } else if (node.to - node.from > 8192) { // Allow caching for bigger internal nodes From d213e1ec9a483899c41712ed3dd805dbe436d15a Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Sat, 24 Dec 2022 14:02:58 +0100 Subject: [PATCH 41/63] Mark version 6.1.1 --- CHANGELOG.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5289513..eabdb6c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 6.1.1 (2022-12-24) + +### Bug fixes + +Remove leftover log statements. + ## 6.1.0 (2022-11-18) ### New features diff --git a/package.json b/package.json index 39578e5..35c1b7f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@codemirror/lang-python", - "version": "6.1.0", + "version": "6.1.1", "description": "Python language support for the CodeMirror code editor", "scripts": { "test": "cm-runtests", From 11ec1932249a9170c5a0dce11b3df23ab70dd66b Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 24 Jan 2023 08:20:09 +0100 Subject: [PATCH 42/63] Update maintainer email --- LICENSE | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/LICENSE b/LICENSE index 3af12e6..9a91f48 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (C) 2018-2021 by Marijn Haverbeke and others +Copyright (C) 2018-2021 by Marijn Haverbeke and others Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/package.json b/package.json index 35c1b7f..66e1814 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ ], "author": { "name": "Marijn Haverbeke", - "email": "marijnh@gmail.com", + "email": "marijn@haverbeke.berlin", "url": "http://marijnhaverbeke.nl" }, "type": "module", From bcd3f34146b1246086b5155d698df1d04a7e7b8f Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 20 Feb 2023 09:42:39 +0100 Subject: [PATCH 43/63] Regenerate readme --- README.md | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 388830b..f734608 100644 --- a/README.md +++ b/README.md @@ -2,14 +2,14 @@ # @codemirror/lang-python [![NPM version](https://img.shields.io/npm/v/@codemirror/lang-python.svg)](https://www.npmjs.org/package/@codemirror/lang-python) -[ [**WEBSITE**](https://codemirror.net/) | [**ISSUES**](https://github.com/codemirror/dev/issues) | [**FORUM**](https://discuss.codemirror.net/c/next/) | [**CHANGELOG**](https://github.com/codemirror/lang-python/blob/main/CHANGELOG.md) ] +[ [**WEBSITE**](https://codemirror.net/6/) | [**ISSUES**](https://github.com/codemirror/dev/issues) | [**FORUM**](https://discuss.codemirror.net/c/next/) | [**CHANGELOG**](https://github.com/codemirror/lang-python/blob/main/CHANGELOG.md) ] This package implements Python language support for the -[CodeMirror](https://codemirror.net/) code editor. +[CodeMirror](https://codemirror.net/6/) code editor. -The [project page](https://codemirror.net/) has more information, a -number of [examples](https://codemirror.net/examples/) and the -[documentation](https://codemirror.net/docs/). +The [project page](https://codemirror.net/6/) has more information, a +number of [examples](https://codemirror.net/6/examples/) and the +[documentation](https://codemirror.net/6/docs/). This code is released under an [MIT license](https://github.com/codemirror/lang-python/tree/main/LICENSE). @@ -20,17 +20,29 @@ conduct](http://contributor-covenant.org/version/1/1/0/) that applies to communication around the project. # API Reference +

-
- python() → LanguageSupport
+
+ globalCompletion: CompletionSource
-

Python language support.

+

Autocompletion for built-in Python globals and keywords.

+
+
+ localCompletionSource(contextCompletionContext) → CompletionResult | null
+ +

Completion source that looks up locally defined names in +Python code.

- pythonLanguage: LezerLanguage
+ pythonLanguage: LRLanguage

A language provider based on the Lezer Python parser, extended with highlighting and indentation information.

-
+
+ python() → LanguageSupport
+ +

Python language support.

+
+
\ No newline at end of file From 5bd357c723462b6605bd3dec6b5f0203344b7d8e Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 20 Feb 2023 09:49:46 +0100 Subject: [PATCH 44/63] Update links in readme --- README.md | 10 +++++----- src/README.md | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index f734608..91eed62 100644 --- a/README.md +++ b/README.md @@ -2,14 +2,14 @@ # @codemirror/lang-python [![NPM version](https://img.shields.io/npm/v/@codemirror/lang-python.svg)](https://www.npmjs.org/package/@codemirror/lang-python) -[ [**WEBSITE**](https://codemirror.net/6/) | [**ISSUES**](https://github.com/codemirror/dev/issues) | [**FORUM**](https://discuss.codemirror.net/c/next/) | [**CHANGELOG**](https://github.com/codemirror/lang-python/blob/main/CHANGELOG.md) ] +[ [**WEBSITE**](https://codemirror.net/) | [**ISSUES**](https://github.com/codemirror/dev/issues) | [**FORUM**](https://discuss.codemirror.net/c/next/) | [**CHANGELOG**](https://github.com/codemirror/lang-python/blob/main/CHANGELOG.md) ] This package implements Python language support for the -[CodeMirror](https://codemirror.net/6/) code editor. +[CodeMirror](https://codemirror.net/) code editor. -The [project page](https://codemirror.net/6/) has more information, a -number of [examples](https://codemirror.net/6/examples/) and the -[documentation](https://codemirror.net/6/docs/). +The [project page](https://codemirror.net/) has more information, a +number of [examples](https://codemirror.net/examples/) and the +[documentation](https://codemirror.net/docs/). This code is released under an [MIT license](https://github.com/codemirror/lang-python/tree/main/LICENSE). diff --git a/src/README.md b/src/README.md index ea4b907..c3c7d2e 100644 --- a/src/README.md +++ b/src/README.md @@ -2,14 +2,14 @@ # @codemirror/lang-python [![NPM version](https://img.shields.io/npm/v/@codemirror/lang-python.svg)](https://www.npmjs.org/package/@codemirror/lang-python) -[ [**WEBSITE**](https://codemirror.net/6/) | [**ISSUES**](https://github.com/codemirror/dev/issues) | [**FORUM**](https://discuss.codemirror.net/c/next/) | [**CHANGELOG**](https://github.com/codemirror/lang-python/blob/main/CHANGELOG.md) ] +[ [**WEBSITE**](https://codemirror.net/) | [**ISSUES**](https://github.com/codemirror/dev/issues) | [**FORUM**](https://discuss.codemirror.net/c/next/) | [**CHANGELOG**](https://github.com/codemirror/lang-python/blob/main/CHANGELOG.md) ] This package implements Python language support for the -[CodeMirror](https://codemirror.net/6/) code editor. +[CodeMirror](https://codemirror.net/) code editor. -The [project page](https://codemirror.net/6/) has more information, a -number of [examples](https://codemirror.net/6/examples/) and the -[documentation](https://codemirror.net/6/docs/). +The [project page](https://codemirror.net/) has more information, a +number of [examples](https://codemirror.net/examples/) and the +[documentation](https://codemirror.net/docs/). This code is released under an [MIT license](https://github.com/codemirror/lang-python/tree/main/LICENSE). From e4e2540c4acbc40d055c08c4bdf0f79b78dcf1ed Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 28 Feb 2023 10:25:05 +0100 Subject: [PATCH 45/63] Don't indent for blocks that end in a deindented comment line FIX: Don't indent lines after a dedented comment line. Closes https://github.com/codemirror/dev/issues/1094 --- src/python.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/python.ts b/src/python.ts index 1deaafb..1cacfa8 100644 --- a/src/python.ts +++ b/src/python.ts @@ -10,7 +10,7 @@ function indentBody(context: TreeIndentContext, node: SyntaxNode) { let line = context.lineAt(context.pos, -1), to = line.from + line.text.length // Don't consider blank, deindented lines at the end of the // block part of the block - if (!/\S/.test(line.text) && + if (/^\s*($|#)/.test(line.text) && context.node.to < to + 100 && !/\S/.test(context.state.sliceDoc(to, context.node.to)) && context.lineIndent(context.pos, -1) <= base) From 8b033f0aed777b9eda0307cf5d1e492040fc9c1c Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 1 Mar 2023 09:14:17 +0100 Subject: [PATCH 46/63] Mark version 6.1.2 --- CHANGELOG.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index eabdb6c..2d897e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 6.1.2 (2023-03-01) + +### Bug fixes + +Don't indent lines after a dedented comment line. + ## 6.1.1 (2022-12-24) ### Bug fixes diff --git a/package.json b/package.json index 66e1814..1552f89 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@codemirror/lang-python", - "version": "6.1.1", + "version": "6.1.2", "description": "Python language support for the CodeMirror code editor", "scripts": { "test": "cm-runtests", From 1f8d660b515672748f066038a972dfc4b72726b9 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 30 Mar 2023 13:44:16 +0200 Subject: [PATCH 47/63] Remove a kludge made unnecessary by an upstream change --- package.json | 2 +- src/python.ts | 8 -------- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/package.json b/package.json index 1552f89..8ac1a20 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "dependencies": { "@codemirror/autocomplete": "^6.3.2", "@codemirror/language": "^6.0.0", - "@lezer/python": "^1.0.0" + "@lezer/python": "^1.1.4" }, "devDependencies": { "@codemirror/buildhelper": "^0.1.0" diff --git a/src/python.ts b/src/python.ts index 1cacfa8..2d500b5 100644 --- a/src/python.ts +++ b/src/python.ts @@ -7,14 +7,6 @@ export {globalCompletion, localCompletionSource} function indentBody(context: TreeIndentContext, node: SyntaxNode) { let base = context.lineIndent(node.from) - let line = context.lineAt(context.pos, -1), to = line.from + line.text.length - // Don't consider blank, deindented lines at the end of the - // block part of the block - if (/^\s*($|#)/.test(line.text) && - context.node.to < to + 100 && - !/\S/.test(context.state.sliceDoc(to, context.node.to)) && - context.lineIndent(context.pos, -1) <= base) - return null // A normally deindenting keyword that appears at a higher // indentation than the block should probably be handled by the next // level From 1fe52ea9e286980aee63918b8b417a6f69325d7b Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 30 Mar 2023 14:31:48 +0200 Subject: [PATCH 48/63] Restore removed code Seems it did more than I thought --- src/python.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/python.ts b/src/python.ts index 2d500b5..1cacfa8 100644 --- a/src/python.ts +++ b/src/python.ts @@ -7,6 +7,14 @@ export {globalCompletion, localCompletionSource} function indentBody(context: TreeIndentContext, node: SyntaxNode) { let base = context.lineIndent(node.from) + let line = context.lineAt(context.pos, -1), to = line.from + line.text.length + // Don't consider blank, deindented lines at the end of the + // block part of the block + if (/^\s*($|#)/.test(line.text) && + context.node.to < to + 100 && + !/\S/.test(context.state.sliceDoc(to, context.node.to)) && + context.lineIndent(context.pos, -1) <= base) + return null // A normally deindenting keyword that appears at a higher // indentation than the block should probably be handled by the next // level From 73a4909277e25e706365f04be4de31b7ef7f6e20 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 25 May 2023 12:15:05 +0200 Subject: [PATCH 49/63] Move to @codemirror/buildhelper 1.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8ac1a20..6eca967 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "@lezer/python": "^1.1.4" }, "devDependencies": { - "@codemirror/buildhelper": "^0.1.0" + "@codemirror/buildhelper": "^1.0.0" }, "repository": { "type": "git", From b9203eec74b8f4cd877b7fbf2a024b7a4b761727 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 12 Jun 2023 08:04:35 +0200 Subject: [PATCH 50/63] Properly determine a base indentation when indenting a block FIX: Fix a bug where blocks started after a wrapped argument list or similar construct were indented too far. Closes https://github.com/codemirror/dev/issues/1182 --- package.json | 2 +- src/python.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 6eca967..bf62251 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "license": "MIT", "dependencies": { "@codemirror/autocomplete": "^6.3.2", - "@codemirror/language": "^6.0.0", + "@codemirror/language": "^6.8.0", "@lezer/python": "^1.1.4" }, "devDependencies": { diff --git a/src/python.ts b/src/python.ts index 1cacfa8..9c545e1 100644 --- a/src/python.ts +++ b/src/python.ts @@ -6,7 +6,7 @@ import {globalCompletion, localCompletionSource} from "./complete" export {globalCompletion, localCompletionSource} function indentBody(context: TreeIndentContext, node: SyntaxNode) { - let base = context.lineIndent(node.from) + let base = context.baseIndentFor(node) let line = context.lineAt(context.pos, -1), to = line.from + line.text.length // Don't consider blank, deindented lines at the end of the // block part of the block From d87154ec7014063e6c7e0dfe16c2a7be93471114 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 12 Jun 2023 08:04:43 +0200 Subject: [PATCH 51/63] Mark version 6.1.3 --- CHANGELOG.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d897e5..1987b4e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 6.1.3 (2023-06-12) + +### Bug fixes + +Fix a bug where blocks started after a wrapped argument list or similar construct were indented too far. + ## 6.1.2 (2023-03-01) ### Bug fixes diff --git a/package.json b/package.json index bf62251..9b4d904 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@codemirror/lang-python", - "version": "6.1.2", + "version": "6.1.3", "description": "Python language support for the CodeMirror code editor", "scripts": { "test": "cm-runtests", From 6676fd517325a04d8d03fbbc2e903242d1d45996 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Fri, 2 Feb 2024 22:25:14 +0100 Subject: [PATCH 52/63] Declare missing dependencies FIX: Explicitly declare dependencies on @lezer/common and @codemirror/state Closes https://github.com/codemirror/lang-liquid/issues/3 --- package.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/package.json b/package.json index 9b4d904..2c71a39 100644 --- a/package.json +++ b/package.json @@ -26,8 +26,10 @@ "sideEffects": false, "license": "MIT", "dependencies": { + "@codemirror/state": "^6.0.0", "@codemirror/autocomplete": "^6.3.2", "@codemirror/language": "^6.8.0", + "@lezer/common": "^1.2.1", "@lezer/python": "^1.1.4" }, "devDependencies": { From ce4804b2163180989a95d368ffdfa68d48f8d991 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Fri, 2 Feb 2024 22:25:25 +0100 Subject: [PATCH 53/63] Mark version 6.1.4 --- CHANGELOG.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1987b4e..9db5c95 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 6.1.4 (2024-02-02) + +### Bug fixes + +Explicitly declare dependencies on @lezer/common and @codemirror/state + ## 6.1.3 (2023-06-12) ### Bug fixes diff --git a/package.json b/package.json index 2c71a39..efa4ad8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@codemirror/lang-python", - "version": "6.1.3", + "version": "6.1.4", "description": "Python language support for the CodeMirror code editor", "scripts": { "test": "cm-runtests", From 0cf35932e6706d371bde5d5e8464172b2ad61164 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 28 Mar 2024 22:13:58 +0100 Subject: [PATCH 54/63] Improve indentation of else line under for/while loops FIX: Properly indent `else:` when attached to a `for` or `while` statement. Closes https://github.com/codemirror/dev/issues/1363 --- src/python.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/python.ts b/src/python.ts index 9c545e1..000fda2 100644 --- a/src/python.ts +++ b/src/python.ts @@ -33,6 +33,7 @@ export const pythonLanguage = LRLanguage.define({ indentNodeProp.add({ Body: context => indentBody(context, context.node) ?? context.continue(), IfStatement: cx => /^\s*(else:|elif )/.test(cx.textAfter) ? cx.baseIndent : cx.continue(), + "ForStatement WhileStatement": cx => /^\s*else:/.test(cx.textAfter) ? cx.baseIndent : cx.continue(), TryStatement: cx => /^\s*(except |finally:|else:)/.test(cx.textAfter) ? cx.baseIndent : cx.continue(), "TupleExpression ComprehensionExpression ParamList ArgList ParenthesizedExpression": delimitedIndent({closing: ")"}), "DictionaryExpression DictionaryComprehensionExpression SetExpression SetComprehensionExpression": delimitedIndent({closing: "}"}), From cc69f687f582366af5245472a775351d0fcb8f48 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 28 Mar 2024 22:14:10 +0100 Subject: [PATCH 55/63] Mark version 6.1.5 --- CHANGELOG.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9db5c95..234cab8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 6.1.5 (2024-03-28) + +### Bug fixes + +Properly indent `else:` when attached to a `for` or `while` statement. + ## 6.1.4 (2024-02-02) ### Bug fixes diff --git a/package.json b/package.json index efa4ad8..ed0eafe 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@codemirror/lang-python", - "version": "6.1.4", + "version": "6.1.5", "description": "Python language support for the CodeMirror code editor", "scripts": { "test": "cm-runtests", From 0468622ddfee9c2a0011544c8f3128749b714168 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 29 Apr 2024 13:41:13 +0200 Subject: [PATCH 56/63] Base continued body in indentation on the indentation of the line before FIX: Improve the way indentation for the current body is preserved when inenting new lines. Issue https://github.com/codemirror/dev/issues/1370 --- src/python.ts | 42 ++++++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/src/python.ts b/src/python.ts index 000fda2..97f5bd6 100644 --- a/src/python.ts +++ b/src/python.ts @@ -5,6 +5,28 @@ import {delimitedIndent, indentNodeProp, TreeIndentContext, import {globalCompletion, localCompletionSource} from "./complete" export {globalCompletion, localCompletionSource} +function innerBody(context: TreeIndentContext) { + let {node, pos} = context + let lineIndent = context.lineIndent(pos, -1) + let found = null + for (;;) { + let before = node.childBefore(pos) + if (!before) { + break + } else if (before.name == "Comment") { + pos = before.from + } else if (before.name == "Body") { + if (context.baseIndentFor(before) + context.unit <= lineIndent) found = before + node = before + } else if (before.type.is("Statement")) { + node = before + } else { + break + } + } + return found +} + function indentBody(context: TreeIndentContext, node: SyntaxNode) { let base = context.baseIndentFor(node) let line = context.lineAt(context.pos, -1), to = line.from + line.text.length @@ -31,7 +53,10 @@ export const pythonLanguage = LRLanguage.define({ parser: parser.configure({ props: [ indentNodeProp.add({ - Body: context => indentBody(context, context.node) ?? context.continue(), + Body: context => { + let inner = innerBody(context) + return indentBody(context, inner || context.node) ?? context.continue() + }, IfStatement: cx => /^\s*(else:|elif )/.test(cx.textAfter) ? cx.baseIndent : cx.continue(), "ForStatement WhileStatement": cx => /^\s*else:/.test(cx.textAfter) ? cx.baseIndent : cx.continue(), TryStatement: cx => /^\s*(except |finally:|else:)/.test(cx.textAfter) ? cx.baseIndent : cx.continue(), @@ -40,19 +65,8 @@ export const pythonLanguage = LRLanguage.define({ "ArrayExpression ArrayComprehensionExpression": delimitedIndent({closing: "]"}), "String FormatString": () => null, Script: context => { - if (context.pos + /\s*/.exec(context.textAfter)![0].length >= context.node.to) { - let endBody = null - for (let cur: SyntaxNode | null = context.node, to = cur.to;;) { - cur = cur.lastChild - if (!cur || cur.to != to) break - if (cur.type.name == "Body") endBody = cur - } - if (endBody) { - let bodyIndent = indentBody(context, endBody) - if (bodyIndent != null) return bodyIndent - } - } - return context.continue() + let inner = innerBody(context) + return (inner && indentBody(context, inner)) ?? context.continue() } }), foldNodeProp.add({ From 83ed6b3ee13b6d65755ade185a018d469721210c Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 29 Apr 2024 17:52:39 +0200 Subject: [PATCH 57/63] Mark version 6.1.6 --- CHANGELOG.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 234cab8..2e0327e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 6.1.6 (2024-04-29) + +### Bug fixes + +Improve the way indentation for the current body is preserved when inenting new lines. + ## 6.1.5 (2024-03-28) ### Bug fixes diff --git a/package.json b/package.json index ed0eafe..5bf17ed 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@codemirror/lang-python", - "version": "6.1.5", + "version": "6.1.6", "description": "Python language support for the CodeMirror code editor", "scripts": { "test": "cm-runtests", From fec0c165b508ae5f862019cdcf2c2ec3c8bf83e8 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 30 Dec 2024 20:07:12 +0100 Subject: [PATCH 58/63] Add a usage section to readme --- README.md | 39 ++++++++++++++++++++++++++------------- src/README.md | 19 ++++++++++++++++++- 2 files changed, 44 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 91eed62..7356dae 100644 --- a/README.md +++ b/README.md @@ -19,19 +19,26 @@ we have a [code of conduct](http://contributor-covenant.org/version/1/1/0/) that applies to communication around the project. +## Usage + +```javascript +import {EditorView, basicSetup} from "codemirror" +import {python} from "@codemirror/lang-python" + +const view = new EditorView({ + parent: document.body, + doc: `print("Hello world")`, + extensions: [basicSetup, python()] +}) +``` + # API Reference
-
- globalCompletion: CompletionSource
- -

Autocompletion for built-in Python globals and keywords.

-
-
- localCompletionSource(contextCompletionContext) → CompletionResult | null
+
+ python() → LanguageSupport
-

Completion source that looks up locally defined names in -Python code.

+

Python language support.

pythonLanguage: LRLanguage
@@ -40,9 +47,15 @@ Python code.

parser, extended with highlighting and indentation information.

-
- python() → LanguageSupport
+
+ globalCompletion: CompletionSource
-

Python language support.

+

Autocompletion for built-in Python globals and keywords.

+
+
+ localCompletionSource(contextCompletionContext) → CompletionResult | null
+ +

Completion source that looks up locally defined names in +Python code.

-
\ No newline at end of file + diff --git a/src/README.md b/src/README.md index c3c7d2e..1ae9876 100644 --- a/src/README.md +++ b/src/README.md @@ -19,8 +19,25 @@ we have a [code of conduct](http://contributor-covenant.org/version/1/1/0/) that applies to communication around the project. +## Usage + +```javascript +import {EditorView, basicSetup} from "codemirror" +import {python} from "@codemirror/lang-python" + +const view = new EditorView({ + parent: document.body, + doc: `print("Hello world")`, + extensions: [basicSetup, python()] +}) +``` + # API Reference @python -@pythonLanguage \ No newline at end of file +@pythonLanguage + +@globalCompletion + +@localCompletionSource From 0f6499aac3eea5f01d463b484f5da742189c8f4b Mon Sep 17 00:00:00 2001 From: TechnoHouse <13776377+deephbz@users.noreply.github.com> Date: Sat, 18 Jan 2025 19:35:02 +0800 Subject: [PATCH 59/63] Indentation for match-case statements FIX: Properly indent match/case statements. --- src/python.ts | 21 +++++- test/test-indent.ts | 161 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 178 insertions(+), 4 deletions(-) diff --git a/src/python.ts b/src/python.ts index 97f5bd6..d4d2d65 100644 --- a/src/python.ts +++ b/src/python.ts @@ -15,9 +15,11 @@ function innerBody(context: TreeIndentContext) { break } else if (before.name == "Comment") { pos = before.from - } else if (before.name == "Body") { + } else if (before.name == "Body" || before.name == "MatchBody") { if (context.baseIndentFor(before) + context.unit <= lineIndent) found = before node = before + } else if (before.name == "MatchClause") { + node = before } else if (before.type.is("Statement")) { node = before } else { @@ -40,7 +42,7 @@ function indentBody(context: TreeIndentContext, node: SyntaxNode) { // A normally deindenting keyword that appears at a higher // indentation than the block should probably be handled by the next // level - if (/^\s*(else:|elif |except |finally:)/.test(context.textAfter) && context.lineIndent(context.pos, -1) > base) + if (/^\s*(else:|elif |except |finally:|case\s+[^=:]+:)/.test(context.textAfter) && context.lineIndent(context.pos, -1) > base) return null return base + context.unit } @@ -57,9 +59,20 @@ export const pythonLanguage = LRLanguage.define({ let inner = innerBody(context) return indentBody(context, inner || context.node) ?? context.continue() }, + + MatchBody: context => { + let inner = innerBody(context) + return indentBody(context, inner || context.node) ?? context.continue() + }, + IfStatement: cx => /^\s*(else:|elif )/.test(cx.textAfter) ? cx.baseIndent : cx.continue(), "ForStatement WhileStatement": cx => /^\s*else:/.test(cx.textAfter) ? cx.baseIndent : cx.continue(), TryStatement: cx => /^\s*(except |finally:|else:)/.test(cx.textAfter) ? cx.baseIndent : cx.continue(), + MatchStatement: cx => { + if (/^\s*case /.test(cx.textAfter)) return cx.baseIndent + cx.unit + return cx.continue() + }, + "TupleExpression ComprehensionExpression ParamList ArgList ParenthesizedExpression": delimitedIndent({closing: ")"}), "DictionaryExpression DictionaryComprehensionExpression SetExpression SetComprehensionExpression": delimitedIndent({closing: "}"}), "ArrayExpression ArrayComprehensionExpression": delimitedIndent({closing: "]"}), @@ -69,6 +82,7 @@ export const pythonLanguage = LRLanguage.define({ return (inner && indentBody(context, inner)) ?? context.continue() } }), + foldNodeProp.add({ "ArrayExpression DictionaryExpression SetExpression TupleExpression": foldInside, Body: (node, state) => ({from: node.from + 1, to: node.to - (node.to == state.doc.length ? 0 : 1)}) @@ -82,7 +96,8 @@ export const pythonLanguage = LRLanguage.define({ "F", "FR", "RF", "R", "U", "B", "BR", "RB"] }, commentTokens: {line: "#"}, - indentOnInput: /^\s*([\}\]\)]|else:|elif |except |finally:)$/ + // Indent logic logic are triggered upon below input patterns + indentOnInput: /^\s*([\}\]\)]|else:|elif |except |finally:|case\s+[^:]*:?)$/, } }) diff --git a/test/test-indent.ts b/test/test-indent.ts index e117984..513e1d4 100644 --- a/test/test-indent.ts +++ b/test/test-indent.ts @@ -9,7 +9,7 @@ function check(code: string) { let state = EditorState.create({doc: code, extensions: [python().language]}) for (let pos = 0, lines = code.split("\n"), i = 0; i < lines.length; i++) { let line = lines[i], indent = /^\s*/.exec(line)![0].length - ist(`${getIndentation(state, pos)} (${i + 1})`, `${indent} (${i + 1})`) + ist(`indent=${getIndentation(state, pos)} (line-numer=${i + 1})`, `indent=${indent} (line-numer=${i + 1})`) pos += line.length + 1 } } @@ -45,4 +45,163 @@ try: except e: bar() `)) + + it("multi-line-block try-except", check(` +try: + foo() + fooz() +except e: + bar() + barz() +finally: + baz() + bazz() +`)) + + + it("multi-line-nested-block try-except", check(` +try: + foo() + fooz() + try: + inner() + inner2() + except e2: + f3() + f4() + else: + f5() + f6() + finally: + f7() + f8() +except e: + bar() + barz() +finally: + baz() + bazz() +`)) + + it("match-case", check(` +match x: + case 1: + foo() + case 2: + bar() + case _: + bar() +`)) + + it("match-case-multi-line-block", check(` +def func(): + match x: + case 1: + foo() + fooz() + case 2: + bar() + bar() + bar() + match y: + case 3: + bar() + case 4: + bar() + case _: + bar() +`)) + + it("class-with-decorators", check(` +@decorator1 +@decorator2( + param1, + param2 +) +class MyClass: + def method(self): + pass +`)) + + it("list-comprehension", check(` +result = [ + x * y + for x in range(10) + for y in range(5) + if x > y +] +`)) + + it("multi-line-expressions", check(` +result = ( + very_long_variable_name + + another_long_variable * + some_computation( + arg1, + arg2 + ) +) +`)) + + it("async-function-and-with", check(` +async def process_data(): + async with context() as ctx: + result = await ctx.fetch( + url, + timeout=30 + ) + return result +`)) + + it("nested-functions", check(` +def outer(): + x = 1 + def inner1(): + y = 2 + def inner2(): + z = 3 + return x + y + z + return inner2() + return inner1() +`)) + + it("type-hints-and-annotations", check(` +def process_data( + data: list[str], + config: dict[str, Any] +) -> tuple[int, str]: + result: Optional[str] = None + if data: + result = data[0] + return len(data), result +`)) + + it("multi-line-dict-comprehension", check(` +config = { + key: value + for key, value in items + if is_valid( + key, + value + ) +} +`)) + + it("multi-line-with-comments", check(` +def process( + x: int, # The input value + y: float # The coefficient +): + # Compute first step + result = x * y + + # Apply additional processing + if result > 0: + # Positive case + return result + else: + # Negative case + return -result +`)) + }) From 3930ddffe73f2b7fd3e3949f25ee9ddbe3011a4b Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Sat, 18 Jan 2025 12:36:13 +0100 Subject: [PATCH 60/63] Mark version 6.1.7 --- CHANGELOG.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e0327e..ae78796 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 6.1.7 (2025-01-18) + +### Bug fixes + +Properly indent match/case statements. + ## 6.1.6 (2024-04-29) ### Bug fixes diff --git a/package.json b/package.json index 5bf17ed..1215e9c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@codemirror/lang-python", - "version": "6.1.6", + "version": "6.1.7", "description": "Python language support for the CodeMirror code editor", "scripts": { "test": "cm-runtests", From 3049f472f41c3f0c21bc9f379b55bd99b077a1e7 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 22 Apr 2025 14:53:06 +0200 Subject: [PATCH 61/63] Add code folding for multi-line strings FEATURE: Allow multi-line strings to be code-folded. Closes https://github.com/codemirror/dev/issues/1551 --- src/python.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/python.ts b/src/python.ts index d4d2d65..8970c9e 100644 --- a/src/python.ts +++ b/src/python.ts @@ -85,7 +85,8 @@ export const pythonLanguage = LRLanguage.define({ foldNodeProp.add({ "ArrayExpression DictionaryExpression SetExpression TupleExpression": foldInside, - Body: (node, state) => ({from: node.from + 1, to: node.to - (node.to == state.doc.length ? 0 : 1)}) + Body: (node, state) => ({from: node.from + 1, to: node.to - (node.to == state.doc.length ? 0 : 1)}), + "String FormatString": (node, state) => ({from: state.doc.lineAt(node.from).to, to: node.to}) }) ], }), From 52640ae2cf1c36dc0ad779dd92c40b318c91a8d4 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 23 Apr 2025 14:52:46 +0200 Subject: [PATCH 62/63] Add an indentation rule for member expressions FIX: Add an indentation rule for member expressions. Closes 'https://github.com/codemirror/dev/issues/1553 --- src/python.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/python.ts b/src/python.ts index 8970c9e..fa95cc5 100644 --- a/src/python.ts +++ b/src/python.ts @@ -76,11 +76,12 @@ export const pythonLanguage = LRLanguage.define({ "TupleExpression ComprehensionExpression ParamList ArgList ParenthesizedExpression": delimitedIndent({closing: ")"}), "DictionaryExpression DictionaryComprehensionExpression SetExpression SetComprehensionExpression": delimitedIndent({closing: "}"}), "ArrayExpression ArrayComprehensionExpression": delimitedIndent({closing: "]"}), + MemberExpression: cx => cx.baseIndent + cx.unit, "String FormatString": () => null, Script: context => { let inner = innerBody(context) return (inner && indentBody(context, inner)) ?? context.continue() - } + }, }), foldNodeProp.add({ From 34dbda2d67e9f75af4d9228b4ccd5bd7d38d12cb Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Fri, 25 Apr 2025 09:19:14 +0200 Subject: [PATCH 63/63] Mark version 6.2.0 --- CHANGELOG.md | 10 ++++++++++ package.json | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ae78796..50f62e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ +## 6.2.0 (2025-04-25) + +### Bug fixes + +Add an indentation rule for member expressions. + +### New features + +Allow multi-line strings to be code-folded. + ## 6.1.7 (2025-01-18) ### Bug fixes diff --git a/package.json b/package.json index 1215e9c..c1ae028 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@codemirror/lang-python", - "version": "6.1.7", + "version": "6.2.0", "description": "Python language support for the CodeMirror code editor", "scripts": { "test": "cm-runtests",