Skip to content

Commit

Permalink
feat: add pygls.cli.start_server
Browse files Browse the repository at this point in the history
This takes the simple cli wrapper from the example `json_server.py`
and puts it into a new `pygls.cli` module.

The wrapper makes it easier to select which transport mechanism the
server should use. It's primary intention is simply to reduce the
amount of boilerplate required to start one of the example servers
  • Loading branch information
alcarney committed Oct 7, 2024
1 parent 7de0ae5 commit 64a87d2
Show file tree
Hide file tree
Showing 17 changed files with 76 additions and 50 deletions.
10 changes: 1 addition & 9 deletions docs/source/examples/json-server.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,4 @@ JSON Server
===========

.. example-server:: json_server.py
:start-at: import argparse








:start-at: import asyncio
3 changes: 2 additions & 1 deletion examples/servers/code_actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"""

import re
from pygls.cli import start_server
from pygls.lsp.server import LanguageServer
from lsprotocol import types

Expand Down Expand Up @@ -74,4 +75,4 @@ def code_actions(params: types.CodeActionParams):


if __name__ == "__main__":
server.start_io()
start_server(server)
3 changes: 2 additions & 1 deletion examples/servers/code_lens.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@

from lsprotocol import types

from pygls.cli import start_server
from pygls.lsp.server import LanguageServer

ADDITION = re.compile(r"^\s*(\d+)\s*\+\s*(\d+)\s*=(?=\s*$)")
Expand Down Expand Up @@ -140,4 +141,4 @@ def evaluate_sum(ls: LanguageServer, args):

if __name__ == "__main__":
logging.basicConfig(level=logging.INFO, format="%(message)s")
server.start_io()
start_server(server)
3 changes: 2 additions & 1 deletion examples/servers/colors.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@

from lsprotocol import types

from pygls.cli import start_server
from pygls.lsp.server import LanguageServer

COLOR = re.compile(r"""\#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})(?!\w)""")
Expand Down Expand Up @@ -112,4 +113,4 @@ def color_presentation(params: types.ColorPresentationParams):

if __name__ == "__main__":
logging.basicConfig(level=logging.INFO, format="%(message)s")
server.start_io()
start_server(server)
4 changes: 2 additions & 2 deletions examples/servers/formatting.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import attrs
from lsprotocol import types

from pygls.cli import start_server
from pygls.lsp.server import LanguageServer
from pygls.workspace import TextDocument

Expand Down Expand Up @@ -194,5 +195,4 @@ def skip_line(line: int, range_: Optional[types.Range]) -> bool:

if __name__ == "__main__":
logging.basicConfig(level=logging.INFO, format="%(message)s")

server.start_io()
start_server(server)
3 changes: 2 additions & 1 deletion examples/servers/goto.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@

from lsprotocol import types

from pygls.cli import start_server
from pygls.lsp.server import LanguageServer
from pygls.workspace import TextDocument

Expand Down Expand Up @@ -210,4 +211,4 @@ def find_references(ls: GotoLanguageServer, params: types.ReferenceParams):

if __name__ == "__main__":
logging.basicConfig(level=logging.INFO, format="%(message)s")
server.start_io()
start_server(server)
4 changes: 2 additions & 2 deletions examples/servers/hover.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

from lsprotocol import types

from pygls.cli import start_server
from pygls.lsp.server import LanguageServer

DATE_FORMATS = [
Expand Down Expand Up @@ -84,5 +85,4 @@ def hover(ls: LanguageServer, params: types.HoverParams):

if __name__ == "__main__":
logging.basicConfig(level=logging.INFO, format="%(message)s")

server.start_io()
start_server(server)
3 changes: 2 additions & 1 deletion examples/servers/inlay_hints.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
from typing import Optional

from lsprotocol import types
from pygls.cli import start_server
from pygls.lsp.server import LanguageServer

NUMBER = re.compile(r"\d+")
Expand Down Expand Up @@ -91,4 +92,4 @@ def inlay_hint_resolve(hint: types.InlayHint):


if __name__ == "__main__":
server.start_io()
start_server(server)
26 changes: 2 additions & 24 deletions examples/servers/json_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,14 @@
guides.
"""

import argparse
import asyncio
import uuid
from functools import partial
from typing import Optional

from lsprotocol import types as lsp

from pygls.cli import start_server
from pygls.lsp.server import LanguageServer


Expand Down Expand Up @@ -232,27 +232,5 @@ def show_configuration_thread(ls: JsonLanguageServer, *args):
handle_config(ls, config)


def add_arguments(parser):
parser.description = "simple json server example"

parser.add_argument("--tcp", action="store_true", help="Use TCP server")
parser.add_argument("--ws", action="store_true", help="Use WebSocket server")
parser.add_argument("--host", default="127.0.0.1", help="Bind to this address")
parser.add_argument("--port", type=int, default=2087, help="Bind to this port")


def main():
parser = argparse.ArgumentParser()
add_arguments(parser)
args = parser.parse_args()

if args.tcp:
json_server.start_tcp(args.host, args.port)
elif args.ws:
json_server.start_ws(args.host, args.port)
else:
json_server.start_io()


if __name__ == "__main__":
main()
start_server(json_server)
3 changes: 2 additions & 1 deletion examples/servers/links.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@

from lsprotocol import types

from pygls.cli import start_server
from pygls.lsp.server import LanguageServer

LINK = re.compile(r"<(\w+):([^>]+)>")
Expand Down Expand Up @@ -91,4 +92,4 @@ def document_link_resolve(link: types.DocumentLink):

if __name__ == "__main__":
logging.basicConfig(level=logging.INFO, format="%(message)s")
server.start_io()
start_server(server)
3 changes: 2 additions & 1 deletion examples/servers/publish_diagnostics.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

from lsprotocol import types

from pygls.cli import start_server
from pygls.lsp.server import LanguageServer
from pygls.workspace import TextDocument

Expand Down Expand Up @@ -117,4 +118,4 @@ def did_change(ls: PublishDiagnosticServer, params: types.DidOpenTextDocumentPar

if __name__ == "__main__":
logging.basicConfig(level=logging.INFO, format="%(message)s")
server.start_io()
start_server(server)
3 changes: 2 additions & 1 deletion examples/servers/pull_diagnostics.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@

from lsprotocol import types

from pygls.cli import start_server
from pygls.lsp.server import LanguageServer
from pygls.workspace import TextDocument

Expand Down Expand Up @@ -160,4 +161,4 @@ def workspace_diagnostic(

if __name__ == "__main__":
logging.basicConfig(level=logging.INFO, format="%(message)s")
server.start_io()
start_server(server)
3 changes: 2 additions & 1 deletion examples/servers/rename.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@

from lsprotocol import types

from pygls.cli import start_server
from pygls.lsp.server import LanguageServer
from pygls.workspace import TextDocument

Expand Down Expand Up @@ -155,4 +156,4 @@ def prepare_rename(ls: RenameLanguageServer, params: types.PrepareRenameParams):

if __name__ == "__main__":
logging.basicConfig(level=logging.DEBUG, format="%(message)s")
server.start_io()
start_server(server)
4 changes: 2 additions & 2 deletions examples/servers/semantic_tokens.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import attrs
from lsprotocol import types

from pygls.cli import start_server
from pygls.lsp.server import LanguageServer
from pygls.workspace import TextDocument

Expand Down Expand Up @@ -299,5 +300,4 @@ def semantic_tokens_full(ls: SemanticTokensServer, params: types.SemanticTokensP

if __name__ == "__main__":
logging.basicConfig(level=logging.INFO, format="%(message)s")

server.start_io()
start_server(server)
3 changes: 2 additions & 1 deletion examples/servers/symbols.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@

from lsprotocol import types

from pygls.cli import start_server
from pygls.lsp.server import LanguageServer
from pygls.workspace import TextDocument

Expand Down Expand Up @@ -245,4 +246,4 @@ def workspace_symbol(ls: SymbolsLanguageServer, params: types.WorkspaceSymbolPar

if __name__ == "__main__":
logging.basicConfig(level=logging.INFO, format="%(message)s")
server.start_io()
start_server(server)
3 changes: 2 additions & 1 deletion examples/servers/threaded_handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

from lsprotocol import types

from pygls.cli import start_server
from pygls.lsp.server import LanguageServer

server = LanguageServer("threaded-server", "v1")
Expand Down Expand Up @@ -92,4 +93,4 @@ def count_down_error(ls: LanguageServer, *args):


if __name__ == "__main__":
server.start_io()
start_server(server)
45 changes: 45 additions & 0 deletions pygls/cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
############################################################################
# Copyright(c) Open Law Library. All rights reserved. #
# See ThirdPartyNotices.txt in the project root for additional notices. #
# #
# Licensed under the Apache License, Version 2.0 (the "License") #
# you may not use this file except in compliance with the License. #
# You may obtain a copy of the License at #
# #
# http: // www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
############################################################################
"""A simple cli wrapper for pygls servers."""
from __future__ import annotations

import argparse
import typing

if typing.TYPE_CHECKING:
from pygls.server import JsonRPCServer


def start_server(server: JsonRPCServer, args: list[str] | None = None):
"""A helper function that implements a simple cli wrapper for a pygls server
allowing the user to select between the supported transports."""

name = type(server).__name__
parser = argparse.ArgumentParser(description=f"start a {name} instance")
parser.add_argument("--tcp", action="store_true", help="start a TCP server")
parser.add_argument("--ws", action="store_true", help="start a WebSocket server")
parser.add_argument("--host", default="127.0.0.1", help="bind to this address")
parser.add_argument("--port", type=int, default=8888, help="bind to this port")

arguments = parser.parse_args(args)

if arguments.tcp:
server.start_tcp(arguments.host, arguments.port)
elif arguments.ws:
server.start_ws(arguments.host, arguments.port)
else:
server.start_io()

0 comments on commit 64a87d2

Please sign in to comment.