On Thu Jun 16, 2022 at 9:46 PM CEST, Hugo Machet wrote:
> + '\t' => {> + var current = try util.codepointSliceToUtf8SlizeZAlloc(context.gpa,> buffer.buffer.items);> + defer context.gpa.free(current);> +> + var it = mem.tokenize(u8, current, " ");> + var buf: []const u8 = undefined;> + while (it.next()) |tok| buf = tok;> +> + if (buf.len < 2) return;> + var comp = try completion(buf);> + if (mem.eql(u8, comp, buf)) return;> + try buffer.insertFormat(comp);> + },
I think it might be better to first tokenize and then allocate an
utf8 slice containing only the word we are interested in.
Not sure if mem.tokenize() will play along, but since we are only
looking for whitespace, this could be done by hand anyway. Just start
at the cursor position and iterate backwards until you find whitespace
(careful to ignore whitespace directly at the curosr).
> +/// Compare current input with files/directories names. Complete the> name if> +/// there is only one match else only complete the common part.> +/// Case insensitive.> +fn completion(input: []const u8) ![]const u8 {> + var found: std.ArrayListUnmanaged([:0]const u8) = .{};> + defer found.deinit(context.gpa);> +> + for (context.dirmap.cwd.files.items) |file| {> + if (!context.show_hidden and file.isHidden()) continue;
I think we came to the conclusion to not skip hidden files, so this
check should be removed (otherwise you could just use DirMap.visible_files).
Also maybe a list of *File pointers might be better than duping all
similar names we find.
> + if (found.items.len == 0) {> + return input;> + } else if (found.items.len == 1) {> + return found.items[0][input.len..];> + } else {> + var common: []const u8 = found.items[0];> + var i: usize = 1;> + while (i < found.items.len) : (i += 1) {> + common = commonStart(common, found.items[i]);> + }> + return common[input.len..];> + }> +}
I think it might be nicer if this function did not return the entire
string, but only the completion bit. So it "pro" gets completed to
"projects", only "jects" should be returned. If no completion is found
return null. That way, callsite can manage the function a bit nicer
I think, as you'd only have to do something like this:
if (complete(token)) |compl| {
input_buffer.insert(compl);
}
> +> +/// Compare two strings and return the common beginning part.> +/// Case insensitive.> +fn commonStart(a: []const u8, b: []const u8) []const u8 {> + const len: usize = if (a.len < b.len) a.len else b.len;> +> + var offset: usize = 0;> + while (offset < len) : (offset += 1) {> + if (ascii.toLower(a[offset]) != ascii.toLower(b[offset])) break;> + }> +> + return a[0..offset];> +}> +
Neat!
BTW, I think there'll be a problem with file names containing spaces.
Either we should insert quotes, or automatically escape them.
Friendly greetings,
Leon Henrik Plickat