Skip to content

Commit

Permalink
Core exe/md code
Browse files Browse the repository at this point in the history
  • Loading branch information
mxcl committed Jul 6, 2022
1 parent 11ddbcd commit fe9ae8f
Show file tree
Hide file tree
Showing 16 changed files with 558 additions and 320 deletions.
71 changes: 50 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
![tea](https://tea.xyz/banner.png)

tea is a delightful developer tool that gives you and your team your time back
so you can concentrate on what matters: *building your app*.
Package managers prop up every developer’s stack.
With great power comes great responsibility—but like—packagers sit beneath all other developer tools;
couldn’t they do so much more?

tea is built with a set of primitives that make packaging *programmable*.
We made tea/cli with those primitives.
We want *you* to compose them and build completely new tools,
workflows and inventions that change how you work, how your team works or
even (especially) *how the world works*.
We think so.

tea abstracts away packaging; its a *universal* virtual environment manager,
a *universal* interpreter; it’s a *universal* dependency manager.
tea makes packaging *programmable* by exposing it as a set of primitives that can be composed into entirely new tools.
Change how you work.
Change how your team works.
*Change how the world works*.

 


# tea/cli 0.2.0
# tea/cli 0.3.0

tea is a universal virtual‑environment manager:

Expand All @@ -35,10 +39,7 @@ VERSION=…
```

Fear not, this magic works with things like [VSCode] too (we don’t believe in
forcing or restricting your choice of tooling).

> <details><summary><i>What is this sourcery?</i></summary>
> <details><summary><i>What is this sourcery?</i></summary><br>
>
> tea uses a shell hook to insert the precise tooling your project needs into
> your shell environment. Development is now containerized at the
Expand All @@ -53,7 +54,23 @@ forcing or restricting your choice of tooling).
> trying to execute it will install it first.
> </details>
[VSCode]: https://code.visualstudio.com
> <details><summary><i>Fear not! This works with your other shit…</i></summary><br>
>
> Fear not, this magic works with things like [VSCode] too (we don’t believe in
> forcing or restricting your choice of tooling).
> </details>
> <details><summary><i>PSA:</i> Stop using Docker</summary><br>
>
> Docker is great for deployment, but it sucks for dev.
>
> *Docker stifles builders*.
> It constricts you; you’re immalleable; tech marches onwards but your docker
> container remains immobile.
>
> Keep deploying with Docker, but use tea to develop (and when you deploy, use
> tea to install your deps).
> </details>
&nbsp;

Expand All @@ -67,7 +84,10 @@ go: running demo.go
```

> <details><summary><i>Is this safe?</i></summary>
We infer interpreter from the extension, shebang, YAML front matter or
open graph metadata (we’ve added packaging extensions).

> <details><summary><i>Is this safe?</i></summary><br>
>
> If you’re worried about executing scripts from the Internet: *read them
> first!* tea only executes what the script tells it to; the dependency
Expand Down Expand Up @@ -99,7 +119,7 @@ $ curl https://github.com/teaxyz/demos/blob/main/ai.py

> † we use the term dependency manager for tools like npm, pip, cargo and gem
> that install packages for programming languages. They are variants of
> package managers. tea blurs the line a little between these tools.
> package managers. tea blurs the line between these tools.
&nbsp;

Expand Down Expand Up @@ -131,6 +151,9 @@ $ tea build
tea: executing `# Build`
```

&nbsp;



## A Brief Diatribe

Expand Down Expand Up @@ -187,7 +210,7 @@ If they want to learn about tea first they can go to the same URL as they’re
curl’ing. And as soon as we enable cross platform support this one-liner
will work for everyone, everywhere.

> <details><summary><i>Installing Manually</i></summary>
> <details><summary><i>Installing Manually</i></summary><br>
>
> `tea` is a single binary that you can install yourself:
>
Expand All @@ -209,7 +232,7 @@ will work for everyone, everywhere.
>
> </details>
> <details><summary><i>Uninstalling tea</i></summary>
> <details><summary><i>Uninstalling tea</i></summary><br>
>
> tea installs everything to `/opt` though other things may live there too, so
> don’t delete indiscriminately.
Expand All @@ -227,7 +250,7 @@ tools you need per project or script are available to that workspace as
*virtual environments*. Our magic works from depths of libc to the heights of
the latests fads in CSS precompilers. All versions†. All platforms‡.
>we’re new software, give us time to achieve this promise
>We’re new software, give us time to achieve this promise.\
> ‡ Windows, Raspberry Pi, BeOS, etc. coming soon!
When you `cd` into a project in your terminal, tea sets up the environment so
Expand Down Expand Up @@ -256,7 +279,7 @@ your `README`.
>
> </details>
For an example see our [Dependencies](#dependencies) section
For an example see our “[dependencies](#dependencies) section
(teaception: we use tea to build tea).
You can check what environment this generates with `tea`:
Expand Down Expand Up @@ -397,7 +420,7 @@ tea allows you to “get started” anywhere (*just not quite yet*).
# Magic
tea uses the concept of magic. In an environment with magic we try to be
clever and infer what you want. In an environment of muggles we are strict and
clever and infer what you want. Without magic we are strict and
require precise specification of your intent.
You can disable magic by specifying `--muggle` or exporting `MAGIC=0` to your
Expand Down Expand Up @@ -493,4 +516,10 @@ If you got this error message, you need to install tea:
| Project | Version | Lock |
|-------------|---------|--------|
| deno.land | ^1.18 | 1.20.3 |
| tea.xyz | 0.2.0 | - |
| tea.xyz | ^0 | 0.3.0 |
[pantry]: ../../../../pantry
[VSCode]: https://code.visualstudio.com
[Markdown]: https://daringfireball.net/projects/markdown/
[discussion]: ../../discussions
4 changes: 2 additions & 2 deletions scripts/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ args: /bin/sh
deno test \
--allow-net \
--allow-read \
--allow-env=SRCROOT,GITHUB_TOKEN \
--allow-env=SRCROOT,GITHUB_TOKEN,TMPDIR \
--allow-run \
--import-map=$SRCROOT/import-map.json \
--allow-write="$TMPDIR"
--allow-write="$TMPDIR" \
tests/*.ts
70 changes: 70 additions & 0 deletions src/app.dump.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { VirtualEnv } from "hooks/useVirtualEnv.ts"
import { print, undent } from "utils"
import useShellEnv from "hooks/useShellEnv.ts"
import usePantry from "hooks/usePantry.ts"

interface Options {
env: VirtualEnv | undefined
}

//TODO needs to take a argish parameter

export default async function dump({ env: blueprint }: Options) {
console.verbose({ blueprint })

const shell = Deno.env.get("SHELL")?.split('/').pop()
const [ setEnv, unsetEnv ]= (() => {
switch (shell) {
case "fish":
return [
(name: string, val: string) => `set -gx ${name} ${val};`,
(name: string) => `set -e ${name};`
]
default:
return [
(name: string, val: string) => `export ${name}=${val}`,
(name: string) => `unset ${name}`
]
}})()
if (blueprint?.srcroot) {
await print(setEnv("SRCROOT", blueprint.srcroot.string))
} else if (Deno.env.get("SRCROOT")) {
await print(unsetEnv("SRCROOT"))
}

const { combinedStrings: vars, pending } = await useShellEnv(blueprint?.requirements ?? [])

//TODO if PATH is the same as the current PATH maybe don't do it
// though that makes the behavior of --env --dump very specific

for (const [key, value] of Object.entries(vars)) {
await print(value
? setEnv(key, value)
: unsetEnv(key))
}
if (blueprint?.version) {
await print(setEnv("VERSION", blueprint.version.toString()))
}

// TODO: implement command-not-found for fish
if (shell !== "fish") { return }

if (pending.length) {
const pantry = usePantry()
let rv = undent`
command_not_found_handler() {
case $0 in
`
for (const pkg of pending) {
const cmds = (await pantry.getProvides(pkg)).join("|")
rv += ` ${cmds}) tea -xmP ${pkg.project}@'${pkg.constraint}' -- "$@";;\n`
}
rv += ` *)\n printf 'zsh: command not found: %s\\n' "$1";;\n esac\n}`

await print(rv)
} else {
//TODO unless there's a default!
await print("if typeset -f command_not_found_handler >/dev/null; then unset -f command_not_found_handler; fi")
}
}
56 changes: 56 additions & 0 deletions src/app.exec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { run, undent } from "utils"
import hydrate from "./prefab/hydrate.ts"
import resolve from "./prefab/resolve.ts"
import base_install from "./prefab/install.ts"
import { lvl1 as link } from "./prefab/link.ts"
import useShellEnv from "hooks/useShellEnv.ts"
import useCellar from "hooks/useCellar.ts"
import { PackageRequirement, Path } from "types"
import { VirtualEnv } from "hooks/useVirtualEnv.ts"
import useExecutableMarkdown from "hooks/useExecutableMarkdown.ts"

type Options = {
args: string[]
env: VirtualEnv | undefined
pkgs: PackageRequirement[]
}

export default async function exec({ args, ...opts }: Options) {
const cellar = useCellar()

if (args.length < 1) throw "contract violation"

await install(opts.pkgs)

const filename = Path.cwd().join(args[0]).isFile()
if (filename?.extname() == '.md') {
const target = args[1]
const sh = await useExecutableMarkdown({ filename }).findScript(target)
const path = Path.mktemp().join('script').write({ text: undent`
#!/bin/sh
${sh}
` }).chmod(0o500).string
args = [path, ...args.slice(2)]
}

const env = (await useShellEnv(opts.pkgs)).combinedStrings
if (opts.env) {
env["SRCROOT"] = opts.env.srcroot.string
if (opts.env.version) env["VERSION"] = opts.env.version.toString()
}

const cmd = [...args]
await run({ cmd, env }) //TODO implement `execvp`

/////////////////////////////////////////////////////////////
async function install(dry: PackageRequirement[]) {
const wet = await hydrate(dry) ; console.debug({wet})
const gas = await resolve(wet) ; console.debug({gas})
for (const pkg of gas) {
if (await cellar.isInstalled(pkg)) continue
console.info({ installing: pkg })
const installation = await base_install(pkg)
await link(installation)
}
}
}
75 changes: 75 additions & 0 deletions src/app.help.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import useFlags from "hooks/useFlags.ts"
import { print, undent } from "utils"

export default async function help() {
const { verbose } = useFlags()

// tea -mx +deno.land^1.18 foo.ts -- bar
// tea -mx +deno.land^1.18 deno -- ./script-file foo bar baz
// tea build
// tea -mx ./README.md -- build

//TODO make the stuff in brackets grayed out a bit

if (!verbose) {
// 10| 20| 30| 40| 50| 60| 70| | 80|
await print(undent`
usage:
tea [-xd] [flags] [file|URL|target|cmd|interpreter] [+package~x.y] -- [arg…]
modes: magical?
05 𝑜𝑚𝑖𝑡𝑡𝑒𝑑 infer operation ✨
--exec,-x execute
--dump,-d dump
flags:
10 --env,-E inject virtual environment ✨
--muggle,-m disable magic
--verbose,-v eg. tea -vv
--silent,-s no chat, no errors
--cd,-C change directory first
15
more:
tea -vh
18 open github.com/teaxyz/cli
`)
//HEYU! did you exceed 22 lines? Don’t! That’s the limit!
} else {
// 10| 20| 30| 40| 50| 60| 70| | 80|
await print(undent`
usage:
tea [-xd] [flags] [file|URL|target|cmd|interpreter] [+package~x.y] -- [arg…]
modes: magical? env-aware
--exec,-x execute (omittable if ✨) ✨ 𐄂
--dump,-d dump ✨ 𐄂
aliases:
--help,-h --dump=usage
--version,-v --dump=version 𐄂
flags:
--env,-E inject virtual environment ✨
--json,-j output json
--muggle,-m disable magic
--verbose,-v short form accumulates, shows version first
--silent,-s no chat, no errors
--cd,-C,--chdir change directory first
environment variables:
VERBOSE {-1: silent, 0: default, 1: verbose, 2: debug}
MAGIC [0,1]
DEBUG [0,1]: alias for \`VERBOSE=2\`
TEA_DIR \`--chdir \${directory}\`
notes:
- explicit flags override any environment variables
- the results of magic can be observed if verbosity is > 0
ideology:
> A successful tool is one that was used to do something undreamed of
> by its author
—𝑠ℎ𝑎𝑑𝑜𝑤𝑦 𝑠𝑢𝑝𝑒𝑟 𝑐𝑜𝑑𝑒𝑟
`)
}
}
Loading

0 comments on commit fe9ae8f

Please sign in to comment.