Compare commits

..

No commits in common. "2520a37a9076a29897bc79b68a56ef7583406e80" and "e35a0555f16ef77a8f34368ded6868ec46661358" have entirely different histories.

5 changed files with 20 additions and 81 deletions

View file

@ -17,8 +17,6 @@ pub const Cursor = @import("Cursor.zig");
pub const View = @import("View.zig"); pub const View = @import("View.zig");
pub const Selection = @import("Selection.zig"); pub const Selection = @import("Selection.zig");
pub const FindMode = enum { exact, case_folded };
pub const Metrics = struct { pub const Metrics = struct {
ctx: *const anyopaque, ctx: *const anyopaque,
egc_length: egc_length_func, egc_length: egc_length_func,
@ -945,10 +943,10 @@ const Node = union(enum) {
} }
} }
pub const FindMode = enum { exact, case_folded };
pub const FindAllCallback = fn (data: *anyopaque, begin_row: usize, begin_col: usize, end_row: usize, end_col: usize) error{Stop}!void; pub const FindAllCallback = fn (data: *anyopaque, begin_row: usize, begin_col: usize, end_row: usize, end_col: usize) error{Stop}!void;
pub fn find_all_ranges(self: *const Node, pattern: []const u8, data: *anyopaque, callback: *const FindAllCallback, mode: FindMode, allocator: Allocator) error{ OutOfMemory, Stop }!void { pub fn find_all_ranges(self: *const Node, pattern: []const u8, data: *anyopaque, callback: *const FindAllCallback, mode: FindMode, allocator: Allocator) error{ OutOfMemory, Stop }!void {
const Ctx = struct { const Ctx = struct {
allocator: std.mem.Allocator,
pattern: []const u8, pattern: []const u8,
data: *anyopaque, data: *anyopaque,
callback: *const FindAllCallback, callback: *const FindAllCallback,
@ -987,11 +985,7 @@ const Node = union(enum) {
input = input[input_consume_size..]; input = input[input_consume_size..];
}, },
.case_folded => { .case_folded => {
const input_consume_size = @min(ctx.buf.len - ctx.rest.len, input.len); @panic("unimplemented");
var writer = std.Io.Writer.fixed(ctx.buf[ctx.rest.len..]);
unicode.case_folded_write(&writer, input[0..input_consume_size]) catch return error.WriteFailed;
ctx.rest = ctx.buf[0 .. ctx.rest.len + writer.end];
input = input[input_consume_size..];
}, },
} }
@ -1036,7 +1030,6 @@ const Node = union(enum) {
} }
}; };
var ctx: Ctx = .{ var ctx: Ctx = .{
.allocator = allocator,
.pattern = pattern, .pattern = pattern,
.data = data, .data = data,
.callback = callback, .callback = callback,

View file

@ -113,7 +113,9 @@ pub const TransformError = error{
WriteFailed, WriteFailed,
}; };
fn utf8_write_transform(comptime field: uucode.FieldEnum, writer: *std.Io.Writer, text: []const u8) TransformError!void { fn utf8_transform(comptime field: uucode.FieldEnum, allocator: std.mem.Allocator, text: []const u8) TransformError![]u8 {
var result: std.Io.Writer.Allocating = .init(allocator);
defer result.deinit();
const view: std.unicode.Utf8View = try .init(text); const view: std.unicode.Utf8View = try .init(text);
var it = view.iterator(); var it = view.iterator();
while (it.nextCodepoint()) |cp| { while (it.nextCodepoint()) |cp| {
@ -124,18 +126,12 @@ fn utf8_write_transform(comptime field: uucode.FieldEnum, writer: *std.Io.Writer
}; };
var utf8_buf: [6]u8 = undefined; var utf8_buf: [6]u8 = undefined;
const size = try std.unicode.utf8Encode(cp_, &utf8_buf); const size = try std.unicode.utf8Encode(cp_, &utf8_buf);
try writer.writeAll(utf8_buf[0..size]); try result.writer.writeAll(utf8_buf[0..size]);
} }
}
fn utf8_transform(comptime field: uucode.FieldEnum, allocator: std.mem.Allocator, text: []const u8) TransformError![]u8 {
var result: std.Io.Writer.Allocating = .init(allocator);
defer result.deinit();
try utf8_write_transform(field, &result.writer, text);
return result.toOwnedSlice(); return result.toOwnedSlice();
} }
fn utf8_predicate(comptime field: uucode.FieldEnum, text: []const u8) error{InvalidUtf8}!bool { fn utf8_predicate(comptime field: uucode.FieldEnum, text: []const u8) TransformError!bool {
const view: std.unicode.Utf8View = try .init(text); const view: std.unicode.Utf8View = try .init(text);
var it = view.iterator(); var it = view.iterator();
while (it.nextCodepoint()) |cp| { while (it.nextCodepoint()) |cp| {
@ -166,10 +162,6 @@ pub fn case_fold(allocator: std.mem.Allocator, text: []const u8) TransformError!
return utf8_transform(.case_folding_simple, allocator, text); return utf8_transform(.case_folding_simple, allocator, text);
} }
pub fn case_folded_write(writer: *std.Io.Writer, text: []const u8) TransformError!void {
return utf8_write_transform(.case_folding_simple, writer, text);
}
pub fn switch_case(allocator: std.mem.Allocator, text: []const u8) TransformError![]u8 { pub fn switch_case(allocator: std.mem.Allocator, text: []const u8) TransformError![]u8 {
return if (try utf8_predicate(.is_lowercase, text)) return if (try utf8_predicate(.is_lowercase, text))
to_upper(allocator, text) to_upper(allocator, text)
@ -177,9 +169,5 @@ pub fn switch_case(allocator: std.mem.Allocator, text: []const u8) TransformErro
to_lower(allocator, text); to_lower(allocator, text);
} }
pub fn is_lowercase(text: []const u8) error{InvalidUtf8}!bool {
return try utf8_predicate(.is_lowercase, text);
}
const std = @import("std"); const std = @import("std");
const uucode = @import("vaxis").uucode; const uucode = @import("vaxis").uucode;

View file

@ -558,7 +558,6 @@
["ctrl+space", "mini_mode_cancel"], ["ctrl+space", "mini_mode_cancel"],
["ctrl+enter", "mini_mode_insert_bytes", "\n"], ["ctrl+enter", "mini_mode_insert_bytes", "\n"],
["ctrl+backspace", "mini_mode_reset"], ["ctrl+backspace", "mini_mode_reset"],
["alt+c", "toggle_find_mode"],
["alt+v", "system_paste"], ["alt+v", "system_paste"],
["alt+n", "goto_next_match"], ["alt+n", "goto_next_match"],
["alt+p", "goto_prev_match"], ["alt+p", "goto_prev_match"],

View file

@ -5218,16 +5218,12 @@ pub const Editor = struct {
pub fn find_query(self: *Self, ctx: Context) Result { pub fn find_query(self: *Self, ctx: Context) Result {
var query: []const u8 = undefined; var query: []const u8 = undefined;
var match_type: Match.Type = undefined; var match_type: Match.Type = undefined;
var find_mode: Buffer.FindMode = .exact;
if (ctx.args.match(.{tp.extract(&query)}) catch false) { if (ctx.args.match(.{tp.extract(&query)}) catch false) {
self.match_type = .find; self.match_type = .find;
try self.find_in_buffer(query, .none, find_mode); try self.find_in_buffer(query, .none);
self.clamp(); self.clamp();
} else if (ctx.args.match(.{ tp.extract(&query), tp.extract(&match_type) }) catch false) { } else if (ctx.args.match(.{ tp.extract(&query), tp.extract(&match_type) }) catch false) {
try self.find_in_buffer(query, match_type, find_mode); try self.find_in_buffer(query, match_type);
self.clamp();
} else if (ctx.args.match(.{ tp.extract(&query), tp.extract(&match_type), tp.extract(&find_mode) }) catch false) {
try self.find_in_buffer(query, match_type, find_mode);
self.clamp(); self.clamp();
} else return error.InvalidFindQueryArgument; } else return error.InvalidFindQueryArgument;
} }
@ -5237,7 +5233,7 @@ pub const Editor = struct {
_ = ctx; _ = ctx;
const query: []const u8 = try self.copy_word_at_cursor(self.allocator); const query: []const u8 = try self.copy_word_at_cursor(self.allocator);
defer self.allocator.free(query); defer self.allocator.free(query);
try self.find_in_buffer(query, .find, .exact); try self.find_in_buffer(query, .find);
} }
pub const find_word_at_cursor_meta: Meta = .{ .description = "Search for the word under the cursor" }; pub const find_word_at_cursor_meta: Meta = .{ .description = "Search for the word under the cursor" };
@ -5278,13 +5274,13 @@ pub const Editor = struct {
} else self.last_find_query = self.allocator.dupe(u8, query) catch return; } else self.last_find_query = self.allocator.dupe(u8, query) catch return;
} }
pub fn find_in_buffer(self: *Self, query: []const u8, match_type: Match.Type, find_mode: Buffer.FindMode) !void { pub fn find_in_buffer(self: *Self, query: []const u8, match_type: Match.Type) !void {
self.set_last_find_query(query, match_type); self.set_last_find_query(query, match_type);
self.match_type = match_type; self.match_type = match_type;
return self.find_in_buffer_sync(query, find_mode); return self.find_in_buffer_sync(query);
} }
fn find_in_buffer_sync(self: *Self, query: []const u8, mode: Buffer.FindMode) !void { fn find_in_buffer_sync(self: *Self, query: []const u8) !void {
const Ctx = struct { const Ctx = struct {
matches: usize = 0, matches: usize = 0,
self: *Self, self: *Self,
@ -5300,7 +5296,7 @@ pub const Editor = struct {
defer self.add_match_done(); defer self.add_match_done();
var ctx: Ctx = .{ .self = self }; var ctx: Ctx = .{ .self = self };
self.init_matches_update(); self.init_matches_update();
try root.find_all_ranges(query, &ctx, Ctx.cb, mode, self.allocator); try root.find_all_ranges(query, &ctx, Ctx.cb, .exact, self.allocator);
} }
fn find_in_buffer_async(self: *Self, query: []const u8) !void { fn find_in_buffer_async(self: *Self, query: []const u8) !void {
@ -5515,7 +5511,7 @@ pub const Editor = struct {
if (self.matches.items.len == 0) { if (self.matches.items.len == 0) {
if (self.last_find_query) |last| { if (self.last_find_query) |last| {
self.find_operation = .goto_next_match; self.find_operation = .goto_next_match;
try self.find_in_buffer(last, self.last_find_query_match_type, .exact); try self.find_in_buffer(last, self.last_find_query_match_type);
} }
} }
try self.move_cursor_next_match(ctx); try self.move_cursor_next_match(ctx);
@ -5544,7 +5540,7 @@ pub const Editor = struct {
if (self.matches.items.len == 0) { if (self.matches.items.len == 0) {
if (self.last_find_query) |last| { if (self.last_find_query) |last| {
self.find_operation = .goto_prev_match; self.find_operation = .goto_prev_match;
try self.find_in_buffer(last, self.last_find_query_match_type, .exact); try self.find_in_buffer(last, self.last_find_query_match_type);
} }
} }
try self.move_cursor_prev_match(ctx); try self.move_cursor_prev_match(ctx);

View file

@ -1,11 +1,9 @@
const tp = @import("thespian"); const tp = @import("thespian");
const cbor = @import("cbor");
const input = @import("input"); const input = @import("input");
const keybind = @import("keybind"); const keybind = @import("keybind");
const command = @import("command"); const command = @import("command");
const EventHandler = @import("EventHandler"); const EventHandler = @import("EventHandler");
const Buffer = @import("Buffer");
const tui = @import("../../tui.zig"); const tui = @import("../../tui.zig");
const ed = @import("../../editor.zig"); const ed = @import("../../editor.zig");
@ -16,17 +14,11 @@ const ArrayList = @import("std").ArrayList;
const Self = @This(); const Self = @This();
const name = "󱎸 find"; const name = "󱎸 find";
const name_auto = name;
const name_exact = name ++ "";
const name_case_folded = name ++ "";
const Commands = command.Collection(cmds); const Commands = command.Collection(cmds);
const Mode = enum { auto, exact, case_folded };
allocator: Allocator, allocator: Allocator,
input_: ArrayList(u8), input_: ArrayList(u8),
find_mode: Mode = .auto,
last_input: ArrayList(u8), last_input: ArrayList(u8),
start_view: ed.View, start_view: ed.View,
start_cursor: ed.Cursor, start_cursor: ed.Cursor,
@ -34,7 +26,7 @@ editor: *ed.Editor,
history_pos: ?usize = null, history_pos: ?usize = null,
commands: Commands = undefined, commands: Commands = undefined,
pub fn create(allocator: Allocator, ctx: command.Context) !struct { tui.Mode, tui.MiniMode } { pub fn create(allocator: Allocator, _: command.Context) !struct { tui.Mode, tui.MiniMode } {
const editor = tui.get_active_editor() orelse return error.NotFound; const editor = tui.get_active_editor() orelse return error.NotFound;
const self = try allocator.create(Self); const self = try allocator.create(Self);
errdefer allocator.destroy(self); errdefer allocator.destroy(self);
@ -47,11 +39,7 @@ pub fn create(allocator: Allocator, ctx: command.Context) !struct { tui.Mode, tu
.editor = editor, .editor = editor,
}; };
try self.commands.init(self); try self.commands.init(self);
_ = ctx.args.match(.{cbor.extract(&self.find_mode)}) catch {}; if (editor.get_primary().selection) |sel| ret: {
var query: []const u8 = undefined;
if (ctx.args.match(.{ cbor.extract(&self.find_mode), cbor.extract(&query) }) catch false) {
try self.input_.appendSlice(self.allocator, query);
} else if (editor.get_primary().selection) |sel| ret: {
const text = editor.get_selection(sel, self.allocator) catch break :ret; const text = editor.get_selection(sel, self.allocator) catch break :ret;
defer self.allocator.free(text); defer self.allocator.free(text);
try self.input_.appendSlice(self.allocator, text); try self.input_.appendSlice(self.allocator, text);
@ -60,11 +48,7 @@ pub fn create(allocator: Allocator, ctx: command.Context) !struct { tui.Mode, tu
.insert_command = "mini_mode_insert_bytes", .insert_command = "mini_mode_insert_bytes",
}); });
mode.event_handler = EventHandler.to_owned(self); mode.event_handler = EventHandler.to_owned(self);
return .{ mode, .{ .name = switch (self.find_mode) { return .{ mode, .{ .name = name } };
.auto => name_auto,
.exact => name_exact,
.case_folded => name_case_folded,
} } };
} }
pub fn deinit(self: *Self) void { pub fn deinit(self: *Self) void {
@ -107,21 +91,13 @@ fn flush_input(self: *Self) !void {
const primary = self.editor.get_primary(); const primary = self.editor.get_primary();
primary.selection = null; primary.selection = null;
primary.cursor = self.start_cursor; primary.cursor = self.start_cursor;
try self.editor.find_in_buffer(self.input_.items, .find, switch (self.find_mode) { try self.editor.find_in_buffer(self.input_.items, .find);
.auto => self.auto_detect_mode(),
.exact => .exact,
.case_folded => .case_folded,
});
} else { } else {
self.editor.get_primary().selection = null; self.editor.get_primary().selection = null;
self.editor.init_matches_update(); self.editor.init_matches_update();
} }
} }
fn auto_detect_mode(self: *Self) Buffer.FindMode {
return if (Buffer.unicode.is_lowercase(self.input_.items) catch return .exact) .case_folded else .exact;
}
fn cmd(self: *Self, name_: []const u8, ctx: command.Context) tp.result { fn cmd(self: *Self, name_: []const u8, ctx: command.Context) tp.result {
self.flush_input() catch {}; self.flush_input() catch {};
return command.executeName(name_, ctx); return command.executeName(name_, ctx);
@ -177,19 +153,6 @@ const cmds = struct {
const Meta = command.Metadata; const Meta = command.Metadata;
const Result = command.Result; const Result = command.Result;
pub fn toggle_find_mode(self: *Self, _: Ctx) Result {
const new_find_mode: Buffer.FindMode = switch (self.find_mode) {
.exact => .case_folded,
.auto, .case_folded => .exact,
};
const allocator = self.allocator;
const query = try allocator.dupe(u8, self.input_.items);
defer allocator.free(query);
self.cancel();
command.executeName("find", command.fmt(.{ new_find_mode, query })) catch {};
}
pub const toggle_find_mode_meta: Meta = .{ .description = "Toggle find mode" };
pub fn mini_mode_reset(self: *Self, _: Ctx) Result { pub fn mini_mode_reset(self: *Self, _: Ctx) Result {
self.input_.clearRetainingCapacity(); self.input_.clearRetainingCapacity();
self.update_mini_mode_text(); self.update_mini_mode_text();