all repos

clerk @ 8063300

missing tooling for ledger/hledger

clerk/internal/lsp/lsp.go (view raw)

Oleksandr Smirnov Oleksandr Smirnov
olexsmir@gmail.com
lsp: write logs to file, 2 months ago
1
package lsp
2
3
import (
4
	"context"
5
	"io"
6
	"log/slog"
7
	"os"
8
	"path/filepath"
9
10
	"go.lsp.dev/jsonrpc2"
11
	"go.lsp.dev/protocol"
12
	"go.lsp.dev/uri"
13
14
	"olexsmir.xyz/clerk/internal/linter"
15
	"olexsmir.xyz/clerk/internal/xdg"
16
	"olexsmir.xyz/clerk/journal"
17
	"olexsmir.xyz/clerk/journal/printer"
18
)
19
20
type Server struct{ server *server }
21
22
func NewServer(version string) Server {
23
	var logger *slog.Logger
24
	logFile, err := openLogFile()
25
	if err == nil {
26
		logger = slog.New(slog.NewTextHandler(logFile, nil))
27
	} else {
28
		logger = slog.New(slog.NewTextHandler(os.Stderr, nil))
29
	}
30
31
	return Server{
32
		&server{
33
			name:    "clerk",
34
			version: version,
35
36
			openDocs: make(map[uri.URI]docState),
37
38
			config:  DefaultConfig,
39
			linter:  linter.NewLinter(linter.Rules),
40
			loader:  journal.NewLoader(),
41
			printer: printer.DefaultConfig,
42
43
			log: logger,
44
		},
45
	}
46
}
47
48
func openLogFile() (*os.File, error) {
49
	dir, err := xdg.StateDir()
50
	if err != nil {
51
		return nil, err
52
	}
53
	dir = filepath.Join(dir, "clerk")
54
	if err := os.MkdirAll(dir, 0o700); err != nil {
55
		return nil, err
56
	}
57
	return os.OpenFile(filepath.Join(dir, "lsp.log"), os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0o644)
58
}
59
60
func (s *Server) Run(ctx context.Context, stdin io.ReadCloser, stdout io.WriteCloser) error {
61
	stream := jsonrpc2.NewStream(readWriterCloser{
62
		Reader: stdin,
63
		Writer: stdout,
64
		Closer: stdin,
65
	})
66
67
	_, conn, client := protocol.NewServer(ctx, s.server, stream)
68
	defer conn.Close()
69
70
	s.server.client = client
71
72
	<-conn.Done()
73
	return conn.Err()
74
}
75
76
type readWriterCloser struct {
77
	io.Reader
78
	io.Writer
79
	io.Closer
80
}