turbo-editors/turbo-corepublic Fork 0
v1.0.0
Commits
Clone
git clone https://git.rickub.com/turbo-editors/turbo-core.git
git clone ssh://git@rickub.com/turbo-editors/turbo-core.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

🛟 Updated. 28d5985 · on v1.0.0 · k33g · 17h ago
yaml_block.go · 84 lines · 2.7 KBGo Blame HistoryRaw
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
package syntax

// Block scalars: the one construct in YAML whose extent is decided by
// indentation rather than by a delimiter, and the one every CI file uses.

// yamlCarry is what a line leaves open for the next.
//
// Only a block scalar does. It is the one construct in YAML whose extent is
// decided by *indentation* rather than by a delimiter: everything indented
// further than the key that opened it belongs to it, and the first line that is
// not ends it. So the carry holds that key's indentation, and whether one is
// open at all — a depth of zero is a real indentation, not an absence.
type yamlCarry struct {
	inBlock bool
	// keyIndent is the column the key that opened the block starts at. A line
	// indented further is inside the block.
	keyIndent int
	// seenBody is false until the block's first content line, whose indentation
	// is not yet known. YAML lets a block be written at any deeper indent, so
	// the first line establishes it rather than a fixed offset doing so.
	seenBody bool
}

// continueBlockScalar colours a line belonging to an open block scalar, and
// reports whether the block swallowed it.
//
// A blank line inside a block belongs to the block whatever its indentation:
// YAML keeps empty lines in a literal scalar, and treating one as the end would
// cut a shell script in a CI file in half at its first paragraph break.
func continueBlockScalar(s *LineScanner, carry yamlCarry) (bool, yamlCarry) {
	if s.Len() == 0 {
		return true, carry
	}

	indent := leadingSpaces(s.line)
	if indent == s.Len() { // a line of nothing but spaces
		return true, carry
	}

	if !carry.seenBody {
		// The first content line fixes the block's own indentation. It only
		// counts as the body if it is indented past the key.
		if indent <= carry.keyIndent {
			return false, yamlCarry{}
		}
		carry.seenBody = true
		carry.keyIndent = indent - 1 // anything at or past `indent` is inside
	}
	if indent <= carry.keyIndent {
		return false, yamlCarry{}
	}

	s.TakeRest(ClassString)
	return true, carry
}

// opensBlockScalar reports whether what is left of the line is a `|` or `>`
// header, with its optional chomping and indentation indicators.
func opensBlockScalar(s *LineScanner) bool {
	if r := s.Peek(0); r != '|' && r != '>' {
		return false
	}
	for at := 1; s.Pos()+at < s.Len(); at++ {
		switch s.Peek(at) {
		case '-', '+', '1', '2', '3', '4', '5', '6', '7', '8', '9', ' ':
			continue
		case '#':
			return true // a trailing comment still leaves the block open
		default:
			return false
		}
	}
	return true
}

// leadingSpaces returns how many spaces a line starts with.
func leadingSpaces(line []rune) int {
	for at, r := range line {
		if r != ' ' {
			return at
		}
	}
	return len(line)
}