summary refs log tree commit diff
path: root/src/main.zig
blob: 5e91719dc0014d29fbbeff9996c89d2b8bd5c81f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
// Entry point
// SPDX-FileCopyrightText: 2025 Nguyễn Gia Phong
// SPDX-License-Identifier: GPL-3.0-or-later

const Allocator = std.mem.Allocator;
const DebugAllocator = std.heap.DebugAllocator;
const builtin = @import("builtin");
const eql = std.mem.eql;
const ns_per_s = std.time.ns_per_s;
const smp_allocator = std.heap.smp_allocator;
const std = @import("std");

const Key = vaxis.Key;
const Loop = vaxis.Loop;
const Tty = vaxis.Tty;
const Unicode = vaxis.Unicode;
const Winsize = vaxis.Winsize;
const gwidth = vaxis.gwidth.gwidth;
const vaxis = @import("vaxis");
const zsanett = @import("zsanett");

const Config = @import("Config.zig");
const Token = @import("Token.zig");
const languages = @import("languages");

const Event = union(enum) {
    key_press: Key,
    winsize: Winsize,
};

pub fn main() !void {
    var debug_allocator = DebugAllocator(.{}).init;
    defer _ = debug_allocator.deinit();
    const allocator = switch (builtin.mode) {
        .Debug, .ReleaseSafe => debug_allocator.allocator(),
        .ReleaseFast, .ReleaseSmall => smp_allocator,
    };

    zsanett.init();
    defer zsanett.deinit();
    const janet_env = zsanett.coreEnv(null);
    const config = try Config.parse(allocator, janet_env);

    var tty = try Tty.init();
    defer tty.deinit();
    var vx = try vaxis.init(allocator, .{});
    defer vx.deinit(allocator, tty.anyWriter());
    var loop = Loop(Event){ .tty = &tty, .vaxis = &vx };
    try loop.init();
    try loop.start();
    defer loop.stop();

    try vx.enterAltScreen(tty.anyWriter());
    // For the alternate screen
    try vx.queryTerminal(tty.anyWriter(), 1 * ns_per_s);

    const text = "int main()\n{\n\treturn 0;\n}\n";
    var tokens = try Token.ize(text, languages.c);
    defer tokens.deinit();

    while (true) {
        switch (loop.nextEvent()) {
            .key_press => |key| {
                if (key.matches('c', .{ .ctrl = true })) {
                    break;
                }
            },
            .winsize => |ws| try vx.resize(allocator, tty.anyWriter(), ws),
        }
        const window = vx.window();
        window.clear();
        var col: u16 = 0;
        var row: u16 = 0;
        tokens.reset();
        while (tokens.next()) |token| {
            var graphemes = vx.unicode.graphemeIterator(token.text);
            while (graphemes.next()) |grapheme| {
                const bytes = grapheme.bytes(token.text);
                if (eql(u8, bytes, "\r\n")
                    or eql(u8, bytes, "\r")
                    or eql(u8, bytes, "\n")) {
                    col = 0;
                    row += 1;
                    continue;
                }
                const width: u8 = if (eql(u8, bytes, "\t"))
                    config.tab_width
                else
                    @intCast(gwidth(bytes, vx.caps.unicode,
                                    &vx.unicode.width_data));
                defer col += width;
                window.writeCell(col, row, .{
                    .char = .{ .grapheme = bytes, .width = width },
                });
            }
        }
        try vx.render(tty.anyWriter());
    }
}