{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import panel as pn\n",
    "import param\n",
    "pn.extension('ace')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The ``Ace`` widget allows embedding a code editor based on [Ace](https://ace.c9.io/).\n",
    "Only a small subset of Ace functionality is currently enabled:\n",
    " - **syntax highlighting** for several languages\n",
    " - **themes**\n",
    " - basic **completion** support via `ctrl+space` (using only static analysis of the code)\n",
    " - **annotations**\n",
    " - **readonly** mode\n",
    "\n",
    "#### Parameters:\n",
    "\n",
    "For layout and styling related parameters see the [customization user guide](../../user_guide/Customization.ipynb).\n",
    "\n",
    "* **``annotations``** (list): list of annotations. An annotation is a dict with the following keys:\n",
    "    - `'row'`: row in the editor of the annotation\n",
    "    - `'column'`: column of the annotation\n",
    "    - `'text'`: text displayed when hovering over the annotation\n",
    "    - `'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",
    "* **``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",
    "___"
   ]
  },
  {
   "cell_type": "markdown",
   "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`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "py_code = \"\"\"import sys\"\"\"\n",
    "editor = pn.widgets.Ace(value=py_code, sizing_mode='stretch_both', language='python', height=300)\n",
    "editor"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "we can add some code in it"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "editor.value += \"\"\"\n",
    "import Math\n",
    "\n",
    "x = Math.cos(x)**2 + Math.cos(y)**2\n",
    "\"\"\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can change language and theme of the editor"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "html_code = r\"\"\"<!DOCTYPE html>\n",
    "<html>\n",
    "    <head>\n",
    "        <meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\" />\n",
    "        <title>`substitute(Filename('', 'Page Title'), '^.', '\\u&', '')`</title>\n",
    "    </head>\n",
    "    <body>\n",
    "        <h1>Title1</h1>\n",
    "        <h2>Title2</h2>\n",
    "        <p>Paragraph</p>\n",
    "    </body>\n",
    "</html>\n",
    "\"\"\"\n",
    "editor.language = \"html\"\n",
    "editor.theme = \"monokai\"\n",
    "editor.value = html_code"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can add some annotations to the editor"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "editor.annotations= [dict(row=1, column=0, text='an error', type='error'),\n",
    "                     dict(row=2, column=0, text='a warning', type='warning')]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If we want just to display editor content but not edit it we can set the `readonly` property to `True`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#editor.readonly = True"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "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:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "editor.filename = 'test.html'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Including the Ace editor in a parameterized class\n",
    "\n",
    "You can view the Ace widget as part of a `param.Parameterized` class:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "class AceTest(param.Parameterized):\n",
    "    editor = param.String('Hello World')\n",
    "    \n",
    "    def view(self):\n",
    "        \"\"\" Map the string to appear as an Ace editor. \"\"\"\n",
    "        return pn.Param(\n",
    "            self.param,\n",
    "            widgets=dict(\n",
    "                editor=dict(\n",
    "                    type=pn.widgets.Ace,\n",
    "                    language='python',\n",
    "                )\n",
    "            )\n",
    "        )\n",
    "    \n",
    "ace = AceTest()\n",
    "ace.view()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Controls\n",
    "\n",
    "The `Ace` widget exposes a number of options which can be changed from both Python and Javascript. Try out the effect of these parameters interactively:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "widget = pn.widgets.Ace(name='Ace', value=py_code, sizing_mode='stretch_both', height=300)\n",
    "\n",
    "pn.Row(widget.controls(jslink=True), widget)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Try changing the filename including a file extension and watch the language automatically update."
   ]
  }
 ],
 "metadata": {
  "language_info": {
   "name": "python",
   "pygments_lexer": "ipython3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
