Skip to content

Commit

Permalink
Add text editor 2 blog entry to newsletter with static content
Browse files Browse the repository at this point in the history
  • Loading branch information
Skytrias committed May 23, 2024
1 parent e0ff902 commit 4f93f26
Show file tree
Hide file tree
Showing 5 changed files with 204 additions and 2 deletions.
206 changes: 204 additions & 2 deletions content/news/2024-06.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ title: June 2024 Newsletter
summary: Highlights for June - Showcasing ***X*** Community Projects
slug: newsletter-2024-06
author: Michael Kutowski
date: '2024-05-30'
date: '2024-05-30'
draft: true
categories:
- newsletter
Expand All @@ -24,6 +24,208 @@ Read up on the compiler changes in the [monthly release](https://github.com/odin

## Text Editor Experimentation #2 (Skytrias)

TODO
Last month I showed off my text editor with a bit of a twist in terms of buffer management. This time around we'll look into what other approaches exist.

### Dion

***Dion*** was a demo project showed off at around the handmade circles about having an AST (Abstract Syntax Tree) level editor. Sadly the project has been discontinued and the website is now down, but luckily I have saved some of the showcase material. I'll show one of them as long as the creators are okay with it.

<figure class="figure w-100 text-center">
<img src="/images/news/2024-06-skytrias1.gif" class="figure-img img-fluid rounded">
<figcaption class="figure-caption text-center">An AST can be presented in different syntax outputs. The tree still remains editable in any syntax.
</figcaption>
</figure>

<figure class="figure w-100 text-center">
<img src="/images/news/2024-06-skytrias2.gif" class="figure-img img-fluid rounded">
<figcaption class="figure-caption text-center">Lovely feature that mostly IDE's have - Renaming locals or globals.
</figcaption>
</figure>

I'm not certain why the project has been dropped. I think it's sad that nobody is actively developing something like ***Dion*** anymore. If you know anybody who still does, let me know!

### Getting Started

I've always wanted something like this for odin. We'll get into the difficulties that may arrise later.

<figure class="figure w-100 text-center">
<img src="/images/news/2024-06-skytrias4.png" class="figure-img img-fluid rounded">
<figcaption class="figure-caption text-center">Looks simple enough right?
</figcaption>
</figure>

It's worth mentioning that I'm not a programming language guy. AST's and everything surrounding it were quite new to me. It took a while to understand how odin's AST works.

As we already have a nice `core:odin/ast` / `core:odin/parser` package, it was easy to get started analyzing the output, of what the raw text would equate to.

### AST Structure & Examples

I won't go into too much detail but basically odin's AST is split up into *Statements* and *Expressions*. There are also *Declarations* and *Types* but which can be thought of subtypes.

So a generic node for odin would look something like this:

```
Node :: struct {
// linked list
prev: ^Node,
next: ^Node,
parent: ^Node,
node_type: Node_Type,
// sub lists
names: List,
values: List,
params: List,
// ...
// sub nodes
body: ^Node,
type: ^Node,
init: ^Node,
cond: ^Node,
body: ^Node,
extra: ^Node,
// ...
// properties
}
Node_Type :: enum {
// ...
}
```

Let's try out a simple example first

```
some_value: int
```

Equals

```
Declaration_Value ":"
- NAMES
- Expression_Identifier "some_value"
- TYPE
- Expression_Identifier "int"
- VALUES
- empty
```

But it could also get more complex

```
value1, value2, value3: int = 1, 2, 3
```

Equals

```
Declaration_Value ":"
- NAMES
- Expression_Identifier "value1"
- Expression_Identifier "value2"
- Expression_Identifier "value3"
- TYPE
- Expression_Identifier "int"
- VALUES
- Expression_Basic_Literal (integer) "1"
- Expression_Basic_Literal (integer) "2"
- Expression_Basic_Literal (integer) "3"
```

Let's try an odin procedure, can you guess how it's built up?

```
some_procedure :: proc() {
}
```

Would turn out to be

```
Declaration_Value "::"
- NAMES
- Expression_Identifier "some_procedure"
- VALUES
- Expression_Procedure_Literal "proc"
- BODY
- Statement_Block "{...}"
- TYPE
- Type_Procedure "(...)"
- PARAMS (procedure arguments)
- ...
- ...
- ...
```

Quite complex just for a procedure, don't you think?

### AST Creation

First we have to figure out our `Node` structure and how we'll layout things. As you can see above my approach was to go very untyped. Nodes would infer what would have to be used just by their `node_type`.

Once we got that figured out we'll need ways to manually create the AST to test out all the odin features.

My method was to look what the `core:odin/ast` would spit out and recreate that tree. I ended up with roughly ~10 test functions which would go through different scenarios.

### AST Rendering

Debug printing won't get us far and the goal is to render the AST anyway. It sounds complex, but once we figure out how nodes would recursively draw their sub sections it turns out to be simple.

For now we just want to render the AST back to the original textual syntax.

<figure class="figure w-100 text-center">
<img src="/images/news/2024-06-skytrias3.png" class="figure-img img-fluid rounded">
<figcaption class="figure-caption text-center">Basic Rendering: brown = identifiers, white = automatic syntax, rest = literals
</figcaption>
</figure>

To draw the entire odin AST I ended up with around with roughly 600 loc (excluding rendering logic)!

Here's a basic example of a block statement `{ ... }` and an identifier node would render their content.
```
node_ui :: proc(using draw: ^Draw_State, node: ^tree.Node)
sub: Rect
switch (node.node_type) {
// ...
case .Stmt_Block:
draw_text_basic_inc(draw, &sub, "{")
column = 0
line += 1
indentation += 1
// draw children statements
for s := node.values.head; s != nil; s = s.next {
node_ui(draw, &sub, s)
column = 0
line += 1
}
indentation -= 1
draw_text_basic_inc(draw, &sub, "}")
column += 1
// ...
case .Expr_Ident:
draw_text_ident_inc(draw, &sub, node.content, node) // node.content is strings.Builder
// ...
}
}
```

### Wrapping Up

Since the short blog is getting quite long already we'll take a break here and dive into editor navigation, editing and the other painful things that the AST editing ends up becoming.

If you're interested in AST editing let us know!

---
Binary file added static/images/news/2024-06-skytrias1.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added static/images/news/2024-06-skytrias2.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added static/images/news/2024-06-skytrias3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added static/images/news/2024-06-skytrias4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 4f93f26

Please sign in to comment.