Implements: https://todo.sr.ht/~leon_plickat/nfm/17
---
src/nfm.zig | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 55 insertions(+)
diff --git a/src/nfm.zig b/src/nfm.zig
index d978210d4f9f..1414a5f81407 100644
--- a/src/nfm.zig
+++ b/src/nfm.zig
@@ -546,6 +546,19 @@ fn handleInputUserInput(in: spoon.Input) !void {
try handleReturnUserInput();
return;
},
+ '\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);
+ },
127 => { // Backspace.
if (context.mode.user_input.history_index != null) return;
buffer.delete(.left, 1);
@@ -653,6 +666,48 @@ fn handleReturnUserInput() !void {
}
}
+/// 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.cwd.files.items) |file| {
+ if (!context.show_hidden and file.isHidden()) continue;
+ if (file.name.len <= input.len) continue;
+ if (ascii.startsWithIgnoreCase(file.name, input)) {
+ try found.append(context.gpa, file.name);
+ }
+ }
+
+ 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..];
+ }
+}
+
+/// 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];
+}
+
test {
_ = @import("ini.zig");
_ = @import("CommandTokenizer.zig");
--
2.36.1