Skip to content

Instantly share code, notes, and snippets.

@kipcole9
Created December 27, 2022 21:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kipcole9/c3636d29d2b8df90caa6a7c9818275fe to your computer and use it in GitHub Desktop.
Save kipcole9/c3636d29d2b8df90caa6a7c9818275fe to your computer and use it in GitHub Desktop.
Split text at a separators using NimbleParsec
defmodule NimbleSplit do
@moduledoc """
Split text at a separator using [nimble_parsec](https://hex.pm/packages/nimble_parsec)
"""
import NimbleParsec
def test_string do
"""
some text, may also contain character "=", which is part of the separator
can be any number of lines long until the first separator line
==========
next block of text
==========
and another one
"""
end
# A separator line. Note inclusion of the
# surrounding newlines
separator =
string("\n==========\n")
# A line is just a series of characters up to
# but not including a newline
line =
repeat(utf8_char([{:not, ?\n}]))
# A block is a series of lines, stopping when the
# next line is a separator
block =
line
|> repeat(lookahead_not(separator) |> ascii_char([?\n]) |> concat(line))
|> reduce({List, :to_string, []})
# The last block might not be terminated by
# a separator
last_block =
line
|> repeat(ascii_char([?\n]) |> concat(line))
|> reduce({List, :to_string, []})
# Zero or more blocks separated by the separator
# with maybe a final block
defparsec(:parse, repeat(block |> ignore(separator)) |> concat(last_block))
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment