mirror of
https://github.com/oven-sh/bun
synced 2026-02-02 15:08:46 +00:00
Autocomplete popular package names (thanks @evanwashere)
This commit is contained in:
@@ -16,6 +16,18 @@ function __fish__get_bun_scripts
|
||||
string trim (string split '\n' (string split '\t' (bun getcompletes z)))
|
||||
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
|
||||
string split ' ' (bun getcompletes j)
|
||||
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)'
|
||||
|
||||
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 \
|
||||
-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
|
||||
@@ -55,8 +55,9 @@ _bun() {
|
||||
ret=0
|
||||
|
||||
case $state in
|
||||
package) ;;
|
||||
|
||||
package)
|
||||
_bun_add_param_package_completion
|
||||
;;
|
||||
esac
|
||||
|
||||
;;
|
||||
@@ -497,6 +498,39 @@ _bun_run_param_script_completion() {
|
||||
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() {
|
||||
local comp=""
|
||||
|
||||
|
||||
52
src/cli.zig
52
src/cli.zig
@@ -536,6 +536,8 @@ pub const HelpCommand = struct {
|
||||
}
|
||||
};
|
||||
|
||||
const AddCompletions = @import("./cli/add_completions.zig");
|
||||
|
||||
pub const PrintBundleCommand = struct {
|
||||
pub fn exec(ctx: Command.Context) !void {
|
||||
const entry_point = ctx.args.entry_points[0];
|
||||
@@ -723,7 +725,7 @@ pub const Command = struct {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var prefilled_completions: [AddCompletions.biggest_list]string = undefined;
|
||||
var completions = ShellCompletions{};
|
||||
|
||||
if (filter.len == 0) {
|
||||
@@ -742,8 +744,54 @@ pub const Command = struct {
|
||||
completions = try RunCommand.completions(ctx, null, &reject_list, .bun_js);
|
||||
} else if (strings.eqlComptime(filter[0], "z")) {
|
||||
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();
|
||||
|
||||
return;
|
||||
|
||||
9997
src/cli/add_completions.txt
Normal file
9997
src/cli/add_completions.txt
Normal file
File diff suppressed because it is too large
Load Diff
99
src/cli/add_completions.zig
Normal file
99
src/cli/add_completions.zig
Normal 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);
|
||||
}
|
||||
Reference in New Issue
Block a user