Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 21 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ $ cat package.json | jq .engines
"node": "^20"
}

$ dev
$ dev .
activated `~/my-project` (+node^20)

$ node --version && which node
Expand Down Expand Up @@ -72,6 +72,9 @@ Shellcode works _as well_ and is your preference. It has notable caveats with
regard to use in tools like editors. It also requires you to add shellcode to
your `shell.rc` files and thus is more intrusive (depending on your outlook).

A great advantage of the shellcode is not needing to install tools you may never
need again when exploring new open source projects.

```sh
pkgx dev integrate
```
Expand Down Expand Up @@ -103,7 +106,7 @@ more shells.
> If you like, preview the shellcode: `pkgx dev --shellcode`. This command only
> outputs shellcode, it doesn’t modify any files or do anything else either.

## Usage
### Usage

```sh
$ cd my-project
Expand All @@ -130,15 +133,20 @@ command not found: node

> [!TIP]
>
> ### Try Before You `vi`
> #### Try Before You `vi`
>
> Modifying your `shell.rc` can be… _intimidating_. If you just want to
> temporarily try `dev` out before you `:wq`—we got you:
>
> ```sh
> $ cd my-project
> $ eval "$(pkgx dev)"
> $ eval "$(pkgx dev .)"
> +deno^2
> $ deno --version
> deno 2.1.1
>
> $ dev off
> # ^^ or close your terminal
> ```
>
> The devenv will only exist for the duration of your shell session.
Expand Down Expand Up @@ -208,27 +216,25 @@ You can add your own environment variables if you like:

> [!NOTE]
>
> The environment variable's value is sanitized, so expressions like
> `MY_VAR: $(sudo rm -rf --no-preserve-root /)` will throw an error.
> - Adding environment variables only works via the `shellcode` route.
> - The environment variable's value is sanitized, so expressions like
> `MY_VAR: $(sudo rm -rf --no-preserve-root /)` will throw an error.
> - We recommend `direnv` instead of this route.

## `dev` & Editors

Most editors if opened via the Terminal will inherit that Terminal’s
environment. We recommend Visual Studio Code, `dev && code .` works great.

> [!WARNING]
>
> Unfortunately, this usually means you _must_ open your editor via your
> terminal.
The sure fire way for things to work in editors is to use the `dev`/`pkgm`
combo. Having said this most editors if opened via the Terminal will inherit
that Terminal’s environment.

## GitHub Actions

```yaml
- uses: pkgxdev/dev@v1
```

Installs needed packages (via `pkgx`) and sets up the environment the same as
`dev` does in your terminal.
Our action installs needed packages (via `pkgx`) and sets up the environment the
same as `dev` does in your terminal.

## Contributing

Expand Down
94 changes: 87 additions & 7 deletions app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@
//TODO if you step into dev-dir/subdir and type `dev` does it find the root properly?
//TODO dev off uses PWD which may not be correct if in subdir (obv)

import { Path } from "libpkgx";
import { Path, utils } from "libpkgx";
import shellcode, { datadir } from "./src/shellcode().ts";
import app_version from "./src/app-version.ts";
import integrate from "./src/integrate.ts";
import { parseArgs } from "jsr:@std/cli@^1/parse-args";
import dump from "./src/dump.ts";
import sniff from "./src/sniff.ts";
import { walk } from "jsr:@std/fs@1/walk";

const parsedArgs = parseArgs(Deno.args, {
alias: {
Expand All @@ -28,10 +29,13 @@ const parsedArgs = parseArgs(Deno.args, {
});

if (parsedArgs.help) {
const status = await new Deno.Command("pkgx", {
args: ["--quiet", "gh", "repo", "view", "pkgxdev/dev"],
const { code } = await new Deno.Command("pkgx", {
args: [
"glow",
"https://raw.githubusercontent.com/pkgxdev/dev/refs/heads/main/README.md",
],
}).spawn().status;
Deno.exit(status.code);
Deno.exit(code);
} else if (parsedArgs.shellcode) {
console.log(shellcode());
} else if (parsedArgs.version) {
Expand All @@ -40,30 +44,106 @@ if (parsedArgs.help) {
const subcommand = parsedArgs._[0];
const dryrun = parsedArgs["dry-run"] as boolean;
const quiet = parsedArgs["quiet"] != undefined;

switch (subcommand) {
case "integrate":
await integrate("install", { dryrun });
break;

case "deintegrate":
await integrate("uninstall", { dryrun });
break;

case "status":
{
const cwd = Path.cwd();
if (
datadir().join(cwd.string.slice(1), "dev.pkgx.activated").isFile()
) {
//FIXME probably slower than necessary
//FIXME probably slower than ideal
const { pkgs } = await sniff(cwd);
Deno.exit(pkgs.length == 0 ? 1 : 0);
} else {
Deno.exit(1);
}
}
break;

case "ls":
for await (
const entry of walk(datadir().string, { includeDirs: false })
) {
if (entry.name === "dev.pkgx.activated") {
const partial_path = new Path(entry.path).parent().relative({
to: datadir(),
});
console.log(`/${partial_path}`);
}
}
break;

case undefined:
{
const cwd = Path.cwd();
const { pkgs } = await sniff(cwd);
if (
datadir().join(cwd.string.slice(1), "dev.pkgx.activated").isFile()
) {
console.log(
"%cactive",
"color: green",
pkgs.map(utils.pkg.str).join(" "),
);
} else if (pkgs.length > 0) {
console.log(
"%cinactive",
"color: red",
pkgs.map(utils.pkg.str).join(" "),
);
} else {
console.log("%cno keyfiles found", "color: red");
}
}
break;

case "off": {
let dir = Path.cwd();
while (dir.string != "/") {
const f = datadir().join(dir.string.slice(1), "dev.pkgx.activated")
.isFile();
if (f) {
f.rm();
console.log("%cdeactivated", "color: green", dir.string);
Deno.exit(0);
}
dir = dir.parent();
}
console.error("%cno devenv found", "color: red");
Deno.exit(1);
break;
}

default: {
const cwd = Path.cwd().join(subcommand as string);
await dump(cwd, { dryrun, quiet });
if (Deno.stdout.isTerminal()) {
const cwd = Path.cwd().join(subcommand as string);
const { pkgs } = await sniff(cwd);
if (pkgs.length > 0) {
datadir().join(cwd.string.slice(1)).mkdir("p").join(
"dev.pkgx.activated",
).touch();
console.log(
"%cactived",
"color: green",
pkgs.map(utils.pkg.str).join(" "),
);
} else {
console.error("%cno keyfiles found", "color: red");
Deno.exit(1);
}
} else {
const cwd = Path.cwd().join(subcommand as string);
await dump(cwd, { dryrun, quiet });
}
}
}
}
9 changes: 8 additions & 1 deletion src/shellcode().ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,14 @@ dev() {
case "$1" in
off)
if type -f _pkgx_dev_try_bye >/dev/null 2>&1; then
rm "${datadir()}$PWD/dev.pkgx.activated"
dir="$PWD"
while [ "$dir" != / -a "$dir" != . ]; do
if [ -f "${datadir()}/$dir/dev.pkgx.activated" ]; then
rm "${datadir()}/$dir/dev.pkgx.activated"
break
fi
dir="$(dirname "$dir")"
done
PWD=/ _pkgx_dev_try_bye
else
echo "no devenv" >&2
Expand Down