Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/vladimirvivien/gosh
Gosh - a pluggable framework for building command shell programs
https://github.com/vladimirvivien/gosh
cli command-line go go-buildmode golang plugin shared-library shell
Last synced: 17 days ago
JSON representation
Gosh - a pluggable framework for building command shell programs
- Host: GitHub
- URL: https://github.com/vladimirvivien/gosh
- Owner: vladimirvivien
- License: mit
- Created: 2017-03-19T22:26:51.000Z (over 7 years ago)
- Default Branch: master
- Last Pushed: 2020-01-14T22:54:55.000Z (almost 5 years ago)
- Last Synced: 2024-11-17T22:02:27.318Z (24 days ago)
- Topics: cli, command-line, go, go-buildmode, golang, plugin, shared-library, shell
- Language: Go
- Homepage:
- Size: 22.5 KB
- Stars: 529
- Watchers: 14
- Forks: 56
- Open Issues: 3
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
- awesome-ccamel - vladimirvivien/gosh - Gosh - a pluggable framework for building command shell programs (Go)
- awesome-repositories - vladimirvivien/gosh - Gosh - a pluggable framework for building command shell programs (Go)
- awesome-list - gosh - a pluggable framework for building command shell programs | vladimirvivien | 450 | (Go)
README
# Gosh - A pluggable interactive shell written Go
`Gosh` (or Go shell) is a framework that uses Go's plugin system to create
for building interactive console-based shell programs. A gosh shell is
comprised of a collection of Go plugins which implement one or more commands.
When `gosh` starts, it searches directory `./plugins` for available shared object
files that implement command plugins.## Getting started
#### Pre-requisites
* Go 1.8 or above
* Linux
* Mac OSXGosh makes it easy to create shell programs. First, download or clone this
repository. For a quick start, run the following:```bash
go run shell/gosh.go
```
This will produce the following output:
```bash888
888
888
.d88b. .d88b. .d8888b 88888b.
d88P"88bd88""88b88K 888 "88b
888 888888 888"Y8888b.888 888
Y88b 888Y88..88P X88888 888
"Y88888 "Y88P" 88888P'888 888
888
Y8b d88P
"Y88P"No commands found
```
After the splashscreen is displayed, `gosh` informs you that `no commands found`, as expected. Next,
exit the `gosh` shell (`Ctrl-C`) and let us compile the example plugins that comes with the source code.```bash
go build -buildmode=plugin -o plugins/sys_command.so plugins/syscmd.go
```
The previous command will compile `plugins/syscmd.go` and outputs shared object
`plugins/sys_command.so`, as a Go plugin file. Verify the shared object file was created:```
> ls -lh plugins/
total 3.2M
-rw-rw-r-- 1 4.5K Mar 19 18:23 syscmd.go
-rw-rw-r-- 1 3.2M Mar 19 19:14 sys_command.so
-rw-rw-r-- 1 1.4K Mar 19 18:23 testcmd.go
```
Now, when gosh is restarted, it will dynamically load the commands implemented in the shared object file:```bash
> go run shell/gosh.go
...Loaded 4 command(s)...
Type help for available commandsgosh>
```As indicated, typing `help` lists all available commands in the shell:
```bash
gosh> helphelp: prints help information for other commands.
Available commands
------------------
prompt: sets a new shell prompt
sys: sets a new shell prompt
help: prints help information for other commands.
exit: exits the interactive shell immediatelyUse "help " for detail about the specified command
```
## A command
A Gosh `Command` is represented by type `api/Command`:
```go
type Command interface {
Name() string
Usage() string
ShortDesc() string
LongDesc() string
Exec(context.Context, []string) (context.Context, error)
}
```The Gosh framework searches for Go plugin files in the `./plugins` directory. Each package plugin must
export a variable named `Commands` which is of type :
```go
type Commands interface {
...
Registry() map[string]Command
}
```
Type `Commands` type returns a list of `Command` via the `Registry()`.The following shows example command file [plugins/testcmd.go](./plugins/testcmd.go). It implements
two commands via types `helloCmd` and `goodbyeCmd`. The commands are exported via type `testCmds` using
method `Registry()`:```go
package mainimport (
"context"
"fmt"
"io""github.com/vladimirvivien/gosh/api"
)type helloCmd string
func (t helloCmd) Name() string { return string(t) }
func (t helloCmd) Usage() string { return `hello` }
func (t helloCmd) ShortDesc() string { return `prints greeting "hello there"` }
func (t helloCmd) LongDesc() string { return t.ShortDesc() }
func (t helloCmd) Exec(ctx context.Context, args []string) (context.Context, error) {
out := ctx.Value("gosh.stdout").(io.Writer)
fmt.Fprintln(out, "hello there")
return ctx, nil
}type goodbyeCmd string
func (t goodbyeCmd) Name() string { return string(t) }
func (t goodbyeCmd) Usage() string { return t.Name() }
func (t goodbyeCmd) ShortDesc() string { return `prints message "bye bye"` }
func (t goodbyeCmd) LongDesc() string { return t.ShortDesc() }
func (t goodbyeCmd) Exec(ctx context.Context, args []string) (context.Context, error) {
out := ctx.Value("gosh.stdout").(io.Writer)
fmt.Fprintln(out, "bye bye")
return ctx, nil
}// command module
type testCmds struct{}func (t *testCmds) Init(ctx context.Context) error {
out := ctx.Value("gosh.stdout").(io.Writer)
fmt.Fprintln(out, "test module loaded OK")
return nil
}func (t *testCmds) Registry() map[string]api.Command {
return map[string]api.Command{
"hello": helloCmd("hello"),
"goodbye": goodbyeCmd("goodbye"),
}
}var Commands testCmds
```## License
MIT