[spec] comments on the proposed gemini spec revisions

Oliver Simmons oliversimmo at gmail.com
Wed Oct 13 22:53:13 BST 2021
On Wed, 13 Oct 2021 at 21:38, Chris McGowan <cmcgowan9990@gmail.com> wrote:
>
> > Unfortunately, no. For example, take this line: `# Foo bar I'm a level-1 title`
> > A 3-char substring of that would yield "# F", which isn't useful.
>
> In what way isn't it useful? It tells you literally everything you need
> to know.

> my $first3 = substr $line, 0, 3;

*This* is what I assumed you mean by
> … simply taking a three character substring of the line should be enough …
Seems there was a misunderstanding or something, apologies.
I'll respond to the rest of the email with the assumption there wasn't
a misunderstanding.

> # slightly magical regex, /g will return an array of matches,
> # assigning back to a scalar gives us a count of matches
> if ( my $level = $first3 =~ m/(#)+/g )
> {
>    return "Level $level header";
> [...]
> ```

Using RegEx this way is in effect doing the starts-with method I
mentioned in my other email.

> In fact, the substring isn't even necessary in this code

"In what way isn't it useful?", here's the answer.
It's useful as a method for limiting counts of '#', but that could
also be done with a `max(count, 3)` or you might not even be doing
counts.

> but that's largely true for languages which have decent regex support.

A `.StartsWith(foo)` method works too.
For doing the counting '#' part this way, you'd do something along the lines of:
```C# code
if (line.StartWith('#')) {
    int count = line.SubString(0,3).Count(c => c == '#').Length;
OR
    int count = Math.Max(line.Count(c => c == '#').Length, 3);
```
(Note: this code isn't tested, and there are faster ways to count
chars than Count, it's used here for clarity)

> If you weren't using one of those (i.e. C) or are for some reason
> allergic to regexes you could simply index the string to determine the
> line type (note: this would likely improve speed, but probably only a
> imperceptibly small amount and likely wouldn't be worth it.)
>
> Just to really drive home the point that this isn't a difficult task,
> here's the version I wouldn't write unless I was using C (still in Perl
> though):
>
> ```
> # Note: split here is because perl doesn't allow direct subscripting of
> # strings. In languages that do allow that, this other array is
> # unnecessary and you could use $line directly.
> my @first3 = split( "", substr( $line, 0, 3));
> if ( $first3[0] eq '#' )
> {
>    if ( $first3[1] eq '#' )
>    {
>      if ( $first3[2] eq '#' )
>      {
>        return "Level 3 header";
>      }
>      return "Level 2 header";
>    }
>    return "Level 1 header";
> }

Certainly an interesting method for header lines.
Since this is "Perl but with C tactics" code: does Perl have a switch statement?

> In summary, I hardly think it's impossible or even difficult to
> unambiguously parse gemtext without having a mandatory space.

I never claimed that it wasn't, just that it's easier to program.


Here's a simple parser using the split-on-first-space method:
```C# code
// Max split of three is used so this can be re-used later when doing
link-lines, no need to do more than that anyways
string[] splitLine = line.Split(" ", 3)
switch (splitLine[0].SubString(0,3)) {
    case "#":
    case "##":
    case "###":
        Console.PrintLine("Header level of {0} with text {1}",
splitLine[0].Length, line[3..]);
        // Rather than counting the header length, you could also just
use the other `case` statements.
        break;
    case "=>":
        Console.PrintLine("Link line with link {0}, title {1}",
splitLine[1], splitLine[2]);
        break;
    [… and so on …]
    default:
        Console.PrintLine("Normal or preformatted line");
        break;
}
```

Thanks for your code examples,
-Oliver Simmons (GoodClover)


Archive home | About this archive