CodeEditor#

Open this notebook in Jupyterlite | Download this notebook from GitHub (right-click to download).


import panel as pn
import param

pn.extension('codeeditor')

The CodeEditor widget allows embedding a code editor based on Ace.

Only a small subset of Ace functionality is currently enabled:

  • syntax highlighting for several languages

  • themes

  • basic completion support via ctrl+space (using only static analysis of the code)

  • annotations

  • readonly mode

Parameters:#

For details on other options for customizing the component see the layout and styling how-to guides.

  • annotations (list): list of annotations. An annotation is a dict with the following keys:

    • 'row': row in the editor of the annotation

    • 'column': column of the annotation

    • 'text': text displayed when hovering over the annotation

    • 'type': type of annotation and the icon displayed {warning | error}

  • filename (str): If filename is provided the file extension will be used to determine the language

  • language (str): A string declaring which language to use for code syntax highlighting (default: ‘text’)

  • on_keyup (bool): Whether to update the value on every key press or only upon loss of focus / hotkeys.

  • print_margin (boolean): Whether to show a print margin in the editor

  • theme (str): If no value is provided, it defaults to the current theme set by pn.config.theme, as specified in the CodeEditor.THEME_CONFIGURATION dictionary. If not defined there, it falls back to the default parameter value (‘chrome’).

  • readonly (boolean): Whether the editor should be opened in read-only mode

  • 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 <Ctrl+Enter> or <Cmd+Enter>.

  • value_input (str): State of the current code updated on every key press. Identical to value if on_keyup.


To construct an Ace widget we must define it explicitly using pn.widgets.Ace. We can add some text as initial code. Code inserted in the editor is automatically reflected in the value_input and value.

py_code = "import sys"
editor = pn.widgets.CodeEditor(value=py_code, sizing_mode='stretch_width', language='python', height=300)
editor

we can add some code in it

editor.value += """
import Math

x = Math.cos(x)**2 + Math.cos(y)**2
"""

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 <Ctrl+Enter>/ <Cmd+Enter>. Here, the code is printed when value is changed.

def print_code(value):
    print(value)

editor = pn.widgets.CodeEditor(value=py_code, on_keyup=False)
pn.bind(print_code, editor.param.value)

We can change language and theme of the editor

html_code = r"""<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="content-type" content="text/html; charset=utf-8" />
        <title>`substitute(Filename('', 'Page Title'), '^.', '\u&', '')`</title>
    </head>
    <body>
        <h1>Title1</h1>
        <h2>Title2</h2>
        <p>Paragraph</p>
    </body>
</html>
"""
editor.language = "html"
editor.theme = "monokai"
editor.value = html_code
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="content-type" content="text/html; charset=utf-8" />
        <title>`substitute(Filename('', 'Page Title'), '^.', '\u&', '')`</title>
    </head>
    <body>
        <h1>Title1</h1>
        <h2>Title2</h2>
        <p>Paragraph</p>
    </body>
</html>

We can add some annotations to the editor

editor.annotations = [
    dict(row=1, column=0, text='an error', type='error'),
    dict(row=2, column=0, text='a warning', type='warning')
]

If we want just to display editor content but not edit it we can set the readonly property to True

#editor.readonly = True

If instead of setting the language explicitly we want to set the filename and automatically detect the language based on the file extension we can do that too:

editor.filename = 'test.html'

Including the CodeEditor editor in a parameterized class#

You can view the Ace widget as part of a param.Parameterized class:

from panel.viewable import Viewer

class CodeEditorTest(Viewer):
    
    editor = param.String('Hello World')
    
    def __panel__(self):
        """ Map the string to appear as an Ace editor. """
        return pn.Param(
            self.param,
            widgets=dict(
                editor=dict(
                    type=pn.widgets.CodeEditor,
                    language='python',
                )
            )
        )
    
edit = CodeEditorTest()

edit

Controls#

The CodeEditor widget exposes a number of options which can be changed from both Python and Javascript. Try out the effect of these parameters interactively:

widget = pn.widgets.CodeEditor(name='CodeEditor', value=py_code, language='python', sizing_mode='stretch_both', min_height=300)

pn.Row(widget.controls(jslink=True), widget, sizing_mode='stretch_both')

Try changing the filename including a file extension and watch the language automatically update.


Open this notebook in Jupyterlite | Download this notebook from GitHub (right-click to download).