Skip to content

Commit 25939fe

Browse files
committed
doc: update examples and README
1 parent 3155575 commit 25939fe

File tree

4 files changed

+68
-67
lines changed

4 files changed

+68
-67
lines changed

README.md

Lines changed: 64 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -5,113 +5,114 @@
55
[![Documentation](https://img.shields.io/badge/docs-pdoc-blue)](https://observerw.github.io/lsp-client/)
66
[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/observerw/lsp-client)
77

8-
A full-featured, well-typed, and easy-to-use Python client for the Language Server Protocol (LSP). This library provides a clean, async-first interface for interacting with language servers, supporting both local and container-based runtimes.
8+
A production-ready, async-first Python client for the Language Server Protocol (LSP). Built for developers who need fine-grained control, container isolation, and extensibility when integrating language intelligence into their tools.
99

1010
## Why lsp-client?
1111

12-
`lsp-client` is designed specifically for developers who need **high control**, **isolation**, and **extensibility**:
12+
`lsp-client` is engineered for developers building **production-grade tooling** that requires precise control over language server environments:
1313

14-
- **🐳 Native Container Support**: Unlike other clients that focus on local process management, `lsp-client` treats containers as a first-class citizen. It handles the "magic" of mounting workspaces, translating file paths between your host and the container, and managing container lifecycles. Pre-built containers are available for all supported language servers.
15-
- **🧩 SDK for Custom Tooling**: Instead of being a closed wrapper, this is a true SDK. Our **Modular Capability System** allows you to build custom clients by mixing and matching only the LSP features you need, or even adding your own protocol extensions seamlessly.
16-
- **🛠️ Explicit over Implicit**: We prioritize predictable environments. While other tools might auto-download binaries, `lsp-client` gives you full control over your server environment (Local or Container), making it ideal for production-grade tools where version pinning is critical.
17-
- **⚡ Modern Async-First Architecture**: Built from the ground up for Python 3.12+, utilizing advanced async patterns to ensure high-performance concurrent operations without blocking your main event loop.
18-
19-
## Features
20-
21-
- **🚀 Environment Agnostic**: Seamlessly switch between local processes and isolated containers.
22-
- **🔧 Full LSP 3.17 Support**: Comprehensive implementation of the latest protocol specification.
23-
- **🎯 Specialized Clients**: Out-of-the-box support for popular servers (Pyright, Deno, Rust-Analyzer, etc.).
24-
- **📝 Zero-Config Capabilities**: Automatically manages complex protocol handshakes and feature negotiations.
25-
- **🧩 Pluggable & Modular**: Easily extend functionality or add support for custom LSP extensions.
26-
- **🔒 Production-Grade Reliability**: Robust error handling, automatic retries, and full type safety.
14+
- **🐳 Container-First Architecture**: Containers as first-class citizens with workspace mounting, path translation, and lifecycle management. Pre-built images available, seamless switching between local and container environments.
15+
- **🧩 Intelligent Capability Management**: Zero-overhead mixin system with automatic registration, negotiation, and availability checks. Only access methods for registered capabilities.
16+
- **🎯 Complete LSP 3.17 Support**: Full specification implementation with pre-configured clients for Pyright, Rust-Analyzer, Deno, TypeScript, and Pyrefly.
17+
- **⚡ Production-Ready & Modern**: Explicit environment control with no auto-downloads. Built with async patterns, comprehensive error handling, retries, and full type safety.
2718

2819
## Quick Start
2920

3021
### Installation
3122

3223
```bash
24+
# Recommended: Use uv for modern Python dependency management
3325
uv add lsp-client
26+
27+
# Or with pip
28+
pip install lsp-client
3429
```
3530

36-
### Basic Usage
31+
### Local Language Server
32+
33+
The following code snippet can be run as-is, try it out:
3734

3835
```python
39-
from pathlib import Path
36+
# install pyrefly with `uv tool install pyrefly` first
4037
import anyio
4138
from lsp_client import Position
42-
from lsp_client.clients.pyright import PyrightClient, PyrightLocalServer
39+
from lsp_client.clients.pyrefly import PyreflyClient
4340

4441
async def main():
45-
workspace = Path.cwd()
46-
async with PyrightClient(
47-
workspace=workspace,
48-
server=PyrightLocalServer(),
49-
) as client:
50-
# Find definition of something at line 11, character 28 in a file
51-
refs = await client.request_definition_locations(
52-
file_path="src/main.py",
53-
position=Position(11, 28) # line 12, character 29 (1-indexed)
42+
async with PyreflyClient() as client:
43+
refs = await client.request_references(
44+
file_path="example.py",
45+
position=Position(10, 5)
5446
)
55-
56-
if not refs:
57-
print("No definition found.")
58-
return
59-
6047
for ref in refs:
61-
print(f"Found definition at: {ref.uri} - Range: {ref.range}")
48+
print(f"Reference at {ref.uri}: {ref.range}")
6249

63-
if __name__ == "__main__":
64-
anyio.run(main)
50+
anyio.run(main)
6551
```
6652

6753
### Container-based Language Server
6854

6955
```python
70-
from pathlib import Path
71-
import anyio
72-
from lsp_client import Position
73-
from lsp_client.clients.pyright import PyrightClient, PyrightContainerServer
74-
7556
async def main():
7657
workspace = Path.cwd()
7758
async with PyrightClient(
78-
workspace=workspace,
7959
server=PyrightContainerServer(mounts=[workspace]),
60+
workspace=workspace
8061
) as client:
81-
# Find definition of something at line 11, character 28 in a file
82-
refs = await client.request_definition_locations(
83-
file_path="src/main.py",
84-
position=Position(11, 28)
62+
# Find definition of a symbol
63+
definitions = await client.request_definition_locations(
64+
file_path="example.py",
65+
position=Position(10, 5)
8566
)
67+
for def_loc in definitions:
68+
print(f"Definition at {def_loc.uri}: {def_loc.range}")
8669

87-
if not refs:
88-
print("No definition found.")
89-
return
70+
anyio.run(main)
71+
```
9072

91-
for ref in refs:
92-
print(f"Found definition at: {ref.uri} - Range: {ref.range}")
73+
### More Examples
74+
75+
The `examples/` directory contains comprehensive usage examples:
76+
77+
- `pyright_docker.py` - Using Pyright in Docker for Python analysis
78+
- `rust_analyzer.py` - Rust code intelligence with Rust-Analyzer
79+
- `pyrefly.py` - Python linting and analysis with Pyrefly
80+
- `protocol.py` - Direct LSP protocol usage
81+
82+
Run examples with:
9383

94-
if __name__ == "__main__":
95-
anyio.run(main)
84+
```bash
85+
uv run examples/pyright_docker.py
9686
```
9787

9888
## Supported Language Servers
9989

100-
The library includes pre-configured clients for popular language servers:
101-
102-
| Language Server | Module Path | Language | Container Image |
103-
| -------------------------- | ---------------------------------- | --------------------- | ---------------------------------------- |
104-
| Pyright | `lsp_client.clients.pyright` | Python | `ghcr.io/observerw/lsp-client/pyright` |
105-
| Pyrefly | `lsp_client.clients.pyrefly` | Python | `ghcr.io/observerw/lsp-client/pyrefly` |
90+
| Language Server | Module Path | Language | Container Image |
91+
| -------------------------- | ---------------------------------- | --------------------- | -------------------------------------------- |
92+
| Pyright | `lsp_client.clients.pyright` | Python | `ghcr.io/observerw/lsp-client/pyright` |
93+
| Pyrefly | `lsp_client.clients.pyrefly` | Python | `ghcr.io/observerw/lsp-client/pyrefly` |
10694
| Rust Analyzer | `lsp_client.clients.rust_analyzer` | Rust | `ghcr.io/observerw/lsp-client/rust-analyzer` |
107-
| Deno | `lsp_client.clients.deno` | TypeScript/JavaScript | `ghcr.io/observerw/lsp-client/deno` |
108-
| TypeScript Language Server | `lsp_client.clients.typescript` | TypeScript/JavaScript | `ghcr.io/observerw/lsp-client/typescript` |
95+
| Deno | `lsp_client.clients.deno` | TypeScript/JavaScript | `ghcr.io/observerw/lsp-client/deno` |
96+
| TypeScript Language Server | `lsp_client.clients.typescript` | TypeScript/JavaScript | `ghcr.io/observerw/lsp-client/typescript` |
97+
98+
Container images are automatically updated weekly to ensure access to the latest language server versions.
10999

110-
Containers are automatically updated weekly to ensure you always have the latest versions.
100+
### Key Benefits
101+
102+
1. **Method Safety**: You can only call methods for capabilities you've registered. No runtime surprises from unavailable capabilities.
103+
2. **Automatic Registration**: The mixin system automatically handles client registration, capability negotiation, and availability checks behind the scenes.
104+
3. **Zero Boilerplate**: No manual capability checking, no complex initialization logic, no error handling for missing capabilities.
105+
4. **Type Safety**: Full type annotations ensure you get compile-time guarantees about available methods.
106+
5. **Composability**: Mix and match exactly the capabilities you need, creating perfectly tailored clients.
111107

112108
## Contributing
113109

114-
We welcome contributions! Please see our [Contributing Guide](docs/contribution/) for details.
110+
We welcome contributions! Please see our [Contributing Guide](docs/contribution/) for details on:
111+
112+
- Adding new language server support
113+
- Extending protocol capabilities
114+
- Container image updates
115+
- Development workflow
115116

116117
## License
117118

@@ -121,4 +122,4 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file
121122

122123
- Built on the [Language Server Protocol](https://microsoft.github.io/language-server-protocol/) specification
123124
- Uses [lsprotocol](https://github.com/microsoft/lsprotocol) for LSP type definitions
124-
- Inspired by [multilspy](https://github.com/microsoft/multilspy) and other LSP clients
125+
- Architecture inspired by [multilspy](https://github.com/microsoft/multilspy) and other LSP clients

examples/pyrefly.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,15 @@
1010

1111
import lsp_client
1212
from lsp_client import Position, Range
13-
from lsp_client.clients.pyrefly import PyreflyClient, PyreflyLocalServer
13+
from lsp_client.clients.pyrefly import PyreflyClient
1414

1515
lsp_client.enable_logging()
1616

1717

1818
async def main():
1919
# Initialize Pyrefly client with local server
2020
# if `workspace` not specified, defaults to current working directory
21-
async with PyreflyClient(server=PyreflyLocalServer()) as client:
21+
async with PyreflyClient() as client:
2222
# Request references to PyreflyClient at line 22, column 20
2323
refs = await client.request_references(
2424
file_path="src/lsp_client/clients/pyrefly.py",

examples/rust_analyzer.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@
99
import anyio
1010

1111
import lsp_client
12-
from lsp_client.clients.rust_analyzer import RustAnalyzerClient, RustAnalyzerLocalServer
12+
from lsp_client.clients.rust_analyzer import RustAnalyzerClient
1313

1414
lsp_client.enable_logging()
1515

1616

1717
async def main():
1818
# Initialize Rust Analyzer client with local server
19-
async with RustAnalyzerClient(server=RustAnalyzerLocalServer()) as client:
19+
async with RustAnalyzerClient() as client:
2020
# Get and display the language ID for this client
2121
# This should return "rust" for Rust Analyzer
2222
print(client.get_language_id())

0 commit comments

Comments
 (0)