Skip to content

Commit 8b14901

Browse files
committed
decategorize
1 parent be7ade3 commit 8b14901

File tree

17 files changed

+87
-494
lines changed

17 files changed

+87
-494
lines changed

.github/scripts/build.ts

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,33 +17,19 @@ if (!indir || !outdir || !index_json_path) {
1717

1818
const scripts = JSON.parse(Deno.readTextFileSync(index_json_path)).scripts as Script[]
1919

20-
const categories: Record<string, Script[]> = {}
2120
const users: Record<string, Script[]> = {}
2221

2322
for (const script of scripts) {
24-
if (script.category) {
25-
categories[script.category] ??= []
26-
categories[script.category].push(script)
27-
}
2823
const user = script.fullname.split('/')[0]
2924
users[user] ??= []
3025
users[user].push(script)
3126
}
3227

3328
// sort each entry in categories and users by the script birthtime
34-
for (const scripts of Object.values(categories)) {
35-
scripts.sort((a, b) => new Date(b.birthtime).getTime() - new Date(a.birthtime).getTime());
36-
}
3729
for (const scripts of Object.values(users)) {
3830
scripts.sort((a, b) => new Date(b.birthtime).getTime() - new Date(a.birthtime).getTime());
3931
}
4032

41-
for (const category in categories) {
42-
const d = outdir.join(category)
43-
const scripts = categories[category].filter(({description}) => description)
44-
d.mkdir('p').join('index.json').write({ json: { scripts }, force: true, space: 2 })
45-
}
46-
4733
for (const user in users) {
4834
const d = outdir.join('u', user)
4935
const scripts = users[user].filter(({description}) => description)
@@ -53,15 +39,13 @@ for (const user in users) {
5339
for (const script of scripts) {
5440
console.error(script)
5541
const [user, name] = script.fullname.split('/')
56-
const { category } = script
5742
const gh_slug = new URL(script.url).pathname.split('/').slice(1, 3).join('/')
5843
const infile = indir.join(gh_slug, 'scripts', basename(script.url))
5944

6045
infile.cp({ to: outdir.join('u', user).mkdir('p').join(name) })
6146

62-
const leaf = name.split('-').slice(1).join('-')
63-
if (category && !outdir.join(category, leaf).exists()) { // not already snagged
64-
infile.cp({ to: outdir.join(category, leaf) })
47+
if (!outdir.join(name).exists() && user != "pkgxdev") { // not already snagged
48+
infile.cp({ to: outdir.join(name) })
6549
}
6650
}
6751

.github/scripts/index.ts

Lines changed: 40 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -18,24 +18,38 @@ if (import.meta.main) {
1818
const scripts: Script[] = []
1919
for await (const slug of iterateGitRepos('.')) {
2020
console.error(`iterating: ${slug}`);
21-
scripts.push(...await get_metadata(slug));
22-
}
23-
24-
scripts.sort((a, b) => b.birthtime.getTime() - a.birthtime.getTime());
25-
26-
const categories = (() => {
27-
const categories: Record<string, number> = {}
28-
for (const script of scripts) {
29-
if (script.category && script.description) {
30-
categories[script.category] ??= 0;
31-
categories[script.category]++;
21+
for (const script of await get_metadata(slug)) {
22+
switch (basename(script.fullname)) {
23+
case "cache":
24+
case "demo-test-pattern":
25+
case "ensure":
26+
case "inventory":
27+
case "pantry-inventory":
28+
case "ls":
29+
case "magic":
30+
case "prune":
31+
case "run":
32+
case "stub":
33+
case "upgrade":
34+
case "cache+prune":
35+
case "cache+ls":
36+
case "cache+upgrade":
37+
case "demo":
38+
if (!script.fullname.startsWith("mxcl/")) {
39+
// ignore stuff that was forked from when the root repo had scripts
40+
// these scripts are now on @mxcl/…
41+
continue;
42+
}
43+
// fallthrough
44+
default:
45+
scripts.push(script)
3246
}
3347
}
34-
return Object.keys(categories)
35-
})();
48+
}
3649

50+
scripts.sort((a, b) => b.birthtime.getTime() - a.birthtime.getTime());
3751

38-
console.log(JSON.stringify({ scripts, categories }, null, 2));
52+
console.log(JSON.stringify({ scripts }, null, 2));
3953
}
4054

4155
////////////////////////////////////////////////////////////////////// lib
@@ -45,13 +59,16 @@ async function extractMarkdownSection(filePath: string, sectionTitle: string): P
4559
let capturing = false;
4660
let sectionContent = '';
4761

48-
for (const line of lines) {
49-
if (line.startsWith('## ')) {
62+
for (let line of lines) {
63+
line = line.trim();
64+
if (/^##\s+/.test(line)) {
5065
if (capturing) {
51-
break; // stop if we reach another ## section
52-
} else if (normalize_title(line.slice(3)) == normalize_title(sectionTitle)) {
66+
break; // stop if we reach another header section
67+
} else if (normalize_title(line.replace(/^#+/, '')) == normalize_title(sectionTitle)) {
68+
capturing = true;
69+
} else if (line.replace(/^#+/, '').trim() == mash_title(sectionTitle)) {
5370
capturing = true;
54-
} else if (line.slice(3).trim() == mash_title(sectionTitle)) {
71+
} else if (line.replace(/^#+/, '').trim() == `\`mash ${sectionTitle}\``) {
5572
capturing = true;
5673
}
5774
} else if (capturing) {
@@ -77,7 +94,6 @@ export interface Script {
7794
description?: string
7895
avatar: string
7996
url: string
80-
category?: string
8197
README?: string
8298
cmd: string
8399
}
@@ -123,6 +139,8 @@ async function get_metadata(slug: string) {
123139
// the file used to exist but has been deleted
124140
console.warn("skipping deleted: ", filename, line)
125141
continue
142+
} else {
143+
console.warn("%cadding: ", 'color:green', filename, line)
126144
}
127145

128146
const repo_metadata = JSON.parse(await Deno.readTextFile(join(slug, 'metadata.json')))
@@ -133,15 +151,14 @@ async function get_metadata(slug: string) {
133151
const avatar = repo_metadata.avatar
134152
const fullname = join(dirname(slug), _stem)
135153
const url = repo_metadata.url +'/scripts/' + basename(filename)
136-
const category = (([x, y]) => x?.length > 0 && y ? x : undefined)(basename(filename).split("-"))
137154
const description = README
138155
? extract_description(README)
139156
: fullname == 'pkgxdev/demo-test-pattern'
140157
? 'Prints a test pattern to your console'
141158
: undefined
142-
const cmd = category ? `mash ${category} ${_stem.split('-').slice(1).join('-')}` : `mash ${fullname}`
159+
const cmd = `mash ${_stem}`
143160

144-
rv.push({ fullname, birthtime, description, avatar, url, category, README, cmd })
161+
rv.push({ fullname, birthtime, description, avatar, url, README, cmd })
145162
}
146163
}
147164

.github/workflows/cd.www.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ jobs:
2424
runs-on: ubuntu-latest
2525
steps:
2626
- uses: actions/checkout@v4
27-
- uses: pkgxdev/setup@v3
27+
- uses: pkgxdev/setup@v4
2828

2929
- name: trawl
3030
run: .github/scripts/trawl.ts --out ./build

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ jobs:
1010
runs-on: ubuntu-latest
1111
steps:
1212
- uses: actions/checkout@v4
13-
- uses: pkgxdev/setup@v3
13+
- uses: pkgxdev/setup@v4
1414
- run: ./mash demo test-pattern
1515
- run: ./mash demo test-pattern # check cache route works too
1616
- run: ./mash pkgxdev/demo-test-pattern # check fully qualified

README.md

Lines changed: 16 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -17,39 +17,24 @@ mash up millions of open source packages into monstrously powerful scripts.
1717
## Quick Start
1818

1919
```sh
20-
brew install pkgxdev/made/mash || curl https://mash.pkgx.sh | sh
20+
brew install pkgxdev/made/mash || curl https://pkgx.sh | sh
2121
```
2222

2323
> [!NOTE]
2424
> `mash` is a plain POSIX script. All it needs is `bash`, `curl`, and `pkgx`.
25-
> So if you like you can just download it by itself.
25+
> So if you like install the deps and just download it by itself.
2626
2727
## Getting Started
2828

29-
```sh
30-
$ mash # or https://mash.pkgx.sh
31-
# ^^ lists all script categories
32-
```
33-
34-
You can browse script listings with the TUI or at [mash.pkgx.sh]:
35-
36-
```sh
37-
$ mash ai # or https://mash.pkgx.sh/ai/
38-
# ^^ lists all ai scripts
39-
```
40-
41-
> [!NOTE]
42-
> The above lists all user submitted scripts in the `ai` category.
43-
44-
Once you’ve found a script you want to run:
29+
Visit [mash.pkgx.sh] to see what scripts are available. Once you’ve found a
30+
script you want to run:
4531

4632
```sh
47-
$ mash ai chat --help # or https://mash.pkgx.sh/ai/chat/
33+
mash transcribe --help # or https://mash.pkgx.sh/mxcl/transcribe
4834
```
4935

5036
&nbsp;
5137

52-
5338
## Contributing Scripts
5439

5540
### Writing Scripts
@@ -68,24 +53,13 @@ Generally it is sensible to specify constrained versions:
6853

6954
### Naming Scripts
7055

71-
`mash` operates with a “categorization by default is good” philosophy. Your
72-
scripts must be categorized or namespaced with your user.
73-
74-
Thus if you add a script named `foo` it can only be used via
75-
`mash username/foo`. But if you add a script called `foo-bar` if will be
76-
listed if a user types `mash foo`:
77-
78-
```sh
79-
$ mash foo
80-
81-
mash foo bar # your description about `foo bar` is shown here
82-
mash foo other-script #
83-
```
56+
Names are first-come, first served. Please practice taste. We reserve the
57+
right to manage names.
8458

8559
> [!TIP]
8660
> Extensions (eg. `.sh`, `.ts`) are *recommended* for GitHub readability.
8761
> They will be stripped from the mash execution name, eg. `foo-bar.ts` is
88-
> invoked via `mash foo bar` and not `mash foo bar.ts`
62+
> invoked via `mash foo-bar` and not `mash foo-bar.ts`
8963
9064
### Installing Language Dependencies
9165

@@ -143,8 +117,8 @@ available.
143117
Assuming a script named `foo-bar`, while debugging just:
144118

145119
```sh
146-
$ chmod +x scripts/foo-bar
147-
$ ./scripts/foo-bar
120+
chmod +x scripts/foo-bar
121+
./scripts/foo-bar
148122
```
149123

150124
After pushing we will index your script within 60 minutes.
@@ -158,16 +132,6 @@ Once indexed your script can be run with:
158132
> If you can visit https://mash.pkgx.sh/USERNAME/SCRIPT-NAME then you’re
159133
> script has been indexed.
160134
161-
> [!NOTE]
162-
> * Categorized scripts occur on a first come first served basis. If you
163-
> create a script called `foo-bar` and someone already did that then you are
164-
> too late and users can only call your script with `mash youruser/foo-bar`.
165-
> * Updates are fetched automatically, there is no versioning at this time.
166-
> * Single letter categorizations are ignored, eg `./scripts/f-u` will not be
167-
> indexed or made available to mash. If you have a particularly good single
168-
> letter category that you want an exception made, open a discussion and
169-
> let’s chat!
170-
171135
> [!NOTE]
172136
> ### Naming Guidelines: A Call for Consideration
173137
> Think for a little about the names you are picking. We reserve the right
@@ -206,8 +170,8 @@ pkg names, just type what you would type to run the command.
206170
207171
### Documenting Your Script
208172

209-
Rewrite the README in your fork so there is a `## mash category scriptname`
210-
section. If your script is not globally categorized then you would do
173+
Rewrite the README in your fork so there is a `## mash scriptname`
174+
section. If your script is not the first to get a name then you would do
211175
`## mash username/scriptname` instead.
212176

213177
* The paragraph after the `##` will be the [mash.pkgx.sh] description
@@ -231,23 +195,23 @@ https://github.com/mxcl/mash
231195
directly via `pkgx`:
232196

233197
```sh
234-
$ curl -O https://raw.githubusercontent.com/mxcl/mash/main/scripts/gh-stargazer
235-
$ pkgx ./gh-stargazer
198+
curl -O https://raw.githubusercontent.com/mxcl/mash/main/scripts/transcribe
199+
pkgx ./transcribe
236200
```
237201

238202
Even `pkgx` isn’t required, they can source the dependencies themselves and
239203
run the script manually:
240204

241205
```sh
242-
$ bash ./stargazer
206+
$ bash ./transcribe
243207
# ^^ they will need to read the script to determine deps and interpreter
244208
```
245209

246210
Hackers can use your script without installing `pkgx` or `mash` first via our
247211
cURL one-liner. This executes the script but doesn’t install anything:
248212

249213
```sh
250-
sh <(curl https://mash.pkgx.sh) <category> <scriptname>
214+
sh <(curl https://mash.pkgx.sh) transcribe
251215
```
252216

253217

mash

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,15 @@ if [ "$1" == --version ]; then
77
exit 0
88
fi
99

10+
if [ -z "$1" -o "$1" == "--help" ]; then
11+
echo "mash <scriptname> [args...]" 1>&2
12+
if [ "$1" == "--help" ]; then
13+
exit 0
14+
else
15+
exit 1
16+
fi
17+
fi
18+
1019
if [ -n "$RUNNER_DEBUG" -a -n "$GITHUB_ACTIONS" ] || [ -n "$VERBOSE" ]; then
1120
set -x
1221
fi
@@ -66,24 +75,23 @@ run() {
6675
echo "error: $URL" 1>&2
6776
exit 2
6877
fi
69-
7078
}
7179

72-
if [ -z "$1" ]; then
73-
curl -Ssf https://pkgxdev.github.io/mash/ | pkgx --quiet jq '.categories[]' --raw-output | sort | uniq
74-
exit 0
75-
elif [[ "$1" == *"/"* ]]; then
76-
# fully quaified name not a category
77-
cmd=$1
78-
shift
79-
run u/$cmd "$@"
80-
elif [[ -z "$2" ]]; then
81-
curl -Ssf https://pkgxdev.github.io/mash/$1/ |
82-
pkgx --quiet jq -r '.scripts[] | [.cmd, .description] | @tsv' |
83-
awk 'BEGIN {FS="\t"; print "| Script | Description |"; print "|-|-|"} {printf("| %s | %s |\n", $1, $2)}' |
84-
pkgx --quiet gum format
85-
else
86-
cmd=$1/$2
87-
shift; shift
88-
run $cmd "$@"
89-
fi
80+
cmd=$1
81+
shift
82+
83+
case "$cmd-$1" in
84+
tea-erc20|media-yt2mp3|pantry-checker|tmux-sessionizer|demo-test-pattern)
85+
cmd="$cmd-$1"
86+
shift;;
87+
*)
88+
if [[ "$cmd" == pkgx/* || "$cmd" == pkgxdev/* ]]; then
89+
cmd="mxcl/$(basename $cmd)"
90+
fi
91+
92+
if [[ "$cmd" == */* ]]; then
93+
cmd="u/$cmd"
94+
fi
95+
esac
96+
97+
run $cmd "$@"

scripts/cache

Lines changed: 0 additions & 20 deletions
This file was deleted.

0 commit comments

Comments
 (0)