all repos

clerk @ 0ff087c

missing tooling for ledger/hledger
3 files changed, 81 insertions(+), 30 deletions(-)
lsp: completion ranks declared names and demotes typed text
Author: Oleksandr Smirnov olexsmir@gmail.com
Committed at: 2026-09-10 13:33:34 +0300
Authored at: 2026-09-09 14:23:14 +0300
Change ID: xknxsyqrrlnvzywnpkvkmlqyxlktwlwv
Parent: e12aa47
M internal/lsp/testdata/completion-contexts.txtar
···
        143
        143
           expenses:food

      
        144
        144
           expenses:taxi

      
        145
        145
         23:20 commodity "$"

      
        146
        
        -  $

      
        147
        146
         24:19 commodity ""

      
        
        147
        +  USD

      
        148
        148
           $

      
        149
        
        -  USD

      
        150
        149
         25:20 commodity "U"

      
        151
        150
           USD

      
        152
        151
         26:21 none ""

      ···
        160
        159
           acme

      
        161
        160
           x

      
        162
        161
         31:31 tag-value "ac"

      
        163
        
        -  ac

      
        164
        162
           acme

      
        165
        163
         32:20 tag-value "ac"

      
        166
        
        -  ac

      
        167
        164
           acme

      
        168
        165
         33:21 tag-value "https://exa"

      
        169
        166
           https://example

      ···
        284
        281
         110:12 date "2024-01-15"

      
        285
        282
           2024-01-15

      
        286
        283
         111:13 commodity ""

      
        287
        
        -  $

      
        288
        284
           USD

      
        
        285
        +  $

      
        289
        286
         112:14 commodity "U"

      
        290
        287
           USD

      
        291
        288
         113:24 commodity "U"

      
        292
        289
           USD

      
        293
        290
         116:22 commodity ""

      
        294
        
        -  $

      
        295
        291
           USD

      
        
        292
        +  $

      
        296
        293
         117:21 none ""

      
        297
        294
         118:18 none ""

      
        298
        295
         119:22 commodity ""

      
        299
        
        -  $

      
        300
        296
           USD

      
        
        297
        +  $

      
        301
        298
         120:23 commodity "€"

      
M internal/lsp/testdata/completion-journal.txtar
···
        9
        9
           assets:cash

      
        10
        10
         

      
        11
        11
         account assets:cash

      
        
        12
        +account assets:bank

      
        
        13
        +

      
        
        14
        +2024-01-15

      
        
        15
        +  assets:b  $10

      
        
        16
        +  assets:cash

      
        
        17
        +

      
        
        18
        +2024-01-15

      
        
        19
        +  assets:b  $10

      
        
        20
        +  assets:cash

      
        
        21
        +

      
        
        22
        +2024-01-15

      
        
        23
        +  assets:b  $10

      
        
        24
        +  assets:cash

      
        
        25
        +

      
        
        26
        +2024-01-15

      
        
        27
        +  assets:bank  $10

      
        
        28
        +  assets:cash

      
        
        29
        +

      
        
        30
        +2024-01-16

      
        
        31
        +  assets:b^ank  $10

      
        
        32
        +  assets:cash

      
        
        33
        +

      
        
        34
        +2024-01-15

      
        
        35
        +  liabilities:l  $10

      
        
        36
        +  assets:cash

      
        
        37
        +

      
        
        38
        +2024-01-15

      
        
        39
        +  liabilities:l  $10

      
        
        40
        +  assets:cash

      
        
        41
        +

      
        
        42
        +2024-01-15

      
        
        43
        +  liabilities:l  $10

      
        
        44
        +  assets:cash

      
        
        45
        +

      
        
        46
        +2024-01-15

      
        
        47
        +  liabilities:loan  $10

      
        
        48
        +  assets:cash

      
        
        49
        +

      
        
        50
        +2024-01-16

      
        
        51
        +  liabilities:l^oan  $10

      
        
        52
        +  assets:cash

      
        12
        53
         

      
        13
        54
         commodity USD

      
        14
        55
         

      ···
        66
        107
         tag 客^户

      
        67
        108
         

      
        68
        109
         -- expect --

      
        69
        
        -19:10 tag-value "a"

      
        
        110
        +29:10 account "assets:b"

      
        
        111
        +  assets:bank

      
        
        112
        +49:15 account "liabilities:l"

      
        
        113
        +  liabilities:loan

      
        
        114
        +60:10 tag-value "a"

      
        70
        115
           acme

      
        71
        
        -20:10 tag-value ""

      
        
        116
        +61:10 tag-value ""

      
        72
        117
           alpha

      
        73
        
        -22:11 payee ""

      
        
        118
        +63:11 payee ""

      
        74
        119
           Grocery

      
        75
        120
           Продукти

      
        76
        121
           Супермаркет

      
        77
        122
           Store

      
        78
        123
           sup

      
        79
        
        -23:12 account "expenses:f"

      
        
        124
        +64:12 account "expenses:f"

      
        80
        125
           expenses:food

      
        81
        
        -28:16 account "assets:c"

      
        
        126
        +69:16 account "assets:c"

      
        82
        127
           assets:cash

      
        83
        
        -30:11 commodity "U"

      
        
        128
        +71:11 commodity "U"

      
        84
        129
           USD

      
        85
        
        -32:8 payee "Gr"

      
        
        130
        +73:8 payee "Gr"

      
        86
        131
           Grocery

      
        87
        
        -34:7 tag "cli"

      
        
        132
        +75:7 tag "cli"

      
        88
        133
           client

      
        89
        
        -36:5 tag "cli"

      
        
        134
        +77:5 tag "cli"

      
        90
        135
           client

      
        91
        
        -37:6 tag "proj"

      
        
        136
        +78:6 tag "proj"

      
        92
        137
           project

      
        93
        
        -39:3 directive "acc"

      
        
        138
        +80:3 directive "acc"

      
        94
        139
           account

      
        95
        
        -51:16 payee "Супер"

      
        
        140
        +92:16 payee "Супер"

      
        96
        141
           Супермаркет

      
        97
        
        -52:13 account "Витрати:Про"

      
        
        142
        +93:13 account "Витрати:Про"

      
        98
        143
           Витрати:Продукти

      
        99
        
        -55:14 payee "sup"

      
        
        144
        +96:14 payee "sup"

      
        100
        145
           Супермаркет

      
        101
        
        -  sup

      
        102
        
        -57:15 payee "Прод"

      
        
        146
        +98:15 payee "Прод"

      
        103
        147
           Продукти

      
        104
        
        -58:12 account "Витрати:Тр"

      
        
        148
        +99:12 account "Витрати:Тр"

      
        105
        149
           Витрати:Транспорт

      
        106
        
        -62:11 commodity "¥"

      
        
        150
        +103:11 commodity "¥"

      
        107
        151
           ¥

      
        108
        
        -64:5 tag "客"

      
        
        152
        +105:5 tag "客"

      
        109
        153
           客户

      
