fix: break from interating the BindingSet before executing matched command
This prevents a crash. If the executed command switches modes the BindingSet being iterated will be deleted. This commit fixes this by exiting the iteration on match and executing the command at a point where it is safe to delete the BindingSet.
This commit is contained in:
parent
4e7ccd1e00
commit
175d2d968e
1 changed files with 12 additions and 15 deletions
|
@ -585,11 +585,14 @@ const BindingSet = struct {
|
||||||
tp.string,
|
tp.string,
|
||||||
tp.extract(&modifiers),
|
tp.extract(&modifiers),
|
||||||
})) {
|
})) {
|
||||||
self.process_key_event(egc, .{
|
if (self.process_key_event(egc, .{
|
||||||
.event = event,
|
.event = event,
|
||||||
.key = keypress,
|
.key = keypress,
|
||||||
.modifiers = modifiers,
|
.modifiers = modifiers,
|
||||||
}) catch |e| return tp.exit_error(e, @errorReturnTrace());
|
}) catch |e| return tp.exit_error(e, @errorReturnTrace())) |binding| {
|
||||||
|
if (!builtin.is_test) self.logger.print("execute '{s}'", .{binding.command});
|
||||||
|
try binding.execute();
|
||||||
|
}
|
||||||
} else if (try m.match(.{"F"})) {
|
} else if (try m.match(.{"F"})) {
|
||||||
self.flush() catch |e| return tp.exit_error(e, @errorReturnTrace());
|
self.flush() catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||||
} else if (try m.match(.{ "system_clipboard", tp.extract(&text) })) {
|
} else if (try m.match(.{ "system_clipboard", tp.extract(&text) })) {
|
||||||
|
@ -601,10 +604,10 @@ const BindingSet = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
//register a key press and try to match it with a binding
|
//register a key press and try to match it with a binding
|
||||||
fn process_key_event(self: *BindingSet, egc: input.Key, event: KeyEvent) !void {
|
fn process_key_event(self: *BindingSet, egc: input.Key, event: KeyEvent) !?*Binding {
|
||||||
|
|
||||||
//hacky fix since we are ignoring repeats and keyups right now
|
//hacky fix since we are ignoring repeats and keyups right now
|
||||||
if (event.event != input.event.press) return;
|
if (event.event != input.event.press) return null;
|
||||||
|
|
||||||
//clear key history if enough time has passed since last key press
|
//clear key history if enough time has passed since last key press
|
||||||
const timestamp = std.time.milliTimestamp();
|
const timestamp = std.time.milliTimestamp();
|
||||||
|
@ -635,24 +638,17 @@ const BindingSet = struct {
|
||||||
match_possible_count,
|
match_possible_count,
|
||||||
match_impossible_count,
|
match_impossible_count,
|
||||||
});
|
});
|
||||||
for (self.bindings.items) |binding| blk: {
|
for (self.bindings.items) |*binding| {
|
||||||
switch (binding.match(self.current_sequence.items)) {
|
switch (binding.match(self.current_sequence.items)) {
|
||||||
.matched => {
|
.matched => {
|
||||||
matched_count += 1;
|
matched_count += 1;
|
||||||
errdefer {
|
defer {
|
||||||
//clear current sequence if command execution fails
|
//clear current sequence if command execution fails
|
||||||
self.current_sequence.clearRetainingCapacity();
|
self.current_sequence.clearRetainingCapacity();
|
||||||
self.current_sequence_egc.clearRetainingCapacity();
|
self.current_sequence_egc.clearRetainingCapacity();
|
||||||
}
|
}
|
||||||
|
if (!builtin.is_test) self.logger.print("matched binding -> {s}", .{binding.command});
|
||||||
if (!builtin.is_test) {
|
return binding;
|
||||||
self.logger.print("matched binding -> {s}", .{binding.command});
|
|
||||||
if (!builtin.is_test) self.logger.print("execute '{s}'", .{binding.command});
|
|
||||||
try binding.execute();
|
|
||||||
}
|
|
||||||
self.current_sequence.clearRetainingCapacity();
|
|
||||||
self.current_sequence_egc.clearRetainingCapacity();
|
|
||||||
break :blk;
|
|
||||||
},
|
},
|
||||||
.match_possible => {
|
.match_possible => {
|
||||||
match_possible_count += 1;
|
match_possible_count += 1;
|
||||||
|
@ -668,6 +664,7 @@ const BindingSet = struct {
|
||||||
if (all_matches_impossible) {
|
if (all_matches_impossible) {
|
||||||
try self.terminate_sequence(.match_impossible, egc, event);
|
try self.terminate_sequence(.match_impossible, egc, event);
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const AbortType = enum { timeout, match_impossible };
|
const AbortType = enum { timeout, match_impossible };
|
||||||
|
|
Loading…
Add table
Reference in a new issue