Created
October 29, 2019 17:05
-
-
Save bollwyvl/836bb8775f351b579b7204eccc15971f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"cells": [ | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"<h1 style=\"font-size: 72px; font-family: 'Lakki Reddy', cursive; color: orange;\">Bringing the Language Server Protocol to Jupyter(Lab)</h1>\n", | |
"\n", | |
"> ## ⸻ @krassowski, @bollwyvl" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# **What is the Language Server Protocol?**\n", | |
"\n", | |
"> _A Language Server is meant to provide the language-specific smarts and communicate with **development tools** over a protocol that enables inter-process communication._\n", | |
">\n", | |
"> _The idea behind the Language Server Protocol (LSP) is to standardize the protocol for how such **servers** and **development tools** communicate. This way, a single **Language Server** can be **re-used** in multiple development tools, which in turn can support **multiple languages** with minimal effort._\n", | |
">\n", | |
"> ## ⸻ [microsoft.github.io/language-server-protocol](https://microsoft.github.io/language-server-protocol)\n", | |
"> _**emphasis** ours_" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## **But Practically...**\n", | |
"- ### **markdown** specification (on the above site)\n", | |
"- ### reference **server**, `vscode-language-server-node`\n", | |
"- ### reference **client**, `vscode`\n", | |
"- ### number of **other clients**\n", | |
"- ### a lot of language **servers**\n", | |
"\n", | |
"> _For more excruciating detail, see this [gist](https://gist.github.com/bollwyvl/7a128978b8ae89ab02bbd5b84d07a4b7)_" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# **What is a Language Server?**\n", | |
"- ## a process that speaks JSON-RPC 2.0 over `stdin`/`stdout` (or sometimes TCP)\n", | |
"- ## the messages are things like\n", | |
" - ### 🙋 I opened a file!\n", | |
" - ### 🤖 YOUR FILE HAS TRAILING WHITESPACE\n", | |
" - ### 🙋 I fixed some whitespace\n", | |
" - ### 🤖 THERE IS NOTHING WRONG NOW\n", | |
" - ### 🙋 I hovered over a symbol!\n", | |
" - ### 🤖 IT'S A FUNCTION\n", | |
" - ### 🙋 Where did it come from?\n", | |
" - ### 🤖 THIS OTHER FILE OVER HERE" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# **Sounds a lot like the Jupyter Message Spec**\n", | |
"- ## Yep\n", | |
"- ## But it's good to have both\n", | |
" - ### **Kernel** (usually) does **dynamic analysis**, so can do More Things \n", | |
" - ### **Language Server** (usually) does **static analysis**, so (usually) faster\n", | |
" - ### Also, it doesn't make sense to have Kernels for some things \n", | |
"- ## **Future** kernels could contribute their own LSP messages" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"<h1 style=\"font-family: 'Lakki Reddy', cursive; font-size: 128px; color: orange;\">SPOOKY DEMO</h1>" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 6, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"'🎃🎃🎃🎃🎃🎃🎃🎃🎃🎃more pumpkins'" | |
] | |
}, | |
"execution_count": 6, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"pumpkins = \"🎃\" * 10\n", | |
"pumpkins + \"more pumpkins\"" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"pumpkins + 2" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 8, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"Chicken = 0\n", | |
"chicken = {\n", | |
" chicken for chicken in range(10)\n", | |
" if chicken in [Chicken] \n", | |
"}" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 10, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"# this_variable_is_not_used - 1" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# **What have we done on [@krassowski/jupyterlab-lsp](https://github.com/krassowski/jupyterlab-lsp)**\n", | |
"- ## Reuse existing LSP <-> CodeMirror bridge\n", | |
"- ## Implement `Jump to Definition`\n", | |
"- ## TypeScript Unit tests on Travis CI\n", | |
"- ## Traitnado-based LSP WebSocket proxy\n", | |
"- ## Python Unit tests and Browser tests on Azure Pipelines\n", | |
"- ## Upstream PRs\n", | |
" - ### `yaml-language-server`\n", | |
" - ### conda-forge (for `r-languageserver`)\n", | |
" - ### `void` on" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# **Next Steps**\n", | |
"- ## Keep putting out releases people can try out\n", | |
"- ## Keep heading towards proposal to JupyterLab core\n", | |
"- ## Encourage some contributors\n", | |
"- ## Add/Test more Language Servers (and Features)\n", | |
"- ## Warm up the [JEP PR #26](https://github.com/jupyter/enhancement-proposals/pull/26)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"%%file spooky.csscss\n", | |
"@import url('https://fonts.googleapis.com/css?family=Lakki+Reddy&display=swap');\n", | |
"#main {\n", | |
" --jp-border-width: 0.01px;\n", | |
" --pumpkin: rgba(245, 124, 0, 0.75);\n", | |
" --ghost: rgba(255, 255, 255, 0.5);\n", | |
"}\n", | |
"#main .cm-lsp-highlight:not(:empty) {\n", | |
" background-color: var(--pumpkin);\n", | |
" border-radius: 5px;\n", | |
" color: yellow !important;\n", | |
" text-shadow: 0 0 5px yellow;\n", | |
" padding: 0.25em 0;\n", | |
" font-weight: bold;\n", | |
" position: relative;\n", | |
" border-left: none;\n", | |
" border-right: none;\n", | |
" transition: all 1s;\n", | |
"}\n", | |
".cm-lsp-highlight:not(:empty)::before {\n", | |
" content: '🍃';\n", | |
" font-size: 0.9em;\n", | |
" top: -0.9em;\n", | |
" left: 50%;\n", | |
" color: green;\n", | |
" position: absolute;\n", | |
" text-shadow: none;\n", | |
" transition: all 1s;\n", | |
"}\n", | |
"#main\n", | |
" .cm-lsp-diagnostic-Error:not(.cm-lsp-highlight):not(.cm-lsp-highlight-Write) {\n", | |
" color: black !important;\n", | |
" background-color: var(--ghost);\n", | |
" border-radius: 1em 1em 0 0;\n", | |
" font-weight: bold;\n", | |
" padding: 0.25em 0.25em 0.1em 0.25em;\n", | |
" position: relative;\n", | |
" text-decoration-color: transparent;\n", | |
" margin: 0 0.2em;\n", | |
" transition: all 1s;\n", | |
"}\n", | |
".cm-lsp-diagnostic-Error:not(.cm-lsp-highlight):not(.cm-lsp-highlight-Write):before {\n", | |
" position: absolute;\n", | |
" left: 0;\n", | |
" right: 0;\n", | |
" top: -10%;\n", | |
" height: 110%;\n", | |
" border-bottom: dotted 2px var(--ghost) !important;\n", | |
" content: '';\n", | |
" transition: all 1s;\n", | |
"}\n", | |
"#main\n", | |
" .cm-lsp-diagnostic-Warning:not(.cm-lsp-highlight-Write):not(.cm-lsp-diagnostic-Error) {\n", | |
" position: relative;\n", | |
" color: green;\n", | |
" font-weight: bold;\n", | |
" text-shadow: 0 0 10px green;\n", | |
" text-decoration: none;\n", | |
" font-size: 2em;\n", | |
" -webkit-text-stroke: 1px rgba(0, 50, 0, 0.5);\n", | |
" font-family: 'Lakki Reddy', cursive;\n", | |
" transition: all 1s;\n", | |
"}\n", | |
"body .jp-HoverBox {\n", | |
" min-width: 300px;\n", | |
" overflow-y: auto;\n", | |
"}\n", | |
"body .jp-HoverBox,\n", | |
"body .jp-HoverBox * {\n", | |
" background-color: black !important;\n", | |
" color: red !important;\n", | |
" font-family: 'Lakki Reddy', cursive;\n", | |
" font-size: 16px !important;\n", | |
" text-align: center;\n", | |
" font-weight: bold;\n", | |
"}" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 2, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<style>@import url('https://fonts.googleapis.com/css?family=Lakki+Reddy&display=swap');\n", | |
"#main {\n", | |
" --jp-border-width: 0.01px;\n", | |
" --pumpkin: rgba(245, 124, 0, 0.75);\n", | |
" --ghost: rgba(255, 255, 255, 0.5);\n", | |
"}\n", | |
"#main .cm-lsp-highlight:not(:empty) {\n", | |
" background-color: var(--pumpkin);\n", | |
" border-radius: 5px;\n", | |
" color: yellow !important;\n", | |
" text-shadow: 0 0 5px yellow;\n", | |
" padding: 0.25em 0;\n", | |
" font-weight: bold;\n", | |
" position: relative;\n", | |
" border-left: none;\n", | |
" border-right: none;\n", | |
" transition: all 1s;\n", | |
"}\n", | |
".cm-lsp-highlight:not(:empty)::before {\n", | |
" content: '🍃';\n", | |
" font-size: 0.9em;\n", | |
" top: -0.9em;\n", | |
" left: 50%;\n", | |
" color: green;\n", | |
" position: absolute;\n", | |
" text-shadow: none;\n", | |
" transition: all 1s;\n", | |
"}\n", | |
"#main\n", | |
" .cm-lsp-diagnostic-Error:not(.cm-lsp-highlight):not(.cm-lsp-highlight-Write) {\n", | |
" color: black !important;\n", | |
" background-color: var(--ghost);\n", | |
" border-radius: 1em 1em 0 0;\n", | |
" font-weight: bold;\n", | |
" padding: 0.25em 0.25em 0.1em 0.25em;\n", | |
" position: relative;\n", | |
" text-decoration-color: transparent;\n", | |
" margin: 0 0.2em;\n", | |
" transition: all 1s;\n", | |
"}\n", | |
".cm-lsp-diagnostic-Error:not(.cm-lsp-highlight):not(.cm-lsp-highlight-Write):before {\n", | |
" position: absolute;\n", | |
" left: 0;\n", | |
" right: 0;\n", | |
" top: -10%;\n", | |
" height: 110%;\n", | |
" border-bottom: dotted 2px var(--ghost) !important;\n", | |
" content: '';\n", | |
" transition: all 1s;\n", | |
"}\n", | |
"#main\n", | |
" .cm-lsp-diagnostic-Warning:not(.cm-lsp-highlight-Write):not(.cm-lsp-diagnostic-Error) {\n", | |
" position: relative;\n", | |
" color: green;\n", | |
" font-weight: bold;\n", | |
" text-shadow: 0 0 10px green;\n", | |
" text-decoration: none;\n", | |
" font-size: 2em;\n", | |
" -webkit-text-stroke: 1px rgba(0, 50, 0, 0.5);\n", | |
" font-family: 'Lakki Reddy', cursive;\n", | |
" transition: all 1s;\n", | |
"}\n", | |
"body .jp-HoverBox {\n", | |
" min-width: 300px;\n", | |
" overflow-y: auto;\n", | |
"}\n", | |
"body .jp-HoverBox,\n", | |
"body .jp-HoverBox * {\n", | |
" background-color: black !important;\n", | |
" color: red !important;\n", | |
" font-family: 'Lakki Reddy', cursive;\n", | |
" font-size: 16px !important;\n", | |
" text-align: center;\n", | |
" font-weight: bold;\n", | |
"}\n", | |
"</style>" | |
], | |
"text/plain": [ | |
"<IPython.core.display.HTML object>" | |
] | |
}, | |
"execution_count": 2, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"import pathlib\n", | |
"import IPython \n", | |
"css = pathlib.Path(\"spooky.css\").read_text()\n", | |
"IPython.display.HTML(f\"<style>{css}</style>\")" | |
] | |
} | |
], | |
"metadata": { | |
"kernelspec": { | |
"display_name": "Python 3", | |
"language": "python", | |
"name": "python3" | |
}, | |
"language_info": { | |
"codemirror_mode": { | |
"name": "ipython", | |
"version": 3 | |
}, | |
"file_extension": ".py", | |
"mimetype": "text/x-python", | |
"name": "python", | |
"nbconvert_exporter": "python", | |
"pygments_lexer": "ipython3", | |
"version": "3.7.3" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 4 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment