Skip to content

Commit

Permalink
Merge pull request #120 from Kolaru/line_break
Browse files Browse the repository at this point in the history
Support for line break
  • Loading branch information
Kolaru authored Apr 22, 2024
2 parents 6d9f276 + ba8e043 commit a392f27
Show file tree
Hide file tree
Showing 7 changed files with 54 additions and 25 deletions.
6 changes: 5 additions & 1 deletion reference/references.jl
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ inputs["integrals"] = [
L"\int \int \int"
]

input["linebreaks"] = [
L"we clearly see $x = 22$\\and $y > x^2$"
]

inputs["punctuation"] = [
L"x!",
L"23.17",
Expand Down Expand Up @@ -115,7 +119,7 @@ function single_figure(exprs)
failures = Dict()
for (i, expr) in enumerate(exprs)
try
fig[i, 1] = Label(fig, expr)
Label(fig[i, 1], expr)
catch e
failures[expr] = e
end
Expand Down
1 change: 1 addition & 0 deletions src/MathTeXEngine.jl
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import FreeTypeAbstraction:
height_insensitive_boundingbox, leftinkbound, rightinkbound,
topinkbound, bottominkbound

export TeXToken, tokenize
export TeXExpr, texparse, TeXParseError, manual_texexpr
export TeXElement, TeXChar, VLine, HLine, generate_tex_elements
export texfont
Expand Down
37 changes: 16 additions & 21 deletions src/engine/layout.jl
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,7 @@ function tex_layout(expr, state)
if char == ' ' && state.tex_mode == :inline_math
return Space(0.0)
end
texchar = TeXChar(char, state, head)
return texchar
return TeXChar(char, state, head)
elseif head == :combining_accent
accent, core = tex_layout.(args, state)

Expand Down Expand Up @@ -134,8 +133,8 @@ function tex_layout(expr, state)
name = args[1]
elements = TeXChar.(collect(name), state, Ref(:function))
return horizontal_layout(elements)
elseif head == :group || head == :expr || head == :inline_math
mode = head == :inline_math ? :inline_math : state.tex_mode
elseif head in (:group, :inline_math, :line)
mode = (head == :inline_math) ? :inline_math : state.tex_mode
elements = tex_layout.(args, change_mode(state, mode))
if isempty(elements)
return Space(0.0)
Expand All @@ -160,6 +159,17 @@ function tex_layout(expr, state)
],
[1, shrink, shrink]
)
elseif head == :lines
length(args) == 1 && return tex_layout(only(args), state)
lineheight = 1.3
lines = tex_layout.(args, state)
points = map(enumerate(lines)) do (k, line)
x = -inkwidth(line) / 2
y = (1 - k)*lineheight
return Point2f(x, y)
end

return Group(lines, points)
elseif head == :overline
content = tex_layout(args[1], state)

Expand Down Expand Up @@ -248,7 +258,7 @@ function tex_layout(expr, state)
@error "Error while layouting expr"
end

@error "Unsupported head $(head) in expr:\n$expr"
throw(ArgumentError("Unsupported head :$(head) in TeXExpr\n$expr"))
end

tex_layout(::Nothing, state) = Space(0)
Expand Down Expand Up @@ -310,19 +320,4 @@ function generate_tex_elements(str, font_family=FontFamily())
expr = texparse(str)
layout = tex_layout(expr, font_family)
return unravel(layout)
end

#=
# Still hacky as hell
function generate_tex_elements(str::LaTeXString, font_family=FontFamily())
parts = String.(split(str, raw"$"))
groups = Vector{TeXElement}(undef, length(parts))
texts = parts[1:2:end]
maths = parts[2:2:end]
groups[1:2:end] = layout_text.(texts, Ref(font_family))
groups[2:2:end] = tex_layout.(texparse.(maths), Ref(font_family))
return unravel(horizontal_layout(groups))
end
=#
end
4 changes: 4 additions & 0 deletions src/engine/layout_context.jl
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ function add_font_modifier(state::LayoutState, modifier)
end

function get_font(state::LayoutState, char_type)
if state.tex_mode == :text
char_type = :text
end

font_family = state.font_family
font_id = font_family.font_mapping[char_type]

Expand Down
22 changes: 20 additions & 2 deletions src/parser/parser.jl
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,10 @@ arguments.
Setting `showdebug` to `true` show a very verbose break down of the parsing.
"""
function texparse(tex ; root = TeXExpr(:expr), showdebug = false)
function texparse(tex ; root = TeXExpr(:lines), showdebug = false)
stack = Stack{Any}()
push!(stack, root)
push!(stack, TeXExpr(:line))

for (pos, len, token) in tokenize(TeXToken, tex)
if showdebug
Expand All @@ -128,6 +129,13 @@ function texparse(tex ; root = TeXExpr(:expr), showdebug = false)
else
push!(stack, TeXExpr(:inline_math))
end
elseif token == newline
if length(stack) > 2
throw(TeXParseError("unexpected new line", stack, length(tex), tex))
end

push_down!(stack)
push!(stack, TeXExpr(:line))
elseif token == lcurly
push!(stack, TeXExpr(:group))
elseif token == rcurly
Expand Down Expand Up @@ -188,8 +196,18 @@ function texparse(tex ; root = TeXExpr(:expr), showdebug = false)
end
end

if head(first(stack)) == :line
push_down!(stack)
end

if length(stack) > 1
throw(TeXParseError("unexpected end of input", stack, length(tex), tex))
end
return only(stack)

lines = only(stack)
if length(lines.args) == 1
return only(lines.args)
else
return lines
end
end
1 change: 1 addition & 0 deletions src/parser/tokenizer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ tex_tokens = [
:command => re"\\[a-zA-Z]+" | re"\\.",
:right => re"\\right.",
:left => re"\\left.",
:newline => (re"\\" * re"\\") | re"\\n",
:dollar => re"$"
]

Expand Down
8 changes: 7 additions & 1 deletion test/parser.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
function test_parse(input, args... ; broken=false)
arg = (:expr, args...)
arg = (:line, args...)
if broken
@test_broken texparse(input) == manual_texexpr(arg)
else
Expand Down Expand Up @@ -114,6 +114,12 @@ end
)
end

@testset "Linebreak" begin
expr = texparse(L"$A$\\$B$\\$C$")
@test expr.head == :lines
@test length(expr.args) == 3
end

@testset "LaTeXString input" begin
@test texparse(raw"$\gamma$") == texparse(L"\gamma")
end
Expand Down

4 comments on commit a392f27

@Kolaru
Copy link
Owner Author

@Kolaru Kolaru commented on a392f27 Apr 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/105380

Tip: Release Notes

Did you know you can add release notes too? Just add markdown formatted text underneath the comment after the text
"Release notes:" and it will be added to the registry PR, and if TagBot is installed it will also be added to the
release that TagBot creates. i.e.

@JuliaRegistrator register

Release notes:

## Breaking changes

- blah

To add them here just re-invoke and the PR will be updated.

Tagging

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.6.0 -m "<description of version>" a392f2728ac9afbe5a968c2c5d64040b6efae239
git push origin v0.6.0

@Kolaru
Copy link
Owner Author

@Kolaru Kolaru commented on a392f27 Apr 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator register

Release notes:

  • New parser.
  • Support for line break.
  • Multiple small fixes.

Breaking changes

  • The head of the expression returned by texparse is no longer :expr. It is either :lines if there are multiple lines, or :line if there is a single one.

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request updated: JuliaRegistries/General/105380

Tagging

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.6.0 -m "<description of version>" a392f2728ac9afbe5a968c2c5d64040b6efae239
git push origin v0.6.0

Please sign in to comment.