Skip to content

Commit

Permalink
Display duplicated spaces when word wrapping is :normal
Browse files Browse the repository at this point in the history
  • Loading branch information
fuelen committed Aug 3, 2024
1 parent f5a1175 commit bbfb8e1
Show file tree
Hide file tree
Showing 2 changed files with 140 additions and 57 deletions.
119 changes: 71 additions & 48 deletions lib/owl/lines.ex
Original file line number Diff line number Diff line change
Expand Up @@ -23,57 +23,80 @@ defmodule Owl.Lines do
defp wrap_words(line, :normal, max_width) do
line
|> Owl.Data.split(" ")
|> Enum.flat_map_reduce(0, fn word, line_length ->
word_length = Owl.Data.length(word)
break_word? = word_length > max_width
|> Enum.intersperse(" ")
|> Enum.flat_map_reduce({0, false}, fn
%Owl.Tag{data: []}, acc ->
{[], acc}

cond do
break_word? ->
{line_length, pre} =
cond do
line_length == 0 -> {0, nil}
line_length == max_width -> {0, :break}
line_length + 1 == max_width -> {0, :break}
true -> {line_length, {:data, " "}}
[], acc ->
{[], acc}

word, {line_length, after_space?} ->
word_length = Owl.Data.length(word)
break_word? = word_length > max_width

cond do
break_word? ->
{line_length, pre} =
cond do
line_length == 0 -> {0, nil}
line_length == max_width -> {0, :break}
true -> {line_length, nil}
end

first_part_length = max_width - line_length
first_part = Owl.Data.slice(word, 0, first_part_length)

rest_parts =
Owl.Data.chunk_every(
Owl.Data.slice(word, first_part_length, word_length - first_part_length),
max_width
)

items =
Enum.map_intersperse([first_part | rest_parts], :break, fn data -> {:data, data} end)

line_length = List.last(rest_parts) |> Owl.Data.length()

if pre do
{[pre | items], {line_length, false}}
else
{items, {line_length, false}}
end

word_length == max_width ->
if line_length == 0 do
{[{:data, word}, :break], {0, false}}
else
{[:break, {:data, word}, :break], {0, false}}
end

first_part_length = max_width - if line_length == 0, do: 0, else: line_length + 1
first_part = Owl.Data.slice(word, 0, first_part_length)

rest_parts =
Owl.Data.chunk_every(
Owl.Data.slice(word, first_part_length, word_length - first_part_length),
max_width
)

items =
Enum.map_intersperse([first_part | rest_parts], :break, fn data -> {:data, data} end)

line_length = List.last(rest_parts) |> Owl.Data.length()

if pre do
{[pre | items], line_length}
else
{items, line_length}
end

word_length + 1 == max_width or word_length == max_width ->
if line_length == 0 do
{[{:data, word}, :break], 0}
else
{[:break, {:data, word}, :break], 0}
end

word_length + line_length + 1 > max_width ->
{[:break, {:data, word}], word_length}

true ->
if line_length == 0 do
{[{:data, word}], word_length}
else
{[{:data, " "}, {:data, word}], word_length + line_length + 1}
end
end
word_length + line_length > max_width ->
space? = word == " "

if space? do
{[:break], {0, true}}
else
{[:break, {:data, word}], {word_length, false}}
end

true ->
space? = word == " "

cond do
space? and line_length == 0 and not after_space? ->
{[], {0, true}}

space? and after_space? ->
{[data: " "], {line_length + 2, false}}

space? and word_length + line_length == max_width ->
{[:break], {0, false}}

true ->
{[{:data, word}], {word_length + line_length, false}}
end
end
end)
|> elem(0)
|> Enum.chunk_by(fn item -> item == :break end)
Expand Down
78 changes: 69 additions & 9 deletions test/owl/box_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,32 @@ defmodule Owl.BoxTest do
|> Owl.Data.lines()
end

assert get_wrapped_lines.("Hello! My name is Artur.", 2) == [
"He",
"ll",
"o!",
" ",
"My",
"na",
"me",
"is",
"Ar",
"tu",
"r."
]

assert get_wrapped_lines.("Hello! My name is Artur.", 3) == [
"Hel",
"lo!",
" ",
"My ",
"nam",
"e ",
"is ",
"Art",
"ur."
]

assert get_wrapped_lines.("Hello! My name is Artur.", 2) == [
"He",
"ll",
Expand Down Expand Up @@ -280,21 +306,21 @@ defmodule Owl.BoxTest do
]

assert get_wrapped_lines.("Hello! My name is Artur.", 11) == [
"Hello! My",
"name is ",
"Artur. "
"Hello! My ",
"name is ",
"Artur. "
]

assert get_wrapped_lines.("Hello! My name is Artur.", 12) == [
"Hello! My",
"name is ",
"Artur. "
"Hello! My ",
"name is ",
"Artur. "
]

assert get_wrapped_lines.("Hello! My name is Artur.", 13) == [
"Hello! My",
"name is ",
"Artur. "
"Hello! My ",
"name is ",
"Artur. "
]

assert get_wrapped_lines.("Hello! My name is Artur.", 14) == [
Expand Down Expand Up @@ -329,6 +355,40 @@ defmodule Owl.BoxTest do
" ",
Owl.Data.tag("C", [:green_background, :red])
]

assert [
"qwertyuiopasdfghjklzxcvbnm\n",
Owl.Data.tag("```", Owl.TrueColor.color(255, 255, 255)),
"\n",
Owl.Data.tag(" ,_,", Owl.TrueColor.color(255, 255, 255)),
"\n",
Owl.Data.tag(" {o,o}", Owl.TrueColor.color(255, 255, 255)),
"\n",
Owl.Data.tag(" /) )", Owl.TrueColor.color(255, 255, 255)),
"\n",
Owl.Data.tag("---\"-\"--", Owl.TrueColor.color(255, 255, 255)),
"\n",
Owl.Data.tag("```", Owl.TrueColor.color(255, 255, 255))
]
|> Owl.Box.new(word_wrap: :normal, max_width: 11)
|> Owl.Data.to_chardata()
|> Owl.Data.from_chardata() == [
"┌─────────┐\n│qwertyuio│\n│pasdfghjk│\n│lzxcvbnm │\n│",
Owl.Data.tag("```", Owl.TrueColor.color(255, 255, 255)),
" │\n│ ",
Owl.Data.tag(",_,", Owl.TrueColor.color(255, 255, 255)),
" │\n│ ",
Owl.Data.tag("{o,o}", Owl.TrueColor.color(255, 255, 255)),
" │\n│ ",
Owl.Data.tag("/)", Owl.TrueColor.color(255, 255, 255)),
" ",
Owl.Data.tag(")", Owl.TrueColor.color(255, 255, 255)),
" │\n│",
Owl.Data.tag("---\"-\"--", Owl.TrueColor.color(255, 255, 255)),
" │\n│",
Owl.Data.tag("```", Owl.TrueColor.color(255, 255, 255)),
" │\n└─────────┘"
]
end
end
end

0 comments on commit bbfb8e1

Please sign in to comment.