这是indexloc提供的服务,不要输入任何密码
Skip to content

Allow braces for padding #30

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jun 4, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 26 additions & 2 deletions oxifmt.typ
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@
// -- parsing state --
let current-fmt-span = none
let current-fmt-name = none
// if we're at {abc:|, i.e. right after a colon in {}
let last-was-fmt-colon = false
// if the last character was an unescaped {
let last-was-lbracket = false
// if the last character was an unescaped }
Expand Down Expand Up @@ -116,6 +118,7 @@
// -- parse loop --
let last-i = none
let i = 0
let code-i = 0
for character in codepoints {
if character == "{" {
// double l-bracket = escape
Expand All @@ -138,11 +141,19 @@
// indicate we just started a span
// in case it is escaped right afterwards
last-was-lbracket = true
} else if last-was-fmt-colon and codepoints.len() > code-i + 1 and codepoints.at(code-i + 1) in ("<", "^", ">") {
// don't error on mid-span { if this { might be used for padding
// 'escape' it right away
// e.g. {a:{<5} => formats "bc" as "{{{bc"
current-fmt-name += character
last-was-lbracket = false
} else {
// if in the middle of a larger span ({ ... { <-):
// error
excessive-lbracket()
}

last-was-fmt-colon = false
} else if character == "}" {
last-was-lbracket = false
if current-fmt-span == none {
Expand All @@ -154,11 +165,18 @@
// in case this is an escaped }
last-was-rbracket = true
}
} else if last-was-fmt-colon and codepoints.len() > code-i + 1 and codepoints.at(code-i + 1) in ("<", "^", ">") {
// don't close span with } if this } might be used for padding
// e.g. {a:}<5} => formats "bc" as "}}}bc"
current-fmt-name += character
last-was-rbracket = false
} else {
// { ... } <--- ok, close the previous span
// Do this eagerly, escaping } inside { ... } is invalid
(result, current-fmt-span, current-fmt-name) = write-format-span(i, result, current-fmt-span, current-fmt-name)
}

last-was-fmt-colon = false
} else {
if last-was-rbracket {
if current-fmt-span == none {
Expand All @@ -169,22 +187,28 @@
panic("String formatter error: internal error: invalid right bracket state")
}
}
// {abc <--- add character to the format name
if current-fmt-name != none {

if current-fmt-name == none {
last-was-fmt-colon = false
} else {
// {abc <--- add character to the format name
current-fmt-name += character
last-was-fmt-colon = character == ":"
}
last-was-lbracket = false
last-was-rbracket = false
}

last-i = i
i += character.len() // index must be in bytes, and a UTF-8 codepoint can have more than one byte
code-i += 1
}
// { ...
if current-fmt-span != none {
if last-was-rbracket {
// ... } <--- ok, close span
(result, current-fmt-span, current-fmt-name) = write-format-span(last-i, result, current-fmt-span, current-fmt-name)
last-was-fmt-colon = false
} else {
// {abcd| <--- string ended with unclosed span
missing-rbracket()
Expand Down
11 changes: 11 additions & 0 deletions tests/strfmt-tests.typ
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,17 @@
assert.eq(strfmt("{{{}}}", 1), "{1}")
assert.eq(strfmt("{{"), "{")
assert.eq(strfmt("}}"), "}")

// Issue #28: pad with {} inside :
assert.eq(strfmt("{:}>4}", "a"), "}}}a")
assert.eq(strfmt("{:}^4}", "a"), "}}a}}")
assert.eq(strfmt("{:}<4}", "a"), "a}}}")
assert.eq(strfmt("{:{>4}", "a"), "{{{a")
assert.eq(strfmt("{:{^4}", "a"), "{{a{{")
assert.eq(strfmt("{:{<4}", "a"), "a{{{")
assert.eq(strfmt("{:{^}", "a"), "a")
assert.eq(strfmt("{:}^}", "a"), "a")
assert.eq(strfmt("{:}}}", "a"), "a}")
}
// DOC TESTS
#{
Expand Down