all repos

clerk @ 9ee2ed8e103448aec230ea1a1aa25e311d36c83e

missing tooling for ledger/hledger
3 files changed, 48 insertions(+), 25 deletions(-)
lexer: fix include path lexer

- before `include 2026.journal` used to omit INCLUDE NUMBER TEXT
  now it omits INCLUDE TEXT
Author: Oleksandr Smirnov olexsmir@gmail.com
Committed at: 2026-08-04 14:36:36 +0300
Authored at: 2026-08-04 12:44:41 +0300
Change ID: vopnrmyqtxlssqpyzlskpuyxznmwzuqm
Parent: bf2effd
M journal/lexer/lexer.go
···
        55
        55
         	postingExpectAccount  bool

      
        56
        56
         	readingNoteAfterPipe  bool

      
        57
        57
         

      
        
        58
        +	includePath bool // true after [token.INCLUDE] is omitted

      
        
        59
        +

      
        58
        60
         	// subdirective is set when the current line is an account/commodity

      
        59
        61
         	// directive; the next indented line then lexes as directive content

      
        60
        62
         	subdirective bool

      ···
        95
        97
         }

      
        96
        98
         

      
        97
        99
         func (l *Lexer) lexDefault() token.Token {

      
        
        100
        +	if l.includePath {

      
        
        101
        +		l.includePath = false

      
        
        102
        +	}

      
        98
        103
         	if l.subdirective && l.ch != ' ' && l.ch != '\t' {

      
        99
        104
         		l.subdirective = false

      
        100
        105
         	}

      ···
        371
        376
         }

      
        372
        377
         

      
        373
        378
         func (l *Lexer) lexDirective() token.Token {

      
        374
        
        -	switch l.ch {

      
        375
        
        -	case '\n', 0:

      
        
        379
        +	switch {

      
        
        380
        +	case l.ch == '\n', l.ch == 0:

      
        376
        381
         		l.mode = ModeDefault

      
        377
        382
         		return l.lexNewline()

      
        378
        
        -	case '\r':

      
        
        383
        +	case l.ch == '\r':

      
        379
        384
         		l.mode = ModeDefault

      
        380
        385
         		l.col = 0

      
        381
        386
         		l.advance()

      
        382
        387
         		return l.lexNewline()

      
        383
        
        -	case ';':

      
        
        388
        +	case l.ch == ';':

      
        384
        389
         		l.mode = ModeComment

      
        385
        390
         		return l.lexSingle(token.SEMICOLON)

      
        386
        
        -	case ' ', '\t':

      
        
        391
        +	case l.ch == ' ', l.ch == '\t':

      
        387
        392
         		return l.lexWhitespace()

      
        388
        
        -	case '=':

      
        
        393
        +	case l.ch == '=':

      
        389
        394
         		return l.lexSingle(token.EQ)

      
        390
        
        -	case '+':

      
        
        395
        +	case l.ch == '+':

      
        391
        396
         		return l.lexSingle(token.PLUS)

      
        392
        
        -	case '-':

      
        
        397
        +	case l.ch == '-':

      
        393
        398
         		return l.lexSingle(token.MINUS)

      
        394
        
        -	case '"', '\'':

      
        
        399
        +	case l.ch == '"', l.ch == '\'':

      
        395
        400
         		return l.lexString()

      
        396
        
        -	case ':':

      
        
        401
        +	case l.ch == ':':

      
        397
        402
         		return l.lexSingle(token.COLON)

      
        398
        
        -	case ')':

      
        
        403
        +	case l.ch == ')':

      
        399
        404
         		return l.lexSingle(token.RPAREN)

      
        400
        
        -	case ']':

      
        
        405
        +	case l.ch == ']':

      
        401
        406
         		return l.lexSingle(token.RBRACKET)

      
        
        407
        +	case l.includePath:

      
        
        408
        +		return l.lexPath()

      
        
        409
        +	case l.isCommodityStart():

      
        
        410
        +		return l.lexCommodityMark()

      
        
        411
        +	case l.isTime():

      
        
        412
        +		return l.lexTime()

      
        
        413
        +	case l.isDate():

      
        
        414
        +		return l.lexDate()

      
        
        415
        +	case l.isDigit():

      
        
        416
        +		return l.lexNumber()

      
        402
        417
         	default:

      
        403
        
        -		if l.isCommodityStart() {

      
        404
        
        -			return l.lexCommodityMark()

      
        405
        
        -		}

      
        406
        
        -		if l.isTime() {

      
        407
        
        -			return l.lexTime()

      
        408
        
        -		}

      
        409
        
        -		if l.isDate() {

      
        410
        
        -			return l.lexDate()

      
        411
        
        -		}

      
        412
        
        -		if l.isDigit() {

      
        413
        
        -			return l.lexNumber()

      
        414
        
        -		}

      
        415
        418
         		return l.lexAccountNameDirective()

      
        
        419
        +	}

      
        
        420
        +}

      
        
        421
        +

      
        
        422
        +func (l *Lexer) lexPath() token.Token {

      
        
        423
        +	s := l.save()

      
        
        424
        +	for l.ch != '\n' && l.ch != '\r' && l.ch != ';' && l.ch != 0 && l.ch != ' ' && l.ch != '\t' {

      
        
        425
        +		l.advance()

      
        
        426
        +	}

      
        
        427
        +	return token.Token{

      
        
        428
        +		Type:    token.TEXT,

      
        
        429
        +		Literal: string(l.input[s.offset:l.pos]),

      
        
        430
        +		Span:    l.span(s),

      
        416
        431
         	}

      
        417
        432
         }

      
        418
        433
         

      ···
        587
        602
         		kind = token.TEXT

      
        588
        603
         	} else {

      
        589
        604
         		l.mode = ModeDirective

      
        590
        
        -		l.subdirective = lit == "account" || lit == "commodity"

      
        
        605
        +		l.subdirective = kind == token.ACCOUNT || kind == token.COMMODITY

      
        
        606
        +		l.includePath = kind == token.INCLUDE

      
        591
        607
         	}

      
        592
        608
         	return token.Token{Type: kind, Literal: lit, Span: l.span(s)}

      
        593
        609
         }

      
M journal/parser/parser_test.go
···
        26
        26
         		"N directive",

      
        27
        27
         		"inclue directive",

      
        28
        28
         		"inclue directive with comment",

      
        
        29
        +		"inclue directive digit path",

      
        29
        30
         		"apply tag directive",

      
        30
        31
         		"apply fixed directive",

      
        31
        32
         		"end apply directive",

      
A journal/parser/testdata/inclue_directive_digit_path.txtar
···
        
        1
        +-- input --

      
        
        2
        +include 2024.journal

      
        
        3
        +-- expect --

      
        
        4
        +Journal

      
        
        5
        +  IncludeDirective j:1:1-2:1

      
        
        6
        +    Path: "2024.journal"