M internal/lsp/textdocument_completion.go
···
        369
        369
         	label        string

      
        370
        370
         	score        float64

      
        371
        371
         	count        int

      
        
        372
        +	declared     bool  // has a declaration directive (account/payee/commodity/tag); sorts before usage-only names

      
        
        373
        +	exact        bool  // label equals the typed pattern; phantom exact names are dropped entirely

      
        372
        374
         	lastUsedDays int64 // days since 1970-01-01; 0 when unset

      
        373
        375
         	rank         int   // lower sorts first among equal scores; 0 except for date completions

      
        374
        376
         }

      ···
        392
        394
         		kind = protocol.CompletionItemKindClass

      
        393
        395
         		cands = make([]cmplCand, 0, len(a.Accounts))

      
        394
        396
         		for name, info := range a.Accounts {

      
        395
        
        -			cands = append(cands, cmplCand{label: name, count: info.UsedCount, lastUsedDays: dateToDays(info.LastUsed)})

      
        
        397
        +			cands = append(cands, cmplCand{label: name, count: info.UsedCount, lastUsedDays: dateToDays(info.LastUsed), declared: len(info.Directives) > 0})

      
        396
        398
         		}

      
        397
        399
         	case cmplPayee:

      
        398
        400
         		kind = protocol.CompletionItemKindVariable

      
        399
        401
         		cands = make([]cmplCand, 0, len(a.Payees))

      
        400
        402
         		for name, info := range a.Payees {

      
        401
        
        -			cands = append(cands, cmplCand{label: name, count: info.UsedCount, lastUsedDays: dateToDays(info.LastUsed)})

      
        
        403
        +			cands = append(cands, cmplCand{label: name, count: info.UsedCount, lastUsedDays: dateToDays(info.LastUsed), declared: len(info.Directives) > 0})

      
        402
        404
         		}

      
        403
        405
         	case cmplCommodity:

      
        404
        406
         		kind = protocol.CompletionItemKindValue

      
        405
        407
         		cands = make([]cmplCand, 0, len(a.Commodities))

      
        406
        408
         		for name, info := range a.Commodities {

      
        407
        
        -			cands = append(cands, cmplCand{label: name, count: info.UsedCount, lastUsedDays: dateToDays(info.LastUsed)})

      
        
        409
        +			cands = append(cands, cmplCand{label: name, count: info.UsedCount, lastUsedDays: dateToDays(info.LastUsed), declared: len(info.Directives) > 0})

      
        408
        410
         		}

      
        409
        411
         	case cmplTagName:

      
        410
        412
         		kind = protocol.CompletionItemKindProperty

      
        411
        413
         		cands = make([]cmplCand, 0, len(a.Tags))

      
        412
        414
         		for name, info := range a.Tags {

      
        413
        
        -			cands = append(cands, cmplCand{label: name, count: info.UsedCount, lastUsedDays: dateToDays(info.LastUsed)})

      
        
        415
        +			cands = append(cands, cmplCand{label: name, count: info.UsedCount, lastUsedDays: dateToDays(info.LastUsed), declared: len(info.Directives) > 0})

      
        414
        416
         		}

      
        415
        417
         	case cmplTagValue:

      
        416
        418
         		kind = protocol.CompletionItemKindProperty

      ···
        467
        469
         		}

      
        468
        470
         	}

      
        469
        471
         	ranked := cands[:0]

      
        
        472
        +	dropExact := ctx == cmplAccount || ctx == cmplPayee || ctx == cmplCommodity || ctx == cmplTagName || ctx == cmplTagValue

      
        470
        473
         	for i := range cands {

      
        
        474
        +		cands[i].exact = pattern != "" && strings.EqualFold(cands[i].label, pattern)

      
        
        475
        +		if dropExact && cands[i].exact && !cands[i].declared {

      
        
        476
        +			continue // the typed name is not declared; re-offering it is noise

      
        
        477
        +		}

      
        471
        478
         		sc := matcher.Score(cands[i].label)

      
        472
        479
         		if hasTransl {

      
        473
        480
         			sc = max(sc, translMatcher.Score(cands[i].label))

      ···
        485
        492
         		}

      
        486
        493
         	}

      
        487
        494
         	sort.Slice(ranked, func(i, j int) bool {

      
        
        495
        +		if ranked[i].declared != ranked[j].declared {

      
        
        496
        +			return ranked[i].declared

      
        
        497
        +		}

      
        488
        498
         		if ranked[i].score != ranked[j].score {

      
        489
        499
         			return ranked[i].score > ranked[j].score

      
        490
        500
         		}