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