refactor: get zine watcher to build in flow
This commit is contained in:
parent
db4e3e1936
commit
b698fffd25
7 changed files with 90 additions and 30 deletions
|
|
@ -241,3 +241,22 @@ pub fn buffer_from_ref(self: *Self, buffer_ref: usize) ?*Buffer {
|
||||||
pub fn buffer_to_ref(_: *Self, buffer: *Buffer) usize {
|
pub fn buffer_to_ref(_: *Self, buffer: *Buffer) usize {
|
||||||
return @intFromPtr(buffer);
|
return @intFromPtr(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const watcher = @import("watcher");
|
||||||
|
|
||||||
|
pub fn watch_all_buffers(self: *Self) watcher.Error!void {
|
||||||
|
var debouncer: watcher.Debouncer = .{};
|
||||||
|
var buffers: std.ArrayList([]const u8) = .empty;
|
||||||
|
var iter = self.buffers.keyIterator();
|
||||||
|
while (iter.next()) |key| {
|
||||||
|
(try buffers.addOne(self.allocator)).* = key.*;
|
||||||
|
}
|
||||||
|
|
||||||
|
var watcher_: watcher.Watcher = try .init(
|
||||||
|
self.allocator,
|
||||||
|
&debouncer,
|
||||||
|
&.{}, // dirs_to_watch.items,
|
||||||
|
);
|
||||||
|
|
||||||
|
try watcher_.start();
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1401,6 +1401,15 @@ const cmds = struct {
|
||||||
} else return error.InvalidSwapTabsArgument;
|
} else return error.InvalidSwapTabsArgument;
|
||||||
}
|
}
|
||||||
pub const place_next_tab_meta: Meta = .{ .arguments = &.{ .string, .integer } };
|
pub const place_next_tab_meta: Meta = .{ .arguments = &.{ .string, .integer } };
|
||||||
|
|
||||||
|
pub fn enable_file_watcher(self: *Self, _: Ctx) Result {
|
||||||
|
self.buffer_manager.watch_all_buffers() catch |e| {
|
||||||
|
const logger = log.logger("watcher");
|
||||||
|
defer logger.deinit();
|
||||||
|
logger.print_err("watcher", "failed to watch all buffes: {s}", .{@errorName(e)});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
pub const enable_file_watcher_meta: Meta = .{ .description = "Enable file watcher" };
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn handle_editor_event(self: *Self, _: tp.pid_ref, m: tp.message) tp.result {
|
pub fn handle_editor_event(self: *Self, _: tp.pid_ref, m: tp.message) tp.result {
|
||||||
|
|
|
||||||
8
src/watcher/Debouncer.zig
Normal file
8
src/watcher/Debouncer.zig
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
const Debouncer = @This();
|
||||||
|
|
||||||
|
/// Thread-safe. To be called when a new event comes in
|
||||||
|
pub fn newEvent(d: *Debouncer) void {
|
||||||
|
_ = d;
|
||||||
|
}
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
const LinuxWatcher = @This();
|
const LinuxWatcher = @This();
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const fatal = @import("../../../fatal.zig");
|
const Debouncer = @import("Debouncer.zig");
|
||||||
const Debouncer = @import("../../serve.zig").Debouncer;
|
const Error = @import("root.zig").Error;
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
|
|
||||||
const log = std.log.scoped(.watcher);
|
const log = std.log.scoped(.watcher);
|
||||||
|
|
@ -30,11 +30,7 @@ pub fn init(
|
||||||
gpa: std.mem.Allocator,
|
gpa: std.mem.Allocator,
|
||||||
debouncer: *Debouncer,
|
debouncer: *Debouncer,
|
||||||
dir_paths: []const []const u8,
|
dir_paths: []const []const u8,
|
||||||
) LinuxWatcher {
|
) Error!LinuxWatcher {
|
||||||
errdefer |err| fatal.msg("error: unable to start the file watcher: {s}", .{
|
|
||||||
@errorName(err),
|
|
||||||
});
|
|
||||||
|
|
||||||
const notify_fd = try std.posix.inotify_init1(0);
|
const notify_fd = try std.posix.inotify_init1(0);
|
||||||
var watcher: LinuxWatcher = .{
|
var watcher: LinuxWatcher = .{
|
||||||
.gpa = gpa,
|
.gpa = gpa,
|
||||||
|
|
@ -300,7 +296,7 @@ pub fn listen(watcher: *LinuxWatcher) !void {
|
||||||
|
|
||||||
var event_data = buffer[0..len];
|
var event_data = buffer[0..len];
|
||||||
while (event_data.len > 0) {
|
while (event_data.len > 0) {
|
||||||
const event: *Event = @alignCast(@ptrCast(event_data[0..event_size]));
|
const event: *Event = @ptrCast(@alignCast(event_data[0..event_size]));
|
||||||
const parent = watcher.watch_fds.get(event.wd).?;
|
const parent = watcher.watch_fds.get(event.wd).?;
|
||||||
event_data = event_data[event_size + event.len ..];
|
event_data = event_data[event_size + event.len ..];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
const MacosWatcher = @This();
|
const MacosWatcher = @This();
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const fatal = @import("../../../fatal.zig");
|
const Debouncer = @import("Debouncer.zig");
|
||||||
const Debouncer = @import("../../serve.zig").Debouncer;
|
|
||||||
|
|
||||||
const c = @cImport({
|
const c = @cImport({
|
||||||
@cInclude("CoreServices/CoreServices.h");
|
@cInclude("CoreServices/CoreServices.h");
|
||||||
|
|
@ -31,11 +30,7 @@ pub fn start(watcher: *MacosWatcher) !void {
|
||||||
t.detach();
|
t.detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn listen(watcher: *MacosWatcher) void {
|
pub fn listen(watcher: *MacosWatcher) error{ OutOfMemory, FSEventStreamError }!void {
|
||||||
errdefer |err| switch (err) {
|
|
||||||
error.OutOfMemory => fatal.oom(),
|
|
||||||
};
|
|
||||||
|
|
||||||
const macos_paths = try watcher.gpa.alloc(
|
const macos_paths = try watcher.gpa.alloc(
|
||||||
c.CFStringRef,
|
c.CFStringRef,
|
||||||
watcher.dir_paths.len,
|
watcher.dir_paths.len,
|
||||||
|
|
@ -74,9 +69,8 @@ pub fn listen(watcher: *MacosWatcher) void {
|
||||||
c.kCFRunLoopDefaultMode,
|
c.kCFRunLoopDefaultMode,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (c.FSEventStreamStart(stream) == 0) {
|
if (c.FSEventStreamStart(stream) == 0)
|
||||||
fatal.msg("error: macos watcher FSEventStreamStart failed", .{});
|
return error.FSEventStreamError;
|
||||||
}
|
|
||||||
|
|
||||||
c.CFRunLoopRun();
|
c.CFRunLoopRun();
|
||||||
|
|
||||||
|
|
@ -98,9 +92,9 @@ pub fn macosCallback(
|
||||||
_ = eventIds;
|
_ = eventIds;
|
||||||
_ = eventFlags;
|
_ = eventFlags;
|
||||||
_ = streamRef;
|
_ = streamRef;
|
||||||
const watcher: *MacosWatcher = @alignCast(@ptrCast(clientCallBackInfo));
|
const watcher: *MacosWatcher = @ptrCast(@alignCast(clientCallBackInfo));
|
||||||
|
|
||||||
const paths: [*][*:0]u8 = @alignCast(@ptrCast(eventPaths));
|
const paths: [*][*:0]u8 = @ptrCast(@alignCast(eventPaths));
|
||||||
for (paths[0..numEvents]) |p| {
|
for (paths[0..numEvents]) |p| {
|
||||||
const path = std.mem.span(p);
|
const path = std.mem.span(p);
|
||||||
log.debug("Changed: {s}\n", .{path});
|
log.debug("Changed: {s}\n", .{path});
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,7 @@ const WindowsWatcher = @This();
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const windows = std.os.windows;
|
const windows = std.os.windows;
|
||||||
const fatal = @import("../../../fatal.zig");
|
const Debouncer = @import("Debouncer.zig");
|
||||||
const Debouncer = @import("../../serve.zig").Debouncer;
|
|
||||||
|
|
||||||
const log = std.log.scoped(.watcher);
|
const log = std.log.scoped(.watcher);
|
||||||
|
|
||||||
|
|
@ -40,11 +39,7 @@ pub fn init(
|
||||||
gpa: std.mem.Allocator,
|
gpa: std.mem.Allocator,
|
||||||
debouncer: *Debouncer,
|
debouncer: *Debouncer,
|
||||||
dir_paths: []const []const u8,
|
dir_paths: []const []const u8,
|
||||||
) WindowsWatcher {
|
) !WindowsWatcher {
|
||||||
errdefer |err| fatal.msg("error: unable to start the file watcher: {s}", .{
|
|
||||||
@errorName(err),
|
|
||||||
});
|
|
||||||
|
|
||||||
var watcher = WindowsWatcher{
|
var watcher = WindowsWatcher{
|
||||||
.debouncer = debouncer,
|
.debouncer = debouncer,
|
||||||
.iocp_port = windows.INVALID_HANDLE_VALUE,
|
.iocp_port = windows.INVALID_HANDLE_VALUE,
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,47 @@
|
||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
|
|
||||||
pub const Watcher = switch (builtin.target.os.tag) {
|
pub const Watcher = switch (builtin.target.os.tag) {
|
||||||
.linux => @import("serve/watcher/LinuxWatcher.zig"),
|
.linux => @import("LinuxWatcher.zig"),
|
||||||
.macos => @import("serve/watcher/MacosWatcher.zig"),
|
.macos => @import("MacosWatcher.zig"),
|
||||||
.windows => @import("serve/watcher/WindowsWatcher.zig"),
|
.windows => @import("WindowsWatcher.zig"),
|
||||||
else => @compileError("unsupported platform"),
|
else => @compileError("unsupported platform"),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const Debouncer = @import("Debouncer.zig");
|
||||||
|
|
||||||
|
pub const Error = error{
|
||||||
|
OutOfMemory,
|
||||||
|
SystemResources,
|
||||||
|
Unexpected,
|
||||||
|
ProcessFdQuotaExceeded,
|
||||||
|
SystemFdQuotaExceeded,
|
||||||
|
LockedMemoryLimitExceeded,
|
||||||
|
ThreadQuotaExceeded,
|
||||||
|
IsDir,
|
||||||
|
WouldBlock,
|
||||||
|
AccessDenied,
|
||||||
|
ProcessNotFound,
|
||||||
|
PermissionDenied,
|
||||||
|
FileTooBig,
|
||||||
|
NoSpaceLeft,
|
||||||
|
DeviceBusy,
|
||||||
|
NoDevice,
|
||||||
|
SharingViolation,
|
||||||
|
PathAlreadyExists,
|
||||||
|
FileNotFound,
|
||||||
|
PipeBusy,
|
||||||
|
NameTooLong,
|
||||||
|
InvalidUtf8,
|
||||||
|
InvalidWtf8,
|
||||||
|
BadPathName,
|
||||||
|
NetworkNotFound,
|
||||||
|
AntivirusInterference,
|
||||||
|
SymLinkLoop,
|
||||||
|
NotDir,
|
||||||
|
FileLocksNotSupported,
|
||||||
|
FileBusy,
|
||||||
|
UserResourceLimitReached,
|
||||||
|
WatchAlreadyExists,
|
||||||
|
InvalidHandle,
|
||||||
|
QueueFailed,
|
||||||
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue