From 3135fbb6ae7508d9fc620a3c3b3acd084bd00a25 Mon Sep 17 00:00:00 2001 From: Shaun Hamilton Date: Mon, 18 Dec 2023 15:02:35 +0200 Subject: [PATCH] fix(python): add docs + newline fix --- docs/python.md | 76 ++++++++++++++++++++++++++++++++++++++----- docs/tools/helpers.js | 38 ++++++++++++++++++++-- lib/index.ts | 11 +++---- 3 files changed, 108 insertions(+), 17 deletions(-) diff --git a/docs/python.md b/docs/python.md index 05b941a..d4de326 100644 --- a/docs/python.md +++ b/docs/python.md @@ -1,8 +1,6 @@ # Python -## Browser - -Testing a function: +## `getDef` ```javascript,mdbook-runnable,hidelines=# # {{#rustdoc_include tools/helpers.js:1}} @@ -11,9 +9,9 @@ a = 1 b = 2 def add(x, y): - result = x + y - print(f"{x} + {y} = {result}") - return result + result = x + y + print(f"{x} + {y} = {result}") + return result `; @@ -28,6 +26,66 @@ def add(x, y): } ``` +## `getBlock` + +```javascript,mdbook-runnable,hidelines=# +# {{#rustdoc_include tools/helpers.js:1}} +const code = ` +a = 1 +b = 2 + +def add_or_subtract(a, b, add=True): + if add: + return a + b + else: + return a - b + +`; + +{ + const equivalentPatterns = [ + "if add", + /(if|elif) add/, + ]; + for (const pattern of equivalentPatterns) { + const ifBlock = __helpers.python.getBlock(code, pattern); + const { block_body, block_indentation, block_condition } = ifBlock; + console.assert(block_indentation === 4); + console.assert(block_condition === "if add"); + console.assert(block_body.match(/return a \+ b/)); + console.log(ifBlock); + } +} +``` + +## `removeComments` + +```javascript,mdbook-runnable,hidelines=!!!! +!!!!{{!!!!#rustdoc_include tools/helpers.js}} + const code = ` +a = 1 +# comment +def b(d, e): + a = 2 + # comment + return a #comment +`; +{ + const commentlessCode = __helpers.python.removeComments(code); + console.log(commentlessCode); + console.assert(commentlessCode === ` +a = 1 + +def b(d, e): + a = 2 + + return a +`); +} +``` + +## `__pyodide.runPython` + Running the code of a singluar function to get the output: ```javascript,mdbook-runnable,hidelines=# @@ -69,8 +127,8 @@ assert add(a, b) == 300 ```python def - add(x, y): - return x + y + add(x, y): + return x + y ``` - Python **does** allow newline characters between function arguments. E.g: @@ -80,5 +138,5 @@ def add( x, y ): - return x + y + return x + y ``` diff --git a/docs/tools/helpers.js b/docs/tools/helpers.js index 0582b18..eeb0a11 100644 --- a/docs/tools/helpers.js +++ b/docs/tools/helpers.js @@ -2,8 +2,8 @@ const __helpers = { python: { getDef: (code, functionName) => { const regex = new RegExp( - `\\n(? *?)def +${functionName} *\\((?[^\\)]*)\\)\\s*:\\n(?.*?)(?=\\n\\k[\\w#]|$)`, - "s" + `^(? *?)def +${functionName} *\\((?[^\\)]*)\\)\\s*:\\n(?.*?)(?=\\n\\k[\\w#]|$)`, + "ms" ); const matchedCode = regex.exec(code); @@ -25,5 +25,39 @@ const __helpers = { return null; }, + getBlock: (code, blockPattern) => { + const escapedBlockPattern = + blockPattern instanceof RegExp + ? blockPattern.source + : blockPattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); + + const regex = new RegExp( + `^(? *?)(?${escapedBlockPattern})\\s*:\\n(?.*?)(?=\\n\\k[\\w#]|$)`, + "ms" + ); + + const matchedCode = regex.exec(code); + if (matchedCode) { + /* eslint-disable camelcase */ + const { block_body, block_indentation, block_condition } = + matchedCode.groups; + + const blockIndentationSansNewLine = block_indentation.replace( + /\n+/g, + "" + ); + return { + block_body, + block_condition, + block_indentation: blockIndentationSansNewLine.length, + }; + /* eslint-enable camelcase */ + } + + return null; + }, + removeComments: (code) => { + return code.replace(/\/\/.*|\/\*[\s\S]*?\*\/|(#.*$)/gm, ""); + }, }, }; diff --git a/lib/index.ts b/lib/index.ts index 79e5916..15699d2 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -99,8 +99,8 @@ const getIsDeclaredAfter = (styleRule: CSSStyleRule) => (selector: string) => { export module python { export function getDef(code: string, functionName: string) { const regex = new RegExp( - `\\n(? *?)def +${functionName} *\\((?[^\\)]*)\\)\\s*:\\n(?.*?)(?=\\n\\k[\\w#]|$)`, - "s" + `^(? *?)def +${functionName} *\\((?[^\\)]*)\\)\\s*:\\n(?.*?)(?=\\n\\k[\\w#]|$)`, + "ms" ); const matchedCode = regex.exec(code); @@ -113,8 +113,7 @@ export module python { "" ); return { - // Entire function definition without additional \n - def: matchedCode[0].slice(1), + def: matchedCode[0], function_parameters, function_body, function_indentation: functionIndentationSansNewLine.length, @@ -142,8 +141,8 @@ export module python { : blockPattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); const regex = new RegExp( - `\\n(? *?)(?${escapedBlockPattern})\\s*:\\n(?.*?)(?=\\n\\k[\\w#]|$)`, - "s" + `^(? *?)(?${escapedBlockPattern})\\s*:\\n(?.*?)(?=\\n\\k[\\w#]|$)`, + "ms" ); const matchedCode = regex.exec(code);