MCPcopy
hub / github.com/abiosoft/ishell

github.com/abiosoft/ishell @v2.0.2 sqlite

repository ↗ · DeepWiki ↗ · release v2.0.2 ↗
181 symbols 360 edges 12 files 86 documented · 48%
README

ishell

ishell is an interactive shell library for creating interactive cli applications.

Go Reference Go Report Card

Usage

import "strings"
import "github.com/abiosoft/ishell/v2"

func main(){
    // create new shell.
    // by default, new shell includes 'exit', 'help' and 'clear' commands.
    shell := ishell.New()

    // display welcome info.
    shell.Println("Sample Interactive Shell")

    // register a function for "greet" command.
    shell.AddCmd(&ishell.Cmd{
        Name: "greet",
        Help: "greet user",
        Func: func(c *ishell.Context) {
            c.Println("Hello", strings.Join(c.Args, " "))
        },
    })

    // run shell
    shell.Run()
}

Execution

Sample Interactive Shell
>>> help

Commands:
  clear      clear the screen
  greet      greet user
  exit       exit the program
  help       display help

>>> greet Someone Somewhere
Hello Someone Somewhere
>>> exit
$

Reading input

// simulate an authentication
shell.AddCmd(&ishell.Cmd{
    Name: "login",
    Help: "simulate a login",
    Func: func(c *ishell.Context) {
        // disable the '>>>' for cleaner same line input.
        c.ShowPrompt(false)
        defer c.ShowPrompt(true) // yes, revert after login.

        // get username
        c.Print("Username: ")
        username := c.ReadLine()

        // get password.
        c.Print("Password: ")
        password := c.ReadPassword()

        ... // do something with username and password

        c.Println("Authentication Successful.")
    },
})

Execution

>>> login
Username: someusername
Password:
Authentication Successful.

Multiline input

Builtin support for multiple lines.

>>> This is \
... multi line

>>> Cool that << EOF
... everything here goes
... as a single argument.
... EOF

User defined

shell.AddCmd(&ishell.Cmd{
    Name: "multi",
    Help: "input in multiple lines",
    Func: func(c *ishell.Context) {
        c.Println("Input multiple lines and end with semicolon ';'.")
        lines := c.ReadMultiLines(";")
        c.Println("Done reading. You wrote:")
        c.Println(lines)
    },
})

Execution

>>> multi
Input multiple lines and end with semicolon ';'.
>>> this is user defined
... multiline input;
You wrote:
this is user defined
multiline input;

Keyboard interrupt

Builtin interrupt handler.

>>> ^C
Input Ctrl-C once more to exit
>>> ^C
Interrupted
exit status 1

Custom

shell.Interrupt(func(count int, c *ishell.Context) { ... })

Multiple Choice

func(c *ishell.Context) {
    choice := c.MultiChoice([]string{
        "Golangers",
        "Go programmers",
        "Gophers",
        "Goers",
    }, "What are Go programmers called ?")
    if choice == 2 {
        c.Println("You got it!")
    } else {
        c.Println("Sorry, you're wrong.")
    }
},

Output

What are Go programmers called ?
  Golangers
  Go programmers
> Gophers
  Goers

You got it!

Checklist

func(c *ishell.Context) {
    languages := []string{"Python", "Go", "Haskell", "Rust"}
    choices := c.Checklist(languages,
        "What are your favourite programming languages ?", nil)
    out := func() []string { ... } // convert index to language
    c.Println("Your choices are", strings.Join(out(), ", "))
}

Output

What are your favourite programming languages ?
    Python
  ✓ Go
    Haskell
 >✓ Rust

Your choices are Go, Rust

Progress Bar

Determinate

func(c *ishell.Context) {
    c.ProgressBar().Start()
    for i := 0; i < 101; i++ {
        c.ProgressBar().Suffix(fmt.Sprint(" ", i, "%"))
        c.ProgressBar().Progress(i)
        ... // some background computation
    }
    c.ProgressBar().Stop()
}

Output

[==========>         ] 50%

Indeterminate


func(c *ishell.Context) {
    c.ProgressBar().Indeterminate(true)
    c.ProgressBar().Start()
    ... // some background computation
    c.ProgressBar().Stop()
}

Output

[ ====               ]

Custom display using briandowns/spinner.

display := ishell.ProgressDisplayCharSet(spinner.CharSets[11])
func(c *Context) { c.ProgressBar().Display(display) ... }

// or set it globally
ishell.ProgressBar().Display(display)

Durable history

// Read and write history to $HOME/.ishell_history
shell.SetHomeHistoryPath(".ishell_history")

Non-interactive execution

In some situations it is desired to exit the program directly after executing a single command.

// when started with "exit" as first argument, assume non-interactive execution
if len(os.Args) > 1 && os.Args[1] == "exit" {
    shell.Process(os.Args[2:]...)
} else {
    // start shell
    shell.Run()
}
# Run normally - interactive mode:
$ go run main.go
>>> |

# Run non-interactivelly
$ go run main.go exit greet Someusername
Hello Someusername

Output with Color

You can use fatih/color.

func(c *ishell.Context) {
    yellow := color.New(color.FgYellow).SprintFunc()
    c.Println(yellow("This line is yellow"))
}

Execution

>>> color
This line is yellow

Example

Available here.

go run example/main.go

Supported Platforms

  • [x] Linux
  • [x] OSX
  • [x] Windows [Not tested but should work]

Note

ishell is in active development and can still change significantly.

Roadmap (in no particular order)

  • [x] Multiline inputs
  • [x] Command history
  • [x] Customizable tab completion
  • [x] Handle ^C interrupts
  • [x] Subcommands and help texts
  • [x] Scrollable paged output
  • [x] Progress bar
  • [x] Multiple choice prompt
  • [x] Checklist prompt
  • [x] Support for command aliases
  • [ ] Multiple line progress bars
  • [ ] Testing, testing, testing

Contribution

  1. Create an issue to discuss it.
  2. Send in Pull Request.

License

MIT

Credits

Library Use
github.com/flynn-archive/go-shlex splitting input into command and args.
github.com/chzyer/readline readline capabilities.

Donate

bitcoin: 1GTHYEDiy2C7RzXn5nY4wVRaEN2GvLjwZN
paypal: a@abiosoft.com

Extension points exported contracts — how you extend this code

ProgressDisplay (Interface)
ProgressDisplay handles the display string for a progress bar. [1 implementers]
progress.go
Actions (Interface)
Actions are actions that can be performed by a shell. [1 implementers]
actions.go
ProgressBar (Interface)
ProgressBar is an ishell progress bar. [1 implementers]
progress.go
ProgressDisplayFunc (FuncType)
ProgressDisplayFunc is a convenience function to create a ProgressDisplay. percent is -1 for indeterminate and 0-100 for
progress.go

Core symbols most depended-on inside this repo

AddCmd
called by 26
command.go
Println
called by 24
actions.go
Print
called by 10
actions.go
FindCmd
called by 8
command.go
ProgressBar
called by 7
ishell.go
ShowPrompt
called by 6
actions.go
Children
called by 6
command.go
SetPrompt
called by 4
actions.go

Shape

Method 134
Function 29
Struct 10
Interface 4
TypeAlias 3
FuncType 1

Languages

Go100%

Modules by API surface

actions.go49 symbols
ishell.go45 symbols
progress.go42 symbols
command.go12 symbols
context.go8 symbols
reader.go7 symbols
command_test.go7 symbols
functions.go5 symbols
completer.go3 symbols
utils_windows.go1 symbols
utils_unix.go1 symbols
example/main.go1 symbols

Dependencies from manifests, versioned

github.com/abiosoft/readlinev0.0.0-2018060704043 · 1×
github.com/chzyer/logexv1.1.10 · 1×
github.com/chzyer/testv0.0.0-2018021303581 · 1×
github.com/flynn-archive/go-shlexv0.0.0-2015051514535 · 1×

For agents

$ claude mcp add ishell \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact