Skip to content

Commit acc25ed

Browse files
authored
Merge pull request #95 from DannyBen/add/menu-command
Add interactive `rush menu` command for viewing and installing with fzf
2 parents 15ec9cd + c50cd77 commit acc25ed

14 files changed

Lines changed: 469 additions & 30 deletions

File tree

doc/rush-menu.1

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
.\" Automatically generated by Pandoc 3.9
2+
.\"
3+
.TH "rush\-menu" "1" "July 2026" "" "Select a package from an interactive menu."
4+
.SH NAME
5+
\f[B]rush menu\f[R] \- Select a package from an interactive menu.
6+
.SH SYNOPSIS
7+
\f[B]rush menu\f[R] REPO_OR_PACKAGE OPTIONS
8+
.SH DESCRIPTION
9+
Select a package from an interactive menu.
10+
.SH ARGUMENTS
11+
.SS REPO_OR_PACKAGE
12+
Repository name or package name.
13+
.PP
14+
Leave blank to show all packages in all repositories.
15+
.PP
16+
Provide a repository name to show only packages in this repository.
17+
.PP
18+
Provide a package name (may be in the form of \f[B]repo:package\f[R]) to
19+
show nested packages.
20+
.SH OPTIONS
21+
.SS \-\-install, \-i
22+
Install the selected package instead of showing its info.
23+
.SH DEPENDENCIES
24+
.SS fzf
25+
.SH EXAMPLES
26+
.IP
27+
.EX
28+
rush menu
29+
30+
rush menu \-\-install
31+
32+
rush menu personal
33+
.EE
34+
.SH SEE ALSO
35+
\f[B]rush\f[R](1)

doc/rush-menu.md

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
% rush-menu(1) | Select a package from an interactive menu.
2+
%
3+
% July 2026
4+
5+
NAME
6+
==================================================
7+
8+
**rush menu** - Select a package from an interactive menu.
9+
10+
SYNOPSIS
11+
==================================================
12+
13+
**rush menu** [REPO_OR_PACKAGE] [OPTIONS]
14+
15+
DESCRIPTION
16+
==================================================
17+
18+
Select a package from an interactive menu.
19+
20+
21+
ARGUMENTS
22+
==================================================
23+
24+
REPO_OR_PACKAGE
25+
--------------------------------------------------
26+
27+
Repository name or package name.
28+
29+
Leave blank to show all packages in all repositories.
30+
31+
Provide a repository name to show only packages in this repository.
32+
33+
Provide a package name (may be in the form of **repo:package**) to show nested packages.
34+
35+
36+
OPTIONS
37+
==================================================
38+
39+
--install, -i
40+
--------------------------------------------------
41+
42+
Install the selected package instead of showing its info.
43+
44+
45+
DEPENDENCIES
46+
==================================================
47+
48+
fzf
49+
--------------------------------------------------
50+
51+
52+
EXAMPLES
53+
==================================================
54+
55+
~~~
56+
rush menu
57+
58+
rush menu --install
59+
60+
rush menu personal
61+
62+
~~~
63+
64+
SEE ALSO
65+
==================================================
66+
67+
**rush**(1)
68+
69+

doc/rush.1

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ Copy a package between local repositories.
3737
Show information about a package.
3838
.SS rush list
3939
Show packages in one or all repositories.
40+
.SS rush menu
41+
Select a package from an interactive menu.
4042
.SS rush search
4143
Search in package names and info files.
4244
.SS rush edit
@@ -62,9 +64,9 @@ Default: \(ti/rush\-repos
6264
\f[B]rush\-default\f[R](1), \f[B]rush\-get\f[R](1),
6365
\f[B]rush\-undo\f[R](1), \f[B]rush\-snatch\f[R](1),
6466
\f[B]rush\-copy\f[R](1), \f[B]rush\-info\f[R](1),
65-
\f[B]rush\-list\f[R](1), \f[B]rush\-search\f[R](1),
66-
\f[B]rush\-edit\f[R](1), \f[B]rush\-show\f[R](1),
67-
\f[B]rush\-completions\f[R](1)
67+
\f[B]rush\-list\f[R](1), \f[B]rush\-menu\f[R](1),
68+
\f[B]rush\-search\f[R](1), \f[B]rush\-edit\f[R](1),
69+
\f[B]rush\-show\f[R](1), \f[B]rush\-completions\f[R](1)
6870
.SH SOURCE CODE
6971
https://github.com/dannyben/rush
7072
.SH ISSUE TRACKER

doc/rush.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,11 @@ rush list
9898

9999
Show packages in one or all repositories.
100100

101+
rush menu
102+
--------------------------------------------------
103+
104+
Select a package from an interactive menu.
105+
101106
rush search
102107
--------------------------------------------------
103108

@@ -145,7 +150,7 @@ Default: ~/rush-repos
145150
SEE ALSO
146151
==================================================
147152

148-
**rush-add**(1), **rush-remove**(1), **rush-clone**(1), **rush-pull**(1), **rush-push**(1), **rush-config**(1), **rush-default**(1), **rush-get**(1), **rush-undo**(1), **rush-snatch**(1), **rush-copy**(1), **rush-info**(1), **rush-list**(1), **rush-search**(1), **rush-edit**(1), **rush-show**(1), **rush-completions**(1)
153+
**rush-add**(1), **rush-remove**(1), **rush-clone**(1), **rush-pull**(1), **rush-push**(1), **rush-config**(1), **rush-default**(1), **rush-get**(1), **rush-undo**(1), **rush-snatch**(1), **rush-copy**(1), **rush-info**(1), **rush-list**(1), **rush-menu**(1), **rush-search**(1), **rush-edit**(1), **rush-show**(1), **rush-completions**(1)
149154

150155
# SOURCE CODE
151156

features/fixtures/bin/fzf

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#!/usr/bin/env bash
2+
selection=${STUB_FZF_SELECTION:-hello}
3+
input=$(cat)
4+
5+
if [[ ${STUB_FZF_INPUT-} ]]; then
6+
printf "%s\n" "$input" >"$STUB_FZF_INPUT"
7+
fi
8+
9+
while IFS= read -r line; do
10+
package=${line%%[[:space:]]*}
11+
12+
if [[ $package == "$selection" ]]; then
13+
printf "%s\n" "$line"
14+
exit 0
15+
fi
16+
done <<<"$input"
17+
18+
exit 1

features/list.feature

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ Scenario: Show package names only
2424
bootstrap
2525
download
2626
hello
27-
nested
2827
"""
2928

3029
Scenario: Show nested packages for a package name

features/menu.feature

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
Feature: menu
2+
Show packages in one or all repositories using fzf interactive menu
3+
4+
Scenario: Show --help
5+
When I run 'rush menu --help'
6+
Then the exit code should mean success
7+
And stdout should include 'Select a package from an interactive menu'
8+
And stdout should include '--install, -i'
9+
10+
Scenario: Show packages in the default repository
11+
Given rush is properly configured
12+
And the command 'fzf' is stubbed
13+
And my fzf selection will be 'hello'
14+
When I run 'rush menu'
15+
Then the fzf menu should show
16+
"""
17+
▌ package-in-package/two Package two
18+
▌ package-in-package/one Package one
19+
▌ nested/hi Shows how to use nested folders
20+
▌ hello This is a simple example.
21+
▌ download Shows how a script can copy files from its own folder
22+
▌ bootstrap Shows how to run another command from the same reposi·
23+
"""
24+
And the exit code should mean success
25+
And stdout should include 'This info file can be accessed by running'
26+
27+
Scenario: Show packages in the a nested package
28+
Given rush is properly configured
29+
And the command 'fzf' is stubbed
30+
And my fzf selection will be 'nested/hi'
31+
When I run 'rush menu nested'
32+
Then the fzf menu should show
33+
"""
34+
▌ nested/hi Shows how to use nested folders
35+
"""
36+
Then the exit code should mean success
37+
And stdout should include '$ rush info nested/hi'
38+
39+
Scenario: Install package
40+
Given rush is properly configured
41+
And the command 'fzf' is stubbed
42+
And my fzf selection will be 'hello'
43+
When I run 'rush menu --install'
44+
Then the exit code should mean success
45+
And stdout should include 'What's the rush'
46+
And stdout should include 'REPO: default'
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,15 @@
11
@Given the command '{command}' is stubbed
22
install_stubbed_command "$command"
3+
4+
@Given my fzf selection will be '{selection}'
5+
export STUB_FZF_INPUT="$TMPDIR/fzf-input"
6+
export STUB_FZF_SELECTION="$selection"
7+
defer unset STUB_FZF_INPUT
8+
defer unset STUB_FZF_SELECTION
9+
10+
@Then the fzf menu should show
11+
[[ -f "$STUB_FZF_INPUT" ]] || fail "fzf input was not captured"
12+
13+
actual=$(fzf_menu_display "$STUB_FZF_INPUT")
14+
15+
[[ "$actual" == "$DOC_STRING" ]] || fail "expected fzf menu to show:\n$DOC_STRING\n\ngot:\n$actual"

features/support.sh

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,17 @@ stub_fixture_root() {
1919
printf '%s\n' "$SUPPORT_PROJECT_ROOT/features/fixtures/bin"
2020
}
2121

22+
fzf_menu_display() {
23+
tac "$1" |
24+
while IFS= read -r line; do
25+
if ((${#line} > 75)); then
26+
line="${line:0:75}·"
27+
fi
28+
29+
printf "▌ %s\n" "$line"
30+
done
31+
}
32+
2233
prepare_isolated_environment() {
2334
local old_pwd="$PWD"
2435
local old_home="${HOME-}"
@@ -75,7 +86,11 @@ install_stubbed_command() {
7586
stub_root=$(mktemp -d)
7687
stub_path="$stub_root/$command"
7788

78-
[[ -f "$fixture_root/$command" ]] || fail "missing stub fixture: $fixture_root/$command"
89+
if [[ ! -f "$fixture_root/$command" ]]; then
90+
fail "missing stub fixture: $fixture_root/$command"
91+
return
92+
fi
93+
7994
cp "$fixture_root/$command" "$stub_path"
8095
chmod +x "$stub_path"
8196
export PATH="$stub_root:$PATH"

0 commit comments

Comments
 (0)