all repos

clerk @ 8e87a98

missing tooling for ledger/hledger
1 files changed, 74 insertions(+), 0 deletions(-)
lsp: format
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
        +}