"""Python client for Nvim. Client library for talking with Nvim processes via its msgpack-rpc API. """ import logging import os import sys from types import SimpleNamespace as Version from typing import List, Optional, cast, overload from pynvim._version import VERSION, __version__ from pynvim.api import Nvim, NvimError from pynvim.msgpack_rpc import (ErrorResponse, Session, TTransportType, child_session, socket_session, stdio_session, tcp_session) from pynvim.plugin import (Host, autocmd, command, decode, encoding, function, plugin, rpc_export, shutdown_hook) if sys.version_info < (3, 8): from typing_extensions import Literal else: from typing import Literal __all__ = ('tcp_session', 'socket_session', 'stdio_session', 'child_session', 'start_host', 'autocmd', 'command', 'encoding', 'decode', 'function', 'plugin', 'rpc_export', 'Host', 'Nvim', 'NvimError', 'Version', 'VERSION', '__version__', 'shutdown_hook', 'attach', 'setup_logging', 'ErrorResponse', ) def start_host(session: Optional[Session] = None) -> None: """Promote the current process into python plugin host for Nvim. Start msgpack-rpc event loop for `session`, listening for Nvim requests and notifications. It registers Nvim commands for loading/unloading python plugins. The sys.stdout and sys.stderr streams are redirected to Nvim through `session`. That means print statements probably won't work as expected while this function doesn't return. This function is normally called at program startup and could have been defined as a separate executable. It is exposed as a library function for testing purposes only. """ plugins = [] for arg in sys.argv: _, ext = os.path.splitext(arg) if ext == '.py': plugins.append(arg) elif os.path.isdir(arg): init = os.path.join(arg, '__init__.py') if os.path.isfile(init): plugins.append(arg) # This is a special case to support the old workaround of # adding an empty .py file to make a package directory # visible, and it should be removed soon. for path in list(plugins): dup = path + ".py" if os.path.isdir(path) and dup in plugins: plugins.remove(dup) # Special case: the legacy scripthost receives a single relative filename # while the rplugin host will receive absolute paths. if plugins == ["script_host.py"]: name = "script" else: name = "rplugin" setup_logging(name) if not session: session = stdio_session() nvim = Nvim.from_session(session) if nvim.version.api_level < 1: sys.stderr.write("This version of pynvim " "requires nvim 0.1.6 or later") sys.exit(1) host = Host(nvim) host.start(plugins) @overload def attach(session_type: Literal['tcp'], address: str, port: int = 7450) -> Nvim: ... @overload def attach(session_type: Literal['socket'], *, path: str) -> Nvim: ... @overload def attach(session_type: Literal['child'], *, argv: List[str]) -> Nvim: ... @overload def attach(session_type: Literal['stdio']) -> Nvim: ... def attach( session_type: TTransportType, address: Optional[str] = None, port: int = 7450, path: Optional[str] = None, argv: Optional[List[str]] = None, decode: Literal[True] = True ) -> Nvim: """Provide a nicer interface to create python api sessions. Previous machinery to create python api sessions is still there. This only creates a facade function to make things easier for the most usual cases. Thus, instead of: from pynvim import socket_session, Nvim session = tcp_session(address=
, port=