Autocomplete popular package names (thanks @evanwashere)

This commit is contained in:
Jarred Sumner
2021-12-19 23:30:25 -08:00
parent be03fc273a
commit a0551a9b8b
5 changed files with 10196 additions and 6 deletions

View File

@@ -16,6 +16,18 @@ function __fish__get_bun_scripts
string trim (string split '\n' (string split '\t' (bun getcompletes z))) string trim (string split '\n' (string split '\t' (bun getcompletes z)))
end end
function __fish__get_bun_packages
if test (commandline -ct) != ""
set -lx SHELL fish
string split ' ' (bun getcompletes a (commandline -ct))
end
end
function __history_completions
set -l tokens (commandline --current-process --tokenize)
history --prefix (commandline) | string replace -r \^$tokens[1]\\s\* "" | string replace -r \^$tokens[2]\\s\* "" | string split ' '
end
function __fish__get_bun_bun_js_files function __fish__get_bun_bun_js_files
string split ' ' (bun getcompletes j) string split ' ' (bun getcompletes j)
end end
@@ -129,9 +141,9 @@ complete -c bun \
-n "not __fish_seen_subcommand_from $bun_builtin_cmds_without_pm; and not __fish_seen_subcommand_from (__fish__get_bun_bins) (__fish__get_bun_scripts); and __fish_seen_subcommand_from install add remove;" -l 'cache-dir' -d 'Choose a cache directory (default: $HOME/.bun/install/cache)' -n "not __fish_seen_subcommand_from $bun_builtin_cmds_without_pm; and not __fish_seen_subcommand_from (__fish__get_bun_bins) (__fish__get_bun_scripts); and __fish_seen_subcommand_from install add remove;" -l 'cache-dir' -d 'Choose a cache directory (default: $HOME/.bun/install/cache)'
complete -c bun \ complete -c bun \
-n "not __fish_seen_subcommand_from $bun_builtin_cmds_without_pm; and not __fish_seen_subcommand_from (__fish__get_bun_bins) (__fish__get_bun_scripts); and __fish_seen_subcommand_from add remove;" -d "Add a folder to package.json" -n "not __fish_seen_subcommand_from $bun_builtin_cmds_without_pm; and not __fish_seen_subcommand_from (__fish__get_bun_bins) (__fish__get_bun_scripts); and __fish_seen_subcommand_from add;" -d 'Popular' -a '(__fish__get_bun_packages)'
complete -c bun \ complete -c bun \
-n "not __fish_seen_subcommand_from $bun_builtin_cmds_without_pm; and not __fish_seen_subcommand_from (__fish__get_bun_bins) (__fish__get_bun_scripts); and __fish_seen_subcommand_from add;" -F -n "not __fish_seen_subcommand_from $bun_builtin_cmds_without_pm; and not __fish_seen_subcommand_from (__fish__get_bun_bins) (__fish__get_bun_scripts); and __fish_seen_subcommand_from add;" -d 'History' -a '(__history_completions)'
complete -c bun --no-files complete -c bun --no-files

View File

@@ -55,8 +55,9 @@ _bun() {
ret=0 ret=0
case $state in case $state in
package) ;; package)
_bun_add_param_package_completion
;;
esac esac
;; ;;
@@ -497,6 +498,39 @@ _bun_run_param_script_completion() {
fi fi
} }
_set_remove() {
comm -23 <(echo $1 | sort | tr " " "\n") <(echo $2 | sort | tr " " "\n") 2>/dev/null
}
_bun_add_param_package_completion() {
IFS=$'\n' inexact=($(history -n bun | grep -E "^bun add " | cut -c 9- | uniq))
IFS=$'\n' exact=($($inexact | grep -E "^$words[$CURRENT]"))
IFS=$'\n' packages=($(SHELL=zsh bun getcompletes a $words[$CURRENT]))
to_print=$inexact
if [ ! -z "$exact" -a "$exact" != " " ]; then
to_print=$exact
fi
if [ ! -z "$to_print" -a "$to_print" != " " ]; then
if [ ! -z "$packages" -a "$packages" != " " ]; then
_describe -1 -t to_print 'History' to_print
_describe -1 -t packages "Popular" packages
return
fi
_describe -1 -t to_print 'History' to_print
return
fi
if [ ! -z "$packages" -a "$packages" != " " ]; then
_describe -1 -t packages "Popular" packages
return
fi
}
__bun_dynamic_comp() { __bun_dynamic_comp() {
local comp="" local comp=""

View File

@@ -536,6 +536,8 @@ pub const HelpCommand = struct {
} }
}; };
const AddCompletions = @import("./cli/add_completions.zig");
pub const PrintBundleCommand = struct { pub const PrintBundleCommand = struct {
pub fn exec(ctx: Command.Context) !void { pub fn exec(ctx: Command.Context) !void {
const entry_point = ctx.args.entry_points[0]; const entry_point = ctx.args.entry_points[0];
@@ -723,7 +725,7 @@ pub const Command = struct {
break; break;
} }
} }
var prefilled_completions: [AddCompletions.biggest_list]string = undefined;
var completions = ShellCompletions{}; var completions = ShellCompletions{};
if (filter.len == 0) { if (filter.len == 0) {
@@ -742,8 +744,54 @@ pub const Command = struct {
completions = try RunCommand.completions(ctx, null, &reject_list, .bun_js); completions = try RunCommand.completions(ctx, null, &reject_list, .bun_js);
} else if (strings.eqlComptime(filter[0], "z")) { } else if (strings.eqlComptime(filter[0], "z")) {
completions = try RunCommand.completions(ctx, null, &reject_list, .script_and_descriptions); completions = try RunCommand.completions(ctx, null, &reject_list, .script_and_descriptions);
} } else if (strings.eqlComptime(filter[0], "a")) {
const FirstLetter = AddCompletions.FirstLetter;
const index = AddCompletions.index;
outer: {
if (filter.len > 1) {
const first_letter: FirstLetter = switch (filter[1][0]) {
'a' => FirstLetter.a,
'b' => FirstLetter.b,
'c' => FirstLetter.c,
'd' => FirstLetter.d,
'e' => FirstLetter.e,
'f' => FirstLetter.f,
'g' => FirstLetter.g,
'h' => FirstLetter.h,
'i' => FirstLetter.i,
'j' => FirstLetter.j,
'k' => FirstLetter.k,
'l' => FirstLetter.l,
'm' => FirstLetter.m,
'n' => FirstLetter.n,
'o' => FirstLetter.o,
'p' => FirstLetter.p,
'q' => FirstLetter.q,
'r' => FirstLetter.r,
's' => FirstLetter.s,
't' => FirstLetter.t,
'u' => FirstLetter.u,
'v' => FirstLetter.v,
'w' => FirstLetter.w,
'x' => FirstLetter.x,
'y' => FirstLetter.y,
'z' => FirstLetter.z,
else => break :outer,
};
const results = index.get(first_letter);
var prefilled_i: usize = 0;
for (results) |cur| {
if (cur.len == 0 or !strings.hasPrefix(cur, filter[1])) continue;
prefilled_completions[prefilled_i] = cur;
prefilled_i += 1;
if (prefilled_i >= prefilled_completions.len) break;
}
completions.commands = prefilled_completions[0..prefilled_i];
}
}
}
completions.print(); completions.print();
return; return;

9997
src/cli/add_completions.txt Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,99 @@
pub const add_completions: []const u8 = @embedFile("add_completions.txt");
const std = @import("std");
pub const FirstLetter = enum(u8) {
a = 'a',
b = 'b',
c = 'c',
d = 'd',
e = 'e',
f = 'f',
g = 'g',
h = 'h',
i = 'i',
j = 'j',
k = 'k',
l = 'l',
m = 'm',
n = 'n',
o = 'o',
p = 'p',
q = 'q',
r = 'r',
s = 's',
t = 't',
u = 'u',
v = 'v',
w = 'w',
x = 'x',
y = 'y',
z = 'z',
};
pub const Index = std.EnumArray(FirstLetter, []const []const u8);
pub const index: Index = brk: {
var array: Index = Index.initFill(&[_][]const u8{});
var i: u8 = 'a';
var tokenizer = std.mem.tokenize(u8, add_completions, "\n");
var last_index: usize = 0;
var last_len: usize = 0;
while (i <= 'z') {
var init_tokenizer = tokenizer;
var count: usize = 0;
@setEvalBranchQuota(9999999);
while (init_tokenizer.next()) |pkg| {
if (pkg.len == 0) continue;
if (pkg[0] == i) {
count += 1;
} else {
break;
}
}
var record: [count][]const u8 = undefined;
var record_i: usize = 0;
var next_i = i + 1;
while (tokenizer.next()) |pkg| {
if (pkg.len == 0) continue;
if (pkg[0] == i) {
record[record_i] = pkg;
record_i += 1;
} else {
next_i = pkg[0];
break;
}
}
array.set(@intToEnum(FirstLetter, i), &record);
@setEvalBranchQuota(999999);
i = next_i;
}
break :brk array;
};
pub const biggest_list: usize = brk: {
var a = index;
var iter = a.iterator();
var max: usize = 0;
while (iter.next()) |list| {
max = @maximum(list.value.len, max);
}
break :brk max;
};
const index_blob = "add_completions.index.blob";
test "entries" {
const items = index.get(FirstLetter.r);
var found_react = false;
for (items) |item| {
try std.testing.expectEqual(item[0], 'r');
if (std.mem.eql(u8, item, "react")) {
found_react = true;
}
}
try std.testing.expect(found_react);
}