Skip to content

Commit

Permalink
Expose a number of cli arguments (#116)
Browse files Browse the repository at this point in the history
- `--cache-dir`, optionally allows for Language Clients to specify
  the directory where cached data should be stored. If not given the
  Language Server will choose a directory based on a hash of the
  `conf.py`'s filepath. Closes #115 
- `--hide-sphinx-output`, allows for Language Clients to prevent
  Sphinx's build log from being shown.
- `--log-filter`, allows for Language Clients to restrict log output
  to specific loggers. Can be given multiple times. Closes #113 
- `--log-level`, allows for Language Clients to specify the
  verbosity of the log they wish to receive. Closes #87 
- `-p`, `--port`, allows for Language Clients to interact with the
  Language Server over TCP, while setting the port number they wish
  to use. Closes #114
  • Loading branch information
alcarney authored Feb 25, 2021
1 parent 8771669 commit 72fbbf3
Show file tree
Hide file tree
Showing 7 changed files with 101 additions and 29 deletions.
4 changes: 4 additions & 0 deletions lib/esbonio/changes/113.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Add ``log-filter`` cli argument that allows Language Clients to choose
which loggers they want to recieve messages from. Also add
``--hide-sphinx-output`` cli argument that can suppress Sphinx's build
log as it it handled separately.
2 changes: 2 additions & 0 deletions lib/esbonio/changes/114.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Add ``-p``, ``--port`` cli arguments that start the Language Server in
TCP mode while specifying the port number to listen on.
2 changes: 2 additions & 0 deletions lib/esbonio/changes/115.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Add ``--cache-dir`` cli argument that allows Language Clients to
specify where cached data should be stored e.g. Sphinx's build output.
2 changes: 2 additions & 0 deletions lib/esbonio/changes/87.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Add ``--log-level`` cli argument that allows Language Clients to
control the verbosity of the Language Server's log output.
96 changes: 72 additions & 24 deletions lib/esbonio/esbonio/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,64 +5,112 @@
import esbonio.lsp as lsp

from esbonio import __version__
from esbonio.lsp import RstLanguageServer
from esbonio.lsp.logger import LspHandler

LOG_LEVELS = [logging.ERROR, logging.INFO, logging.DEBUG]
LOG_LEVELS = {
"debug": logging.DEBUG,
"error": logging.ERROR,
"info": logging.INFO,
}


def configure_logging(verbose, server):
class LogFilter:
"""A log filter that accepts message from any of the listed logger names."""

try:
level = LOG_LEVELS[-1]
except IndexError:
level = LOG_LEVELS[-1]
def __init__(self, names):
self.names = names

def filter(self, record):
return any(record.name == name for name in self.names)


def configure_logging(args, server: RstLanguageServer):

level = LOG_LEVELS[args.log_level]

lsp_logger = logging.getLogger("esbonio.lsp")
lsp_logger.setLevel(level)

lsp_handler = LspHandler(server)
lsp_handler.setLevel(level)

if args.log_filter is not None:
lsp_handler.addFilter(LogFilter(args.log_filter))

formatter = logging.Formatter("[%(name)s] %(message)s")
lsp_handler.setFormatter(formatter)
lsp_logger.addHandler(lsp_handler)

sphinx_logger = logging.getLogger("esbonio.sphinx")
sphinx_logger.setLevel(level)
if not args.hide_sphinx_output:
sphinx_logger = logging.getLogger("esbonio.sphinx")
sphinx_logger.setLevel(logging.INFO)

sphinx_handler = LspHandler(server)
sphinx_handler.setLevel(level)
sphinx_handler = LspHandler(server)
sphinx_handler.setLevel(logging.INFO)

formatter = logging.Formatter("%(message)s")
sphinx_handler.setFormatter(formatter)
sphinx_logger.addHandler(sphinx_handler)
formatter = logging.Formatter("%(message)s")
sphinx_handler.setFormatter(formatter)
sphinx_logger.addHandler(sphinx_handler)


def start_server(verbose):
def start_server(args):
"""Start the language server."""

server = lsp.create_language_server(lsp.BUILTIN_MODULES)
configure_logging(verbose, server)
server.start_io()
server = lsp.create_language_server(lsp.BUILTIN_MODULES, cache_dir=args.cache_dir)
configure_logging(args, server)

if args.port:
server.start_tcp("localhost", args.port)
else:
server.start_io()


cli = argparse.ArgumentParser(prog="esbonio", description="The Esbonio language server")

cli.add_argument(
"--version", action="store_true", help="print the current version and exit"
"--cache-dir",
default=None,
type=str,
help="the directory where cached data should be stored, e.g. Sphinx build output ",
)

cli.add_argument(
"-v",
"--verbose",
action="count",
default=0,
help="increase output verbosity, repeatable e.g. -v, -vv, -vvv, ...",
"--hide-sphinx-output",
action="store_true",
help="hide sphinx build output from the log",
)

cli.add_argument(
"--log-filter",
action="append",
help="only include log messages from loggers with the given name,"
+ "can be set multiple times.",
)

cli.add_argument(
"--log-level",
choices=["error", "info", "debug"],
default="error",
help="set the level of log message to show from the language server",
)

cli.add_argument(
"-p",
"--port",
type=int,
default=None,
help="start a TCP instance of the language server listening on the given port ",
)

cli.add_argument(
"--version", action="store_true", help="print the current version and exit"
)

args = cli.parse_args()

if args.version:
print("v{}".format(__version__))
sys.exit(0)

start_server(args.verbose)
start_server(args)
13 changes: 10 additions & 3 deletions lib/esbonio/esbonio/lsp/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,12 @@ def __init__(self, rst: "RstLanguageServer"):


class RstLanguageServer(LanguageServer):
def __init__(self, *args, **kwargs):
def __init__(self, cache_dir=None, *args, **kwargs):
super().__init__(*args, **kwargs)

self.cache_dir = cache_dir
"""The folder to store cached data in."""

self.logger = logging.getLogger(__name__)
"""The logger that should be used for all Language Server log entries"""

Expand Down Expand Up @@ -121,15 +124,19 @@ def default(obj):
return json.dumps(obj, default=default)


def create_language_server(modules: List[str]) -> RstLanguageServer:
def create_language_server(
modules: List[str], cache_dir: Optional[str] = None
) -> RstLanguageServer:
"""Create a new language server instance.
Parameters
----------
modules:
The list of modules that should be loaded.
cache_dir:
The folder to use for cached data.
"""
server = RstLanguageServer()
server = RstLanguageServer(cache_dir)

for mod in modules:
server.load_module(mod)
Expand Down
11 changes: 9 additions & 2 deletions lib/esbonio/esbonio/lsp/sphinx.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""Code for managing sphinx applications."""
import collections
import hashlib
import logging
import pathlib
import re
Expand Down Expand Up @@ -182,8 +183,14 @@ def create_app(self):

src = conf_py.parent

# TODO: Create a unique scratch space based on the project.
build = appdirs.user_cache_dir("esbonio", "swyddfa")
if self.rst.cache_dir is not None:
build = self.rst.cache_dir
else:
# Try to pick a sensible dir based on the project's location
cache = appdirs.user_cache_dir("esbonio", "swyddfa")
project = hashlib.md5(str(src).encode()).hexdigest()
build = pathlib.Path(cache) / project

doctrees = pathlib.Path(build) / "doctrees"

self.rst.logger.debug("Config dir %s", src)
Expand Down

0 comments on commit 72fbbf3

Please sign in to comment.