+10
src/app.zig
+10
src/app.zig
···
6
6
const config = &@import("./config.zig").config;
7
7
const List = @import("./list.zig").List;
8
8
const Directories = @import("./directories.zig");
9
+
const FileLogger = @import("./file_logger.zig");
9
10
const CircStack = @import("./circ_stack.zig").CircularStack;
10
11
const zuid = @import("zuid");
11
12
const vaxis = @import("vaxis");
···
54
55
55
56
directories: Directories,
56
57
notification: Notification,
58
+
// Assigned in main after config parsing.
59
+
file_logger: FileLogger = undefined,
57
60
58
61
text_input: vaxis.widgets.TextInput,
59
62
text_input_buf: [std.fs.max_path_bytes]u8 = undefined,
···
107
110
self.text_input.deinit();
108
111
self.vx.deinit(self.alloc, self.tty.anyWriter());
109
112
self.tty.deinit();
113
+
self.file_logger.deinit();
110
114
}
111
115
112
116
pub fn run(self: *App) !void {
···
140
144
} else |err| switch (err) {
141
145
error.SyntaxError => {
142
146
try self.notification.writeErr(.ConfigSyntaxError);
147
+
},
148
+
error.InvalidCharacter => {
149
+
try self.notification.writeErr(.InvalidKeybind);
150
+
},
151
+
error.DuplicateKeybind => {
152
+
try self.notification.writeErr(.DuplicateKeybinds);
143
153
},
144
154
else => {
145
155
try self.notification.writeErr(.ConfigUnknownError);
+13
src/config.zig
+13
src/config.zig
···
2
2
const builtin = @import("builtin");
3
3
const environment = @import("./environment.zig");
4
4
const vaxis = @import("vaxis");
5
+
const FileLogger = @import("file_logger.zig");
5
6
const Notification = @import("./notification.zig");
6
7
7
8
const CONFIG_NAME = "config.json";
···
103
104
104
105
// Check duplicate keybinds
105
106
{
107
+
var file_logger = try FileLogger.init(alloc);
108
+
defer file_logger.deinit();
109
+
106
110
var key_map = std.AutoHashMap(u21, []const u8).init(alloc);
107
111
defer {
108
112
var it = key_map.iterator();
···
117
121
118
122
const res = try key_map.getOrPut(codepoint);
119
123
if (res.found_existing) {
124
+
const message = try std.fmt.allocPrint(
125
+
alloc,
126
+
"'{s}' and '{s}' have the same keybind: '{d}'",
127
+
.{ res.value_ptr.*, field.name, codepoint },
128
+
);
129
+
defer alloc.free(message);
130
+
131
+
file_logger.write(message, .err) catch {};
132
+
120
133
return error.DuplicateKeybind;
121
134
}
122
135
res.value_ptr.* = try alloc.dupe(u8, field.name);
+60
src/file_logger.zig
+60
src/file_logger.zig
···
1
+
const std = @import("std");
2
+
const environment = @import("environment.zig");
3
+
const config = &@import("./config.zig").config;
4
+
5
+
pub const LOG_PATH = "log.txt";
6
+
7
+
const LogLevel = enum {
8
+
err,
9
+
info,
10
+
warn,
11
+
12
+
pub fn toString(level: LogLevel) []const u8 {
13
+
return switch (level) {
14
+
.err => "ERROR",
15
+
.info => "INFO",
16
+
.warn => "WARN",
17
+
};
18
+
}
19
+
};
20
+
21
+
const FileLogger = @This();
22
+
23
+
alloc: std.mem.Allocator,
24
+
dir: std.fs.Dir,
25
+
26
+
pub fn init(alloc: std.mem.Allocator) !FileLogger {
27
+
const file_logger = FileLogger{
28
+
.alloc = alloc,
29
+
.dir = try config.configDir() orelse return error.UnableToFindConfigDir,
30
+
};
31
+
32
+
if (!environment.fileExists(file_logger.dir, LOG_PATH)) {
33
+
_ = try file_logger.dir.createFile(LOG_PATH, .{});
34
+
}
35
+
36
+
return file_logger;
37
+
}
38
+
39
+
pub fn deinit(self: FileLogger) void {
40
+
var dir = self.dir;
41
+
dir.close();
42
+
}
43
+
44
+
pub fn write(self: FileLogger, msg: []const u8, level: LogLevel) !void {
45
+
var log = try self.dir.openFile(LOG_PATH, .{ .mode = .write_only });
46
+
defer log.close();
47
+
48
+
const message = try std.fmt.allocPrint(
49
+
self.alloc,
50
+
"({d}) {s}: {s}\n",
51
+
.{ std.time.timestamp(), LogLevel.toString(level), msg },
52
+
);
53
+
defer self.alloc.free(message);
54
+
55
+
if (try log.tryLock(std.fs.File.Lock.shared)) {
56
+
defer log.unlock();
57
+
try log.seekFromEnd(0);
58
+
try log.writeAll(message);
59
+
}
60
+
}
+3
src/main.zig
+3
src/main.zig
···
1
1
const std = @import("std");
2
2
const builtin = @import("builtin");
3
3
const App = @import("app.zig");
4
+
const FileLogger = @import("file_logger.zig");
4
5
const vaxis = @import("vaxis");
5
6
const config = &@import("./config.zig").config;
6
7
···
40
41
try app.notification.writeErr(.ConfigUnknownError);
41
42
},
42
43
};
44
+
45
+
app.file_logger = try FileLogger.init(alloc);
43
46
44
47
try app.run();
45
48
}