all repos

clerk @ 9369172

missing tooling for ledger/hledger

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

Oleksandr Smirnov Oleksandr Smirnov
olexsmir@gmail.com
lsp: diagnostics, 20 days ago
1
package lsp
2
3
import (
4
	"context"
5
	"fmt"
6
	"strings"
7
8
	"go.lsp.dev/protocol"
9
10
	"olexsmir.xyz/clerk/journal/lexer"
11
	"olexsmir.xyz/clerk/journal/parser"
12
)
13
14
func (s *server) Formatting(ctx context.Context, params *protocol.DocumentFormattingParams) ([]protocol.TextEdit, error) {
15
	text, ok := s.getDocText(params.TextDocument.URI)
16
	if !ok {
17
		return nil, nil
18
	}
19
20
	lex := lexer.New(params.TextDocument.URI.Path(), []byte(text))
21
	jnrl := parser.New(lex).ParseJournal()
22
	if len(jnrl.Errors) > 0 {
23
		return nil, fmt.Errorf("can't format file with errors: %v", jnrl.Errors[0].Message)
24
	}
25
26
	var buf strings.Builder
27
	if err := s.printerCfg.Fprint(&buf, jnrl); err != nil {
28
		return nil, fmt.Errorf("format: %w", err)
29
	}
30
	newText := buf.String()
31
32
	if newText == text {
33
		return nil, nil
34
	}
35
36
	endLine, endChar := getEndLineAndChar(text)
37
	return []protocol.TextEdit{{
38
		NewText: newText,
39
		Range: protocol.Range{
40
			Start: protocol.Position{
41
				Line:      0,
42
				Character: 0,
43
			},
44
			End: protocol.Position{
45
				Line:      uint32(endLine),
46
				Character: uint32(endChar),
47
			},
48
		},
49
	}}, nil
50
}
51
52
func getEndLineAndChar(txt string) (int, int) {
53
	endLine := 0
54
	lastNewline := -1
55
	for i, ch := range txt {
56
		if ch == '\n' {
57
			endLine++
58
			lastNewline = i
59
		}
60
	}
61
	endChar := 0
62
	if lastNewline >= 0 {
63
		if lastNewline == len(txt)-1 {
64
			endLine++
65
			endChar = 0
66
		} else {
67
			endChar = len(txt) - lastNewline - 1
68
		}
69
	} else {
70
		endChar = len(txt)
71
	}
72
	return endLine, endChar
73
}