diff --git a/docs/source/index.rst b/docs/source/index.rst index a3833603..fb261c90 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -42,23 +42,10 @@ allows you to write your own `language server`_ in just a few lines of code:: :hidden: :caption: User Guide - pages/tutorial - pages/user-guide - pages/testing - -.. toctree:: - :hidden: - :caption: How To - - Handle Invalid Data - Migrate to v1 - -.. toctree:: - :hidden: - :glob: - :caption: API Reference - - reference/* + tutorial + user-guide + How To + reference .. toctree:: :hidden: @@ -74,7 +61,9 @@ The documentation is divided up into the following sections .. grid:: 1 2 2 2 :gutter: 2 - .. grid-item-card:: User Guide + .. grid-item-card:: Tutorial + :link: /tutorial + :link-type: doc :text-align: center Step-by-step guides on writing your first language server with *pygls*. @@ -87,6 +76,8 @@ The documentation is divided up into the following sections Short, focused articles on how to acheive a particular outcome .. grid-item-card:: API Reference + :link: /reference + :link-type: doc :columns: 12 :text-align: center diff --git a/docs/source/pages/tutorial.rst b/docs/source/pages/tutorial.rst deleted file mode 100644 index 6db7f6c2..00000000 --- a/docs/source/pages/tutorial.rst +++ /dev/null @@ -1,207 +0,0 @@ -.. _tutorial: - -Tutorial -======== - -In order to help you with using *pygls* in VSCode, we have created the `vscode-playground`_ extension. - -.. note:: - - This extension is meant to provide an environment in which you can easily experiment with a *pygls* powered language server. - It is not necessary in order to use *pygls* with other text editors. - - If you decide you want to publish your language server on the VSCode marketplace this - `template extension `__ - from Microsoft a useful starting point. - -Prerequisites -------------- - -In order to setup and run the example VSCode extension, you need following software -installed: - -* `Visual Studio Code `_ editor -* `Python 3.8+ `_ -* `vscode-python `_ extension -* A clone of the `pygls `_ repository - -.. note:: - If you have created virtual environment, make sure that you have *pygls* installed - and `selected appropriate python interpreter `_ - for the *pygls* project. - - -Running the Example -------------------- - -For a step-by-step guide on how to setup and run the example follow `README`_. - -Hacking the Extension ---------------------- - -When you have successfully setup and run the extension, open `server.py`_ and -go through the code. - -We have implemented following capabilities: - -- ``textDocument/completion`` feature -- ``countDownBlocking`` command -- ``countDownNonBlocking`` command -- ``textDocument/didChange`` feature -- ``textDocument/didClose`` feature -- ``textDocument/didOpen`` feature -- ``showConfigurationAsync`` command -- ``showConfigurationCallback`` command -- ``showConfigurationThread`` command - -When running the extension in *debug* mode, you can set breakpoints to see -when each of above mentioned actions gets triggered. - -Visual Studio Code supports *Language Server Protocol*, which means, that every -action on the client-side, will result in sending request or notification to -the server via JSON RPC. - -Debug Code Completions -~~~~~~~~~~~~~~~~~~~~~~ - -Set a breakpoint inside ``completion`` function and go back to opened *json* -file in your editor. Now press ``ctrl + space`` (``control + space`` on mac) to -show completion list and you will hit the breakpoint. When you continue -debugging, the completion list pop-up won't show up because it was closing when -the editor lost focus. - -Similarly, you can debug any feature or command. - -Keep the breakpoint and continue to the next section. - -Blocking Command Test -~~~~~~~~~~~~~~~~~~~~~ - -In order to demonstrate you that blocking the language server will reject other -requests, we have registered a custom command which counts down 10 seconds and -sends notification messages to the client. - -1. Press **F1**, find and run ``Count down 10 seconds [Blocking]`` command. -2. Try to show *code completions* while counter is still ticking. - -Language server is **blocked**, because ``time.sleep`` is a -**blocking** operation. This is why you didn't hit the breakpoint this time. - -.. hint:: - - To make this command **non blocking**, add ``@json_server.thread()`` - decorator, like in code below: - - .. code-block:: python - - @json_server.thread() - @json_server.command(JsonLanguageServer.CMD_COUNT_DOWN_BLOCKING) - def count_down_10_seconds_blocking(ls, *args): - # Omitted - - *pygls* uses a **thread pool** to execute functions that are marked with - a ``thread`` decorator. - - -Non-Blocking Command Test -~~~~~~~~~~~~~~~~~~~~~~~~~ - -Python 3.4 introduced *asyncio* module which allows us to use asynchronous -functions (aka *coroutines*) and do `cooperative multitasking`_. Using the -`await` keyword inside your coroutine will give back control to the -scheduler and won't block the main thread. - -1. Press **F1** and run the ``Count down 10 seconds [Non Blocking]`` command. -2. Try to show *code completions* while counter is still ticking. - -Bingo! We hit the breakpoint! What just happened? - -The language server was **not blocked** because we used ``asyncio.sleep`` this -time. The language server was executing *just* in the *main* thread. - - -Text Document Operations -~~~~~~~~~~~~~~~~~~~~~~~~ - -Opening and closing a JSON file will display appropriate notification message -in the bottom right corner of the window and the file content will be -validated. Validation will be performed on content changes, as well. - -Show Configuration Data -~~~~~~~~~~~~~~~~~~~~~~~ - -There are *three* ways for getting configuration section from the client -settings. - -.. note:: - - *pygls*' built-in coroutines are suffixed with *async* word, which means that - you have to use the *await* keyword in order to get the result (instead of - *asyncio.Future* object). - -- **Get the configuration inside a coroutine** - -.. code-block:: python - - config = await ls.get_configuration_async(ConfigurationParams([ - ConfigurationItem('', JsonLanguageServer.CONFIGURATION_SECTION) - ])) - -- **Get the configuration inside a normal function** - -We already saw that we *don't* want to block the main thread. Sending the -configuration request to the client will result with the response from it, but -we don't know when. You have to pass *callback* function which will be -triggered once response from the client is received. - -.. code-block:: python - - def _config_callback(config): - try: - example_config = config[0].exampleConfiguration - - ls.show_message( - f'jsonServer.exampleConfiguration value: {example_config}' - ) - - except Exception as e: - ls.show_message_log(f'Error ocurred: {e}') - - ls.get_configuration(ConfigurationParams([ - ConfigurationItem('', JsonLanguageServer.CONFIGURATION_SECTION) - ]), _config_callback) - -As you can see, the above code is hard to read. - -- **Get the configuration inside a threaded function** - -Blocking operations such as ``future.result(1)`` should not be used inside -normal functions, but to increase the code readability, you can add the -*thread* decorator to your function to use *pygls*' *thread pool*. - -.. code-block:: python - - @json_server.thread() - @json_server.command(JsonLanguageServer.CMD_SHOW_CONFIGURATION_THREAD) - def show_configuration_thread(ls: JsonLanguageServer, *args): - """Gets exampleConfiguration from the client settings using a thread pool.""" - try: - config = ls.get_configuration(ConfigurationParams([ - ConfigurationItem('', JsonLanguageServer.CONFIGURATION_SECTION) - ])).result(2) - - # ... - -This way you won't block the main thread. *pygls* will start a new thread when -executing the function. - -Modify the Example -~~~~~~~~~~~~~~~~~~ - -We encourage you to continue to :ref:`user guide ` and -modify this example. - -.. _vscode-playground: https://github.com/openlawlibrary/pygls/blob/main/examples/vscode-playground -.. _README: https://github.com/openlawlibrary/pygls/blob/main/examples/vscode-playground/README.md -.. _server.py: https://github.com/openlawlibrary/pygls/blob/main/examples/servers/json_server.py -.. _cooperative multitasking: https://en.wikipedia.org/wiki/Cooperative_multitasking diff --git a/docs/source/tutorial.rst b/docs/source/tutorial.rst new file mode 100644 index 00000000..77fdbab0 --- /dev/null +++ b/docs/source/tutorial.rst @@ -0,0 +1,12 @@ +.. _tutorial: + +Tutorial +======== + +Here we have a tutorial + +.. toctree:: + :glob: + :maxdepth: 1 + + tutorial/* diff --git a/docs/source/tutorial/0-setup.rst b/docs/source/tutorial/0-setup.rst new file mode 100644 index 00000000..c2642e0e --- /dev/null +++ b/docs/source/tutorial/0-setup.rst @@ -0,0 +1,16 @@ +Project Setup +============= + +By the end of this stage you will have everything you need setup in order to follow the rest of this tutorial, including a simple "Hello, World" language server. + +**Required Software** + +Before continuing with the setup you need following software installed: + +* `Visual Studio Code `__ +* `Python 3.8+ `__ +* `Node JS 18+ `__ +* `Git `__ + +Your First Language Server +-------------------------- diff --git a/docs/source/pages/testing.rst b/docs/source/tutorial/y-testing.rst similarity index 100% rename from docs/source/pages/testing.rst rename to docs/source/tutorial/y-testing.rst diff --git a/docs/source/tutorial/z-next-steps.rst b/docs/source/tutorial/z-next-steps.rst new file mode 100644 index 00000000..24c599a4 --- /dev/null +++ b/docs/source/tutorial/z-next-steps.rst @@ -0,0 +1,6 @@ +Next Steps +========== + +If you decide you want to publish your language server on the VSCode marketplace this +`template extension `__ +from Microsoft a useful starting point. diff --git a/docs/source/pages/user-guide.rst b/docs/source/user-guide.rst similarity index 100% rename from docs/source/pages/user-guide.rst rename to docs/source/user-guide.rst