Skip to content

Commit

Permalink
Merge ad751e4 into 82e18c3
Browse files Browse the repository at this point in the history
  • Loading branch information
odino committed Apr 4, 2020
2 parents 82e18c3 + ad751e4 commit 23c36d1
Show file tree
Hide file tree
Showing 25 changed files with 665 additions and 162 deletions.
23 changes: 4 additions & 19 deletions ast/ast.go
Expand Up @@ -435,30 +435,15 @@ func (fl *FunctionLiteral) String() string {
}

type Decorator struct {
Token token.Token // @
Name string
Arguments []Expression
Decorated Expression
Token token.Token // @
Expression Expression
Decorated Expression
}

func (dc *Decorator) expressionNode() {}
func (dc *Decorator) TokenLiteral() string { return dc.Token.Literal }
func (dc *Decorator) String() string {
var out bytes.Buffer

args := []string{}
for _, a := range dc.Arguments {
args = append(args, a.String())
}

out.WriteString(dc.TokenLiteral())
out.WriteString(dc.Name)
out.WriteString("(")
out.WriteString(strings.Join(args, ", "))
out.WriteString(") ")
out.WriteString(dc.Decorated.String())

return out.String()
return dc.Expression.String()
}

type CurrentArgsLiteral struct {
Expand Down
6 changes: 6 additions & 0 deletions docs/_includes/toc.md
Expand Up @@ -27,6 +27,12 @@
* [Builtin functions](/types/builtin-function)
* [Decorators](/types/decorator)

## Standard library

* [Introduction](/stdlib/intro)
* [@runtime](/stdlib/runtime)
* [@cli](/stdlib/cli)

## Miscellaneous

* [Installing 3rd party libraries](/misc/3pl)
Expand Down
107 changes: 107 additions & 0 deletions docs/stdlib/cli.md
@@ -0,0 +1,107 @@
# @cli

The `@cli` module provides a simple interface to
easily build CLI applications.

## API

```py
cli = require('@cli')
```

### @cli.cmd(name, description, default_flags)

A decorator that registers a command to be executed via CLI:

```py
@cli.cmd("date", "prints the current date", {format: ''})
f date(args, flags) {
format = flags.format
return `date ${format}`
}
```

The `name` of the command matches the command entered
by the user on the CLI (eg. `$ ./cli my_command`), while
the description is used when printing a help message,
available through `$ ./cli help`.

The user can pass however many arguments and flags they want,
and they will be passed on to the function defined as command.
For example, when the user issues the command `$ ./cli a b c --flag 25`,
args will be `["a", "b", "c", "--flag", "25"]` and flags will
be `{"flag": "25"}`. Default flags are there so that, if a flag
is not passed, it will be populated with a default value.

### @cli.run()

Runs the CLI application:

```py
cli.run()
```

The application will, by default, have an `help` command
that lists all available commands and is called if no command
is provided.

## Example CLI app

Here is an example app with 3 commands:

* the default `help`
* `date`, to print the current date in a specific format
* `ip`, to fetch our IP address

```py
#!/usr/bin/env abs
cli = require('@cli')

@cli.cmd("ip", "finds our IP address", {})
f ip_address(arguments, flags) {
return `curl icanhazip.com`
}

@cli.cmd("date", "Is it Friday already?", {"format": ""})
f date(arguments, flags) {
format = flags.format
return `date ${format}`
}

cli.run()
```

You can save this script as `./cli` and make it executable
with `chmod +x ./cli`. Then you will be able to use the CLI
app:

```
$ ./cli
Available commands:
* date - Is it Friday already?
* help - print this help message
* ip - finds our IP address
$ ./cli help
Available commands:
* date - Is it Friday already?
* help - print this help message
* ip - finds our IP address
$ ./cli ip
87.201.252.69
$ ./cli date
Sat Apr 4 18:06:35 +04 2020
$ ./cli date --format +%s
1586009212
```

## Next

That's about it for this section!

You can now head over to read a little bit about [how to install 3rd party libraries](/misc/3pl).
104 changes: 104 additions & 0 deletions docs/stdlib/intro.md
@@ -0,0 +1,104 @@
# Standard library

ABS comes bundled not only with an array of builtin types and functions,
but also with a few modules to ease your development process: we refer
to this modules as the "standard library", "standard modules" or `stdlib`.

## Requiring a standard library module

Standard library modules are required the same way you'd require
any other external module, by using the `require(...)` function;
the only difference is that standard modules use the `@` character
as prefix, for example:

```py
mod = require('@module') # Loads "module" from the standard library
mod = require('./module') # Loads "module" from the current directory
mod = require('module') # Loads "module" that was installed through the ABS package manager
```

## Technical details

The ABS standard library is developed in ABS itself and available
for everyone to see (and poke with) at [github.com/abs-lang/abs/tree/master/stdlib](https://github.com/abs-lang/abs/tree/master/stdlib).

The `@cli` library, for example, is a simple ABS script of less
than 100 lines of code:

```bash
# CLI app
cli = {}

# Commands registered within this CLI app
cli.commands = {}

# Function used to register a command
cli.cmd = f(name, description, flags) {
return f(fn) {
cli.commands[name] = {};
cli.commands[name].cmd = f() {
# Create flags with default values
for k, _ in flags {
v = flag(k)

if v {
flags[k] = v
}
}

# Call the original cmd
result = fn.call([args()[3:], flags])

# If there's a result we print it out
if result {
echo(result)
}
}

cli.commands[name].description = description
}
}

# Run the CLI app
cli.run = f() {
# ABS sees "abs script.abs xyz"
# so the command is the 3rd argument
cmd = arg(2)

# Not passing a command? Let's print the help
if !cmd {
return cli.commands['help'].cmd()
}

if !cli.commands[cmd] {
exit(99, "command '${cmd}' not found")
}

return cli.commands[cmd].cmd()
}

# Add a default help command that can be
# overridden by the caller
@cli.cmd("help", "print this help message", {})
f help() {
echo("Available commands:\n")

for cmd in cli.commands.keys().sort() {
s = " * ${cmd}"

if cli.commands[cmd].description {
s += " - " + cli.commands[cmd].description
}

echo(s)
}
}

return cli
```
## Next
That's about it for this section!
You can now explore ABS' first standard library module, the [@runtime](/stdlib/runtime).
32 changes: 32 additions & 0 deletions docs/stdlib/runtime.md
@@ -0,0 +1,32 @@
# @runtime

The `@runtime` module provides information about the ABS
runtime that is currently executing the script.

## API

```py
runtime = require('@runtime')
```

### @runtime.version

Returns the version of the ABS interpreter:

```py
runtime.version # "x.y.z" eg. 1.0.0
```

### @runtime.name

Returns the name of the runtime:

```py
runtime.name # "abs"
```

## Next

That's about it for this section!

You can now explore how to easily build command-line applications through the [@cli](/stdlib/cli) module.

0 comments on commit 23c36d1

Please sign in to comment.