From f34f02884f8e6054543bd1a3231187da321a9f85 Mon Sep 17 00:00:00 2001 From: Andrew Huang Date: Thu, 13 Jun 2024 12:36:47 -0700 Subject: [PATCH 01/12] Add value_input for code editor --- examples/reference/widgets/CodeEditor.ipynb | 4 ++-- panel/models/ace.py | 2 ++ panel/models/ace.ts | 11 ++++++++++- panel/tests/widgets/test_codeeditor.py | 11 +++++++++++ panel/widgets/codeeditor.py | 7 +++++-- 5 files changed, 30 insertions(+), 5 deletions(-) diff --git a/examples/reference/widgets/CodeEditor.ipynb b/examples/reference/widgets/CodeEditor.ipynb index 4232d91ed3..8d4c00364a 100644 --- a/examples/reference/widgets/CodeEditor.ipynb +++ b/examples/reference/widgets/CodeEditor.ipynb @@ -40,8 +40,8 @@ "* **``print_margin``** (boolean): Whether to show a print margin in the editor\n", "* **``theme``** (str): theme of the editor (default: 'chrome')\n", "* **``readonly``** (boolean): Whether the editor should be opened in read-only mode\n", - "* **``value``** (str): A string with (initial) code to set in the editor\n", - "\n", + "* **``value``** (str): State of the current code in the editor when pressing the key\n", + "* **``value_input``** (str): State of the current code updated on every key press\n", "___" ] }, diff --git a/panel/models/ace.py b/panel/models/ace.py index 391abac0f2..3f3d621b6d 100644 --- a/panel/models/ace.py +++ b/panel/models/ace.py @@ -50,6 +50,8 @@ def __js_skip__(cls): code = String(default='') + code_input = String(default='') + theme = Enum(ace_themes, default='chrome') filename = Nullable(String()) diff --git a/panel/models/ace.ts b/panel/models/ace.ts index 10ffc77f9d..711f91c408 100644 --- a/panel/models/ace.ts +++ b/panel/models/ace.ts @@ -68,7 +68,8 @@ export class AcePlotView extends HTMLBoxView { this._update_language() this._editor.setReadOnly(this.model.readonly) this._editor.setShowPrintMargin(this.model.print_margin) - this._editor.on("change", () => this._update_code_from_editor()) + this._editor.on("blur", () => this._update_code_from_editor()) + this._editor.on("change", () => this._update_code_input_from_editor()) } _update_code_from_model(): void { @@ -87,6 +88,12 @@ export class AcePlotView extends HTMLBoxView { } } + _update_code_input_from_editor(): void { + if (this._editor.getValue() != this.model.code_input) { + this.model.code_input = this._editor.getValue() + } + } + _update_theme(): void { this._editor.setTheme(`ace/theme/${this.model.theme}`) } @@ -120,6 +127,7 @@ export namespace AcePlot { export type Attrs = p.AttrsOf export type Props = HTMLBox.Props & { code: p.Property + code_input: p.Property language: p.Property filename: p.Property theme: p.Property @@ -145,6 +153,7 @@ export class AcePlot extends HTMLBox { this.define(({Any, List, Bool, Str, Nullable}) => ({ code: [ Str, "" ], + code_input: [ Str, "" ], filename: [ Nullable(Str), null], language: [ Str, "" ], theme: [ Str, "chrome" ], diff --git a/panel/tests/widgets/test_codeeditor.py b/panel/tests/widgets/test_codeeditor.py index d85c8650de..fba2924c57 100644 --- a/panel/tests/widgets/test_codeeditor.py +++ b/panel/tests/widgets/test_codeeditor.py @@ -12,3 +12,14 @@ def test_ace(document, comm): # Try changes editor._process_events({"value": "Hi there!"}) assert editor.value == "Hi there!" + + +def test_ace_input(document, comm): + editor = CodeEditor(value="", language="python") + editor.value = "Hello World!" + assert editor.value == "Hello World!" + assert editor.value_input == "Hello World!" + + editor.value = "" + assert editor.value == "" + assert editor.value_input == "" diff --git a/panel/widgets/codeeditor.py b/panel/widgets/codeeditor.py index 94d331c45b..0fcd4b5271 100644 --- a/panel/widgets/codeeditor.py +++ b/panel/widgets/codeeditor.py @@ -49,9 +49,11 @@ class CodeEditor(Widget): theme = param.ObjectSelector(default="chrome", objects=list(ace_themes), doc="Theme of the editor") - value = param.String(doc="State of the current code in the editor") + value = param.String(doc="State of the current code in the editor when pressing the key.") - _rename: ClassVar[Mapping[str, str | None]] = {"value": "code", "name": None} + value_input = param.String(doc="State of the current code updated on every key press.") + + _rename: ClassVar[Mapping[str, str | None]] = {"value": "code", "value_input": "code_input", "name": None} def __init__(self, **params): if 'readonly' in params: @@ -63,6 +65,7 @@ def __init__(self, **params): self.param.watch(self._update_disabled, ['disabled', 'readonly']) ) self.jslink(self, readonly='disabled', bidirectional=True) + self.link(self, value="value_input") def _get_model( self, doc: Document, root: Optional[Model] = None, From af8a65c8b9b867c2c9b7bb3875fadbb489faef82 Mon Sep 17 00:00:00 2001 From: Andrew Huang Date: Thu, 13 Jun 2024 12:52:27 -0700 Subject: [PATCH 02/12] clarify docs --- examples/reference/widgets/CodeEditor.ipynb | 2 +- panel/widgets/codeeditor.py | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/examples/reference/widgets/CodeEditor.ipynb b/examples/reference/widgets/CodeEditor.ipynb index 8d4c00364a..f4a465acbc 100644 --- a/examples/reference/widgets/CodeEditor.ipynb +++ b/examples/reference/widgets/CodeEditor.ipynb @@ -40,7 +40,7 @@ "* **``print_margin``** (boolean): Whether to show a print margin in the editor\n", "* **``theme``** (str): theme of the editor (default: 'chrome')\n", "* **``readonly``** (boolean): Whether the editor should be opened in read-only mode\n", - "* **``value``** (str): State of the current code in the editor when pressing the key\n", + "* **``value``** (str): State of the current code in the editor when pressing the key or loss of focus\n", "* **``value_input``** (str): State of the current code updated on every key press\n", "___" ] diff --git a/panel/widgets/codeeditor.py b/panel/widgets/codeeditor.py index 0fcd4b5271..dde57d0adc 100644 --- a/panel/widgets/codeeditor.py +++ b/panel/widgets/codeeditor.py @@ -49,7 +49,7 @@ class CodeEditor(Widget): theme = param.ObjectSelector(default="chrome", objects=list(ace_themes), doc="Theme of the editor") - value = param.String(doc="State of the current code in the editor when pressing the key.") + value = param.String(doc="State of the current code in the editor when pressing the key or loss of focus.") value_input = param.String(doc="State of the current code updated on every key press.") @@ -65,7 +65,10 @@ def __init__(self, **params): self.param.watch(self._update_disabled, ['disabled', 'readonly']) ) self.jslink(self, readonly='disabled', bidirectional=True) - self.link(self, value="value_input") + + @param.depends("value", watch=True) + def _update_value_input(self): + self.value_input = self.value def _get_model( self, doc: Document, root: Optional[Model] = None, From e85ecfd0a8d1455feb69af95576e13775121ec73 Mon Sep 17 00:00:00 2001 From: Andrew Huang Date: Thu, 27 Jun 2024 14:53:24 -0700 Subject: [PATCH 03/12] address comment --- examples/reference/widgets/CodeEditor.ipynb | 2 +- panel/tests/ui/widgets/test_codeeditor.py | 33 +++++++++++++++++++++ panel/widgets/codeeditor.py | 3 +- 3 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 panel/tests/ui/widgets/test_codeeditor.py diff --git a/examples/reference/widgets/CodeEditor.ipynb b/examples/reference/widgets/CodeEditor.ipynb index f4a465acbc..babaacebda 100644 --- a/examples/reference/widgets/CodeEditor.ipynb +++ b/examples/reference/widgets/CodeEditor.ipynb @@ -40,7 +40,7 @@ "* **``print_margin``** (boolean): Whether to show a print margin in the editor\n", "* **``theme``** (str): theme of the editor (default: 'chrome')\n", "* **``readonly``** (boolean): Whether the editor should be opened in read-only mode\n", - "* **``value``** (str): State of the current code in the editor when pressing the key or loss of focus\n", + "* **``value``** (str): State of the current code in the editor upon loss of focus, i.e. clicking outside the editor\n", "* **``value_input``** (str): State of the current code updated on every key press\n", "___" ] diff --git a/panel/tests/ui/widgets/test_codeeditor.py b/panel/tests/ui/widgets/test_codeeditor.py new file mode 100644 index 0000000000..1c6b5e4736 --- /dev/null +++ b/panel/tests/ui/widgets/test_codeeditor.py @@ -0,0 +1,33 @@ +import pytest + +pytest.importorskip("playwright") + +from playwright.sync_api import expect + +from panel.tests.util import serve_component, wait_until +from panel.widgets import CodeEditor + +pytestmark = pytest.mark.ui + + +def test_code_editor(page): + + editor = CodeEditor(value="print('Hello World!')") + serve_component(page, editor) + ace_input = page.locator(".ace_content") + expect(ace_input).to_have_count(1) + ace_input.click() + + page.keyboard.press("Enter") + page.keyboard.type('print("Hello Panel!")') + wait_until( + lambda: page.locator(".ace_content").inner_text() + == "print('Hello World!')\nprint(\"Hello Panel!\")" + ) + wait_until(lambda: editor.value_input == "print('Hello World!')\nprint(\"Hello Panel!\")") + assert editor.value == "print('Hello World!')" + + # page click outside the editor + page.locator("body").click() + assert editor.value_input == "print('Hello World!')\nprint(\"Hello Panel!\")" + wait_until(lambda: editor.value == "print('Hello World!')\nprint(\"Hello Panel!\")") diff --git a/panel/widgets/codeeditor.py b/panel/widgets/codeeditor.py index dde57d0adc..d449dc79a3 100644 --- a/panel/widgets/codeeditor.py +++ b/panel/widgets/codeeditor.py @@ -49,7 +49,8 @@ class CodeEditor(Widget): theme = param.ObjectSelector(default="chrome", objects=list(ace_themes), doc="Theme of the editor") - value = param.String(doc="State of the current code in the editor when pressing the key or loss of focus.") + value = param.String(doc=""" + State of the current code in the editor upon loss of focus, i.e. clicking outside the editor.""") value_input = param.String(doc="State of the current code updated on every key press.") From 47f4bcefda2af459c3ebc661b196a831badaee78 Mon Sep 17 00:00:00 2001 From: Andrew <15331990+ahuang11@users.noreply.github.com> Date: Thu, 27 Jun 2024 15:11:12 -0700 Subject: [PATCH 04/12] Update panel/tests/ui/widgets/test_codeeditor.py Co-authored-by: Philipp Rudiger --- panel/tests/ui/widgets/test_codeeditor.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/panel/tests/ui/widgets/test_codeeditor.py b/panel/tests/ui/widgets/test_codeeditor.py index 1c6b5e4736..25dd2d1f71 100644 --- a/panel/tests/ui/widgets/test_codeeditor.py +++ b/panel/tests/ui/widgets/test_codeeditor.py @@ -20,10 +20,7 @@ def test_code_editor(page): page.keyboard.press("Enter") page.keyboard.type('print("Hello Panel!")') - wait_until( - lambda: page.locator(".ace_content").inner_text() - == "print('Hello World!')\nprint(\"Hello Panel!\")" - ) + expect(page.locator(".ace_content")).to_have_text("print('Hello World!')\nprint(\"Hello Panel!\")") wait_until(lambda: editor.value_input == "print('Hello World!')\nprint(\"Hello Panel!\")") assert editor.value == "print('Hello World!')" From e2ced4719d28dd07e602294fed07ca1d6a79092f Mon Sep 17 00:00:00 2001 From: Andrew Huang Date: Thu, 27 Jun 2024 16:12:25 -0700 Subject: [PATCH 05/12] fix test --- panel/tests/ui/widgets/test_codeeditor.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/panel/tests/ui/widgets/test_codeeditor.py b/panel/tests/ui/widgets/test_codeeditor.py index 25dd2d1f71..6a7fce2daf 100644 --- a/panel/tests/ui/widgets/test_codeeditor.py +++ b/panel/tests/ui/widgets/test_codeeditor.py @@ -20,11 +20,12 @@ def test_code_editor(page): page.keyboard.press("Enter") page.keyboard.type('print("Hello Panel!")') - expect(page.locator(".ace_content")).to_have_text("print('Hello World!')\nprint(\"Hello Panel!\")") + + expect(page.locator(".ace_content")).to_have_text("print('Hello World!')\nprint(\"Hello Panel!\")", use_inner_text=True) wait_until(lambda: editor.value_input == "print('Hello World!')\nprint(\"Hello Panel!\")") assert editor.value == "print('Hello World!')" - # page click outside the editor + # page click outside the editor; sync the value page.locator("body").click() assert editor.value_input == "print('Hello World!')\nprint(\"Hello Panel!\")" wait_until(lambda: editor.value == "print('Hello World!')\nprint(\"Hello Panel!\")") From be37503476bcee6e03fba38f9ee562b4cffb774c Mon Sep 17 00:00:00 2001 From: Andrew Huang Date: Thu, 27 Jun 2024 16:26:39 -0700 Subject: [PATCH 06/12] add ctrl+enter --- examples/reference/widgets/CodeEditor.ipynb | 6 ++--- panel/models/ace.ts | 7 ++++++ panel/tests/ui/widgets/test_codeeditor.py | 25 +++++++++++++++++++++ panel/widgets/codeeditor.py | 3 ++- 4 files changed, 37 insertions(+), 4 deletions(-) diff --git a/examples/reference/widgets/CodeEditor.ipynb b/examples/reference/widgets/CodeEditor.ipynb index babaacebda..fcec7b9f74 100644 --- a/examples/reference/widgets/CodeEditor.ipynb +++ b/examples/reference/widgets/CodeEditor.ipynb @@ -40,7 +40,7 @@ "* **``print_margin``** (boolean): Whether to show a print margin in the editor\n", "* **``theme``** (str): theme of the editor (default: 'chrome')\n", "* **``readonly``** (boolean): Whether the editor should be opened in read-only mode\n", - "* **``value``** (str): State of the current code in the editor upon loss of focus, i.e. clicking outside the editor\n", + "* **``value``** (str): State of the current code in the editor upon loss of focus, i.e. clicking outside the editor, or `` or ``.\n", "* **``value_input``** (str): State of the current code updated on every key press\n", "___" ] @@ -50,7 +50,7 @@ "metadata": {}, "source": [ "To construct an `Ace` widget we must define it explicitly using `pn.widgets.Ace`. We can add some text as initial code.\n", - "Code inserted in the editor is automatically reflected in the `value`." + "Code inserted in the editor is automatically reflected in the `value_input` and `value` upon loss of focus or `` or ``." ] }, { @@ -61,7 +61,7 @@ "source": [ "py_code = \"import sys\"\n", "editor = pn.widgets.CodeEditor(value=py_code, sizing_mode='stretch_width', language='python', height=300)\n", - "editor" + "editor.show()" ] }, { diff --git a/panel/models/ace.ts b/panel/models/ace.ts index fe6d9a3efe..250fb58d44 100644 --- a/panel/models/ace.ts +++ b/panel/models/ace.ts @@ -70,6 +70,13 @@ export class AcePlotView extends HTMLBoxView { this._editor.setShowPrintMargin(this.model.print_margin) this._editor.on("blur", () => this._update_code_from_editor()) this._editor.on("change", () => this._update_code_input_from_editor()) + this._editor.commands.addCommand({ + name: "updateCodeFromEditor", + bindKey: { win: "Ctrl-Enter", mac: "Command-Enter"}, + exec: () => { + this._update_code_from_editor(); + } + }); } _update_code_from_model(): void { diff --git a/panel/tests/ui/widgets/test_codeeditor.py b/panel/tests/ui/widgets/test_codeeditor.py index 6a7fce2daf..8cce85e333 100644 --- a/panel/tests/ui/widgets/test_codeeditor.py +++ b/panel/tests/ui/widgets/test_codeeditor.py @@ -1,3 +1,5 @@ +import sys + import pytest pytest.importorskip("playwright") @@ -29,3 +31,26 @@ def test_code_editor(page): page.locator("body").click() assert editor.value_input == "print('Hello World!')\nprint(\"Hello Panel!\")" wait_until(lambda: editor.value == "print('Hello World!')\nprint(\"Hello Panel!\")") + + # clear the editor + editor.value = "" + expect(page.locator(".ace_content")).to_have_text("", use_inner_text=True) + assert editor.value == "" + assert editor.value_input == "" + + # enter Hello UI + ace_input.click() + page.keyboard.type('print("Hello UI!")') + expect(page.locator(".ace_content")).to_have_text("print(\"Hello UI!\")", use_inner_text=True) + assert editor.value == "" + + # If windows: Ctrl+Enter to trigger value else if mac, Command+Enter + if sys.platform == "win32": + page.keyboard.down("Control") + page.keyboard.press("Enter") + page.keyboard.up("Control") + else: + page.keyboard.down("Meta") + page.keyboard.press("Enter") + page.keyboard.up("Meta") + wait_until(lambda: editor.value == "print(\"Hello UI!\")") diff --git a/panel/widgets/codeeditor.py b/panel/widgets/codeeditor.py index 809d801bf4..d22c5310a9 100644 --- a/panel/widgets/codeeditor.py +++ b/panel/widgets/codeeditor.py @@ -50,7 +50,8 @@ class CodeEditor(Widget): doc="Theme of the editor") value = param.String(default="", doc=""" - State of the current code in the editor upon loss of focus, i.e. clicking outside the editor.""") + State of the current code in the editor upon loss of focus, + i.e. clicking outside the editor, or pressing or .""") value_input = param.String(doc="State of the current code updated on every key press.") From 840d5d2b3f9e36a12606a3082d8e15b55d2cbc13 Mon Sep 17 00:00:00 2001 From: Andrew Huang Date: Fri, 28 Jun 2024 09:24:34 -0700 Subject: [PATCH 07/12] eslint --- panel/models/ace.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/panel/models/ace.ts b/panel/models/ace.ts index 250fb58d44..7c552344d7 100644 --- a/panel/models/ace.ts +++ b/panel/models/ace.ts @@ -72,11 +72,11 @@ export class AcePlotView extends HTMLBoxView { this._editor.on("change", () => this._update_code_input_from_editor()) this._editor.commands.addCommand({ name: "updateCodeFromEditor", - bindKey: { win: "Ctrl-Enter", mac: "Command-Enter"}, + bindKey: {win: "Ctrl-Enter", mac: "Command-Enter"}, exec: () => { - this._update_code_from_editor(); - } - }); + this._update_code_from_editor() + }, + }) } _update_code_from_model(): void { From cf2e1283e32d9a814b5b2251d13d1470671e6fcb Mon Sep 17 00:00:00 2001 From: Andrew Huang Date: Fri, 28 Jun 2024 10:59:26 -0700 Subject: [PATCH 08/12] flag to toggle --- panel/models/ace.py | 2 ++ panel/models/ace.ts | 23 ++++++++++------ panel/tests/ui/widgets/test_codeeditor.py | 32 +++++++++++++++++++++-- panel/widgets/codeeditor.py | 8 ++++-- 4 files changed, 53 insertions(+), 12 deletions(-) diff --git a/panel/models/ace.py b/panel/models/ace.py index 3f3d621b6d..b898a6b363 100644 --- a/panel/models/ace.py +++ b/panel/models/ace.py @@ -52,6 +52,8 @@ def __js_skip__(cls): code_input = String(default='') + on_keyup = Bool(default=True) + theme = Enum(ace_themes, default='chrome') filename = Nullable(String()) diff --git a/panel/models/ace.ts b/panel/models/ace.ts index 7c552344d7..584e3fc544 100644 --- a/panel/models/ace.ts +++ b/panel/models/ace.ts @@ -68,15 +68,20 @@ export class AcePlotView extends HTMLBoxView { this._update_language() this._editor.setReadOnly(this.model.readonly) this._editor.setShowPrintMargin(this.model.print_margin) - this._editor.on("blur", () => this._update_code_from_editor()) + // if on keyup, update code from editor + if (this.model.on_keyup) { + this._editor.on("change", () => this._update_code_from_editor()) + } else { + this._editor.on("blur", () => this._update_code_from_editor()) + this._editor.commands.addCommand({ + name: "updateCodeFromEditor", + bindKey: {win: "Ctrl-Enter", mac: "Command-Enter"}, + exec: () => { + this._update_code_from_editor() + }, + }) + } this._editor.on("change", () => this._update_code_input_from_editor()) - this._editor.commands.addCommand({ - name: "updateCodeFromEditor", - bindKey: {win: "Ctrl-Enter", mac: "Command-Enter"}, - exec: () => { - this._update_code_from_editor() - }, - }) } _update_code_from_model(): void { @@ -135,6 +140,7 @@ export namespace AcePlot { export type Props = HTMLBox.Props & { code: p.Property code_input: p.Property + on_keyup: p.Property language: p.Property filename: p.Property theme: p.Property @@ -161,6 +167,7 @@ export class AcePlot extends HTMLBox { this.define(({Any, List, Bool, Str, Nullable}) => ({ code: [ Str, "" ], code_input: [ Str, "" ], + on_keyup: [ Bool, true ], filename: [ Nullable(Str), null], language: [ Str, "" ], theme: [ Str, "chrome" ], diff --git a/panel/tests/ui/widgets/test_codeeditor.py b/panel/tests/ui/widgets/test_codeeditor.py index 8cce85e333..5b552d56df 100644 --- a/panel/tests/ui/widgets/test_codeeditor.py +++ b/panel/tests/ui/widgets/test_codeeditor.py @@ -12,9 +12,37 @@ pytestmark = pytest.mark.ui -def test_code_editor(page): +def test_code_editor_on_keyup(page): - editor = CodeEditor(value="print('Hello World!')") + editor = CodeEditor(value="print('Hello World!')", on_keyup=True) + serve_component(page, editor) + ace_input = page.locator(".ace_content") + expect(ace_input).to_have_count(1) + ace_input.click() + + page.keyboard.press("Enter") + page.keyboard.type('print("Hello Panel!")') + + expect(page.locator(".ace_content")).to_have_text("print('Hello World!')\nprint(\"Hello Panel!\")", use_inner_text=True) + wait_until(lambda: editor.value_input == "print('Hello World!')\nprint(\"Hello Panel!\")") + assert editor.value == "print('Hello World!')\nprint(\"Hello Panel!\")" + + # clear the editor + editor.value = "" + expect(page.locator(".ace_content")).to_have_text("", use_inner_text=True) + assert editor.value == "" + assert editor.value_input == "" + + # enter Hello UI + ace_input.click() + page.keyboard.type('print("Hello UI!")') + expect(page.locator(".ace_content")).to_have_text("print(\"Hello UI!\")", use_inner_text=True) + assert editor.value == "print(\"Hello UI!\")" + + +def test_code_editor_not_on_keyup(page): + + editor = CodeEditor(value="print('Hello World!')", on_keyup=False) serve_component(page, editor) ace_input = page.locator(".ace_content") expect(ace_input).to_have_count(1) diff --git a/panel/widgets/codeeditor.py b/panel/widgets/codeeditor.py index d22c5310a9..4c0469ea4d 100644 --- a/panel/widgets/codeeditor.py +++ b/panel/widgets/codeeditor.py @@ -50,10 +50,14 @@ class CodeEditor(Widget): doc="Theme of the editor") value = param.String(default="", doc=""" - State of the current code in the editor upon loss of focus, + State of the current code in the editor if `on_keyup`. Otherwise, only upon loss of focus, i.e. clicking outside the editor, or pressing or .""") - value_input = param.String(doc="State of the current code updated on every key press.") + value_input = param.String(default="", doc=""" + State of the current code updated on every key press. Identical to `value` if `on_keyup`.""") + + on_keyup = param.Boolean(default=True, doc=""" + Whether to update the value on every key press or only upon loss of focus / hotkeys.""") _rename: ClassVar[Mapping[str, str | None]] = {"value": "code", "value_input": "code_input", "name": None} From 002fd582a787c73edf9978f70e409f809eeb668b Mon Sep 17 00:00:00 2001 From: Andrew Huang Date: Fri, 28 Jun 2024 11:05:16 -0700 Subject: [PATCH 09/12] update notebook --- examples/reference/widgets/CodeEditor.ipynb | 25 +++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/examples/reference/widgets/CodeEditor.ipynb b/examples/reference/widgets/CodeEditor.ipynb index fcec7b9f74..26c3b8fafa 100644 --- a/examples/reference/widgets/CodeEditor.ipynb +++ b/examples/reference/widgets/CodeEditor.ipynb @@ -40,8 +40,9 @@ "* **``print_margin``** (boolean): Whether to show a print margin in the editor\n", "* **``theme``** (str): theme of the editor (default: 'chrome')\n", "* **``readonly``** (boolean): Whether the editor should be opened in read-only mode\n", - "* **``value``** (str): State of the current code in the editor upon loss of focus, i.e. clicking outside the editor, or `` or ``.\n", - "* **``value_input``** (str): State of the current code updated on every key press\n", + "* **``value``** (str): State of the current code in the editor if `on_keyup`. Otherwise, only upon loss of focus, i.e. clicking outside the editor, or pressing or .\n", + "* **``on_keyup``** (bool): Whether to update the value on every key press or only upon loss of focus / hotkeys.\n", + "* **``value_input``** (str): State of the current code updated on every key press. Identical to `value` if `on_keyup`.\n", "___" ] }, @@ -84,6 +85,26 @@ "\"\"\"" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "By default, the code editor will update the `value` on every key press, but you can set `on_keyup=False` to only update the `value` when the editor loses focus or pressing ``/ ``. Here, the code is printed when `value` is changed." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def print_code(value):\n", + " print(value)\n", + "\n", + "editor = pn.widgets.CodeEditor(value=py_code, on_keyup=False)\n", + "pn.bind(print_code, editor.param.value)" + ] + }, { "cell_type": "markdown", "metadata": {}, From bc259c9c418fa26215c2f664eb54e173f2ca0713 Mon Sep 17 00:00:00 2001 From: Andrew Huang Date: Fri, 28 Jun 2024 11:06:30 -0700 Subject: [PATCH 10/12] alphabetical sorting --- examples/reference/widgets/CodeEditor.ipynb | 2 +- panel/widgets/codeeditor.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/reference/widgets/CodeEditor.ipynb b/examples/reference/widgets/CodeEditor.ipynb index 26c3b8fafa..0f8fb7fd52 100644 --- a/examples/reference/widgets/CodeEditor.ipynb +++ b/examples/reference/widgets/CodeEditor.ipynb @@ -37,11 +37,11 @@ " - `'type'`: type of annotation and the icon displayed {`warning` | `error`}\n", "* **``filename``** (str): If filename is provided the file extension will be used to determine the language\n", "* **``language``** (str): A string declaring which language to use for code syntax highlighting (default: 'text')\n", + "* **``on_keyup``** (bool): Whether to update the value on every key press or only upon loss of focus / hotkeys.\n", "* **``print_margin``** (boolean): Whether to show a print margin in the editor\n", "* **``theme``** (str): theme of the editor (default: 'chrome')\n", "* **``readonly``** (boolean): Whether the editor should be opened in read-only mode\n", "* **``value``** (str): State of the current code in the editor if `on_keyup`. Otherwise, only upon loss of focus, i.e. clicking outside the editor, or pressing or .\n", - "* **``on_keyup``** (bool): Whether to update the value on every key press or only upon loss of focus / hotkeys.\n", "* **``value_input``** (str): State of the current code updated on every key press. Identical to `value` if `on_keyup`.\n", "___" ] diff --git a/panel/widgets/codeeditor.py b/panel/widgets/codeeditor.py index 4c0469ea4d..8e766afd85 100644 --- a/panel/widgets/codeeditor.py +++ b/panel/widgets/codeeditor.py @@ -40,6 +40,9 @@ class CodeEditor(Widget): language = param.String(default='text', doc="Language of the editor") + on_keyup = param.Boolean(default=True, doc=""" + Whether to update the value on every key press or only upon loss of focus / hotkeys.""") + print_margin = param.Boolean(default=False, doc=""" Whether to show the a print margin.""") @@ -56,9 +59,6 @@ class CodeEditor(Widget): value_input = param.String(default="", doc=""" State of the current code updated on every key press. Identical to `value` if `on_keyup`.""") - on_keyup = param.Boolean(default=True, doc=""" - Whether to update the value on every key press or only upon loss of focus / hotkeys.""") - _rename: ClassVar[Mapping[str, str | None]] = {"value": "code", "value_input": "code_input", "name": None} def __init__(self, **params): From 0c6553801a1f1475c5d7c06182d5a320081d71e4 Mon Sep 17 00:00:00 2001 From: Andrew Huang Date: Fri, 28 Jun 2024 11:06:52 -0700 Subject: [PATCH 11/12] rm show --- examples/reference/widgets/CodeEditor.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/reference/widgets/CodeEditor.ipynb b/examples/reference/widgets/CodeEditor.ipynb index 0f8fb7fd52..6d84318a33 100644 --- a/examples/reference/widgets/CodeEditor.ipynb +++ b/examples/reference/widgets/CodeEditor.ipynb @@ -62,7 +62,7 @@ "source": [ "py_code = \"import sys\"\n", "editor = pn.widgets.CodeEditor(value=py_code, sizing_mode='stretch_width', language='python', height=300)\n", - "editor.show()" + "editor" ] }, { From fd1c7fa62cd955fafbe5f2f6ce55eea672f78011 Mon Sep 17 00:00:00 2001 From: Andrew Huang Date: Fri, 28 Jun 2024 12:00:09 -0700 Subject: [PATCH 12/12] clarify --- examples/reference/widgets/CodeEditor.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/reference/widgets/CodeEditor.ipynb b/examples/reference/widgets/CodeEditor.ipynb index 6d84318a33..abab154058 100644 --- a/examples/reference/widgets/CodeEditor.ipynb +++ b/examples/reference/widgets/CodeEditor.ipynb @@ -51,7 +51,7 @@ "metadata": {}, "source": [ "To construct an `Ace` widget we must define it explicitly using `pn.widgets.Ace`. We can add some text as initial code.\n", - "Code inserted in the editor is automatically reflected in the `value_input` and `value` upon loss of focus or `` or ``." + "Code inserted in the editor is automatically reflected in the `value_input` and `value`." ] }, {