Giter Site home page Giter Site logo

ishell's Introduction

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

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

Note

ishell is in active development and can still change significantly.

Roadmap (in no particular order)

  • Multiline inputs
  • Command history
  • Customizable tab completion
  • Handle ^C interrupts
  • Subcommands and help texts
  • Scrollable paged output
  • Progress bar
  • Multiple choice prompt
  • Checklist prompt
  • 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: [email protected]

ishell's People

Contributors

abiosoft avatar chessman avatar delaneyj avatar dokipen avatar eprparadox82 avatar eskriett avatar mindreframer avatar muesli avatar napche avatar omani avatar pierren avatar poppycompass avatar rhuss avatar svenbs avatar tomruk avatar tonyazzimov avatar ugy avatar vaelen avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ishell's Issues

customized Prompt doesn't work

func NewWithConfig(conf *readline.Config) *Shell {
	rl, err := readline.NewEx(conf)
	if err != nil {
		log.Println("Shell or operating system not supported.")
		log.Fatal(err)
	}
	shell := &Shell{
		rootCmd: &Cmd{},
		reader: &shellReader{
			scanner:     rl,
			prompt:      defaultPrompt,
			multiPrompt: defaultMultiPrompt,
			showPrompt:  true,
			buf:         &bytes.Buffer{},
			completer:   readline.NewPrefixCompleter(),
		},
		writer:   conf.Stdout,
		haltChan: make(chan struct{}),
		autoHelp: true,
	}
	shell.Actions = &shellActionsImpl{Shell: shell}
	shell.progressBar = newProgressBar(shell)
	addDefaultFuncs(shell)
	return shell
}

still use defaultPrompt not conf.Prompt

Feature: integration with spinner and progress bar libraries

I tried without success to use some library for spinners ( github.com/briandowns/spinner ) but it seems that the shell is taking over the display.

This is a feature request: compatibility with some spinners and progress bar libraries, or core integration of the feature.

I would use the spinner for waiting until timeouts, and the progress bar to display some incoming time info about an operation in progress.

Thanks for your library anyway

Feature request: Pipe operator (function)

hi,

I am thinking of a pipe operator in ishell. so you could pipe through another function:

>>> print "hello" | func1

stdout (or return of the print function) is piped into func1 as stdin (or input arguments).

is this possible or any plans to implement this?

doubled output with Context.Printf()

The attached program creates two commands; the first, "foo", uses ishell.Context.Println() to print "foo', and the second, "bar" uses ishell.Context.Printf() to print "bar". If I build it and run it (on OSX, FWIW), giving it the command "foo", gives me one "foo" printed, but multiple "bar"s are printed for the "bar" command. (Note that the output looks like I entered "bar" multiple times, but I actually only entered it once.)

go build . && ./bug
>>> foo
foo
>>> bar
bar
>>> bar
>>> bar
^D
EOF

Looking at actions.go, I notice that Println() only sends output to s.writer, but that Print() and Printf() send output to both that and s.reader.buf. I haven't dug further to understand why this is.

bug.go.txt

It's impossible to enter a literal tab (\t) in the shell

It seems shlex has quite weird behaviour for escaped characters.
If you enter:

>>> command "a\tb"

The argument you get will be atb. Typing an actual literal tab character is ignored by the shell, so it's also not possible to enter a tab that way.

I don't see a very easy way to fix this, especially since shlex is not maintained anymore. Would you be okay with a PR that removes the dependency on shlex and uses strconv.Unquote() to handle escaping and quoting?

Access to interruptCount

Perhaps there is a better way to do this but it's currently escaping me so any advice is appreciated.

I'm writing a custom interrupt handler but I'd like to make use of interruptCount similar to the way the default handler function works. But I don't believe I have access to that interruptCount variable to check or increment.

Perhaps making that variable public or giving access to it in some other way?

Alternatively, giving a hook where the count can be reset would work as well.

Again, if I'm missing something then I'd appreciate a point in the right direction.

Thanks!

Ctrl+C does not quit the program on multiple ReadLine prompts:

I have 2 ReadLine() questions and when I hit Ctrl+C on any of them, the program is not exiting as expected, but proceeding to the next question.

	var name, displayName string

	sh := ishell.New()
	sh.AddCmd(&ishell.Cmd{
		Name: "default",
		Func: func(c *ishell.Context) {
			c.Printf("Name: ")
			name = c.ReadLine()

			c.Printf("Display name (optional): ")
			displayName = c.ReadLine()
		}})
	sh.Process("default")

	fmt.Println("Answers:", name, displayName)

Hit Ctrl+c on the first question, falls back to second question:

Name: ^C
Display name (optional):

hit Ctrl+C on second question, it proceeded on running the rest of the program:

Name: ^C
Display name (optional): ^C
Answers:

it should be quitting the program on first Ctrl+C.

Checklist() does not scroll among the options if the term.height<len(options)

Similar to #35, if the term.height is a lot less than list of options, using Up/Arrow down keys do not update screen to always show the cursor. Inquisitor.js can be a good example of how this can be performed correctly.

I can still move the cursor to point to another option, but I can't see the item I am pointing at once it's off-screen.

Make the icon of Multiple Choice and Checklist customizable

As the title suggested. We are using your library to build some application, and the symbols you have in Multiple Choice and Checklist show up greatly on terminal clients that support proper UTF-8 fonts. Unfortunately, this is not true across the organization and we had some complains about characters not show up correctly.

Can we make those characters customizable so that I can change them to something more ASCI friendly?

Best regards,

History

Have you thought about how you want command history to work? If you have some ideas on architecture for this, I'd love to help out.

Unselectable items for MultiChoice/Checklist

Currently all items in MultiChoice/Checklist are selectable.

If there was a way to specify unselectable items, those could be used as section headers to separate a long list of items. While cycling through options, the cursor wouldn't land on these items, it would just move onto the next item.

Do not clear screen for question/list prompts

This one is from Inquirer.js too:

image

Basically Inquirer.js can ask questions without clearing the screen (and printing the question to x=0 y=0) ishell currently clears the screen when called like ishell.New().MultiChoice(...)

(P.S. also in the long-list.js example above, if the list is longer than N items, it allows limiting the scroll area to N items, while still allowing user to scroll. but that's a separate topic.)

command arg validation

Any thoughts on having argument validation and/or help strings per command?

I'd like to have some kind of validation built in where I can specify that a command takes in specific args and have ishell be able to process the arguments and report any errors.

[Feature Request] Jumping to Commands

Hello guys,
I think it would be great to call (jump to) a command from another command.
Here is an usage example :

  • Command 1 = Lists log entries
  • Command 2 = Read details about each log entry

The idea is calling the first command from the second one when the user is done reading the details about the log entry he selected.. So it basically returns him to the list of logs

Feature Request: Provide ability to invoke chained functions

Hi,

given that I have a chain of Cmds (update, user, set, name) and "john" being an argument:

>>> update user set name john

It would be nice to have the invocation of this string as a subsequent invocation of all cmds in the chain. resulting in:
update.Func() -> user.Func() -> set.Func() -> name.Func() -> (c.Args[0] == john)

rather than only the function of name

right now I could parse c.RawArgs when name.Func() is called and call each cmds by myself. but it would be nice to have it built in into ishell.

readline.ClearScreen only returns error vs (int, error) on Windows

Looking at readline, it likes like the code for Windows for the call to ClearScreen only returns 1 arg rather than 2 for Unix, causing ishell to not compile on windows because of:
https://github.com/abiosoft/ishell/blob/master/actions.go#L167

Readline Windows:
https://github.com/chzyer/readline/blob/283f5429f7723ac628cb68a44a11097c11a7a9c1/utils_windows.go#L31

Unix:
https://github.com/chzyer/readline/blob/8a1389155f133761e8e73b585f47ed27a78b74d5/utils_unix.go#L48

any alternatives?

Are there alternatives to this package?

I'd like to compare most of them allow to build CLI apps but I couldn't find a way to build interactive shells like this app.

More practical examples in /example folder

In the /examples folder have more practical examples in separate files, for example, in the smod project:
https://github.com/enddo/smod

SMOD > show modules
Modules Description


modbus/dos/arp DOS with Arp Poisoning
modbus/dos/galilRIO DOS Galil RIO-47100
modbus/dos/writeAllCoils DOS With Write All Coils
modbus/dos/writeAllRegister DOS With Write All Register Function
modbus/dos/writeSingleCoils DOS With Write Single Coil Function
modbus/dos/writeSingleRegister DOS Write Single Register Function
modbus/function/fuzzing Fuzzing Modbus Functions
modbus/function/readCoils Fuzzing Read Coils Function
modbus/function/readCoilsException Fuzzing Read Coils Exception Function
modbus/function/readDiscreteInput Fuzzing Read Discrete Inputs Function
modbus/function/readDiscreteInputException Fuzzing Read Discrete Inputs Exception Function
modbus/function/readExceptionStatus Fuzzing Read Exception Status Function
modbus/function/readHoldingRegister Fuzzing Read Holding Registers Function
modbus/function/readHoldingRegisterException Fuzzing Read Holding Registers Exception Function
modbus/function/readInputRegister Fuzzing Read Input Registers Function
modbus/function/readInputRegisterException Fuzzing Read Input Registers Exception Function
modbus/function/writeSingleCoils Fuzzing Write Single Coil Function
modbus/function/writeSingleRegister Fuzzing Write Single Register Function
modbus/scanner/arpWatcher ARP Watcher
modbus/scanner/discover Check Modbus Protocols
modbus/scanner/getfunc Enumeration Function on Modbus
modbus/scanner/uid Brute Force UID
modbus/sniff/arp Arp Poisoning

Structure in linux filesystem:
/scada/tools/smod/Application# tree
.
└── modules
└── modbus
├── dos
│   ├── arp.py
│   ├── arp.pyc
│   ├── galilRIO.py
│   ├── galilRIO.pyc
│   ├── writeAllCoils.py
│   ├── writeAllCoils.pyc
│   ├── writeAllRegister.py
│   ├── writeAllRegister.pyc
│   ├── writeSingleCoils.py
│   ├── writeSingleCoils.pyc
│   ├── writeSingleRegister.py
│   └── writeSingleRegister.pyc
├── function
│   ├── fuzzing.py
│   ├── fuzzing.pyc
│   ├── readCoilsException.py
│   ├── readCoilsException.pyc
│   ├── readCoils.py
│   ├── readCoils.pyc
│   ├── readDiscreteInputException.py
│   ├── readDiscreteInputException.pyc
│   ├── readDiscreteInput.py
│   ├── readDiscreteInput.pyc
│   ├── readExceptionStatus.py
│   ├── readExceptionStatus.pyc
│   ├── readHoldingRegisterException.py
│   ├── readHoldingRegisterException.pyc
│   ├── readHoldingRegister.py
│   ├── readHoldingRegister.pyc
│   ├── readInputRegisterException.py
│   ├── readInputRegisterException.pyc
│   ├── readInputRegister.py
│   ├── readInputRegister.pyc
│   ├── writeSingleCoils.py
│   ├── writeSingleCoils.pyc
│   ├── writeSingleRegister.py
│   └── writeSingleRegister.pyc
├── scanner
│   ├── arpWatcher.py
│   ├── arpWatcher.pyc
│   ├── discover.py
│   ├── discover.pyc
│   ├── getfunc.py
│   ├── getfunc.pyc
│   ├── uid.py
│   └── uid.pyc
└── sniff
├── arp.py
└── arp.pyc

6 directories, 46 files

I would like to create a form of file structure in the filesystem of my project and that it would be called inside the source code in golang in ishell. An example in the / examples folder would be cool, even because the current example would already be the next step to this.

The more practical examples you have, the more developers will certainly use your project, which by the way is a great project.

@firebitsbr

Completer handling of suggestions containing whitespace

Seeing how the completer and readline integration works, I think suggestions containing spaces should be put in quotation marks upon completion. Also, prefixes beginning with a quotation mark should be handled correctly, e.g.: "foo + TAB should complete both foobar as well as "foo bar".

Checklist and MultiChoice have undesired behaviour when the term.height<len(options)

Firstly, if the list of options to Checklist() are greater than the row count of the terminal, the end of list is shown, even though the cursor is at the beginning

List of options: https://gist.github.com/ahmetb/f73482d3f11c0b5cdc4af1daf3cdbefd

image

You can see that this is the end of my options.

If I hit UpArrow key to go back to the end of list, it successfully does:

image

Secondly, if the term.height is a lot less than list of options, using Up/Arrow down keys do not update screen to always show the ❯ cursor. Inquisitor.js can be a good example of how this can be performed correctly.

I can still move the cursor to point to another option, but I can't see the item I am pointing at once it's off-screen.

Custom contextual completers for commands

Can ishell allow users to hook into the PrefixCompleterInterface when we Register commands? I'd like to be able to provide autocompletion given a command currently in the read line.
For example:

$ login --
--timeout --user --password

Furthermore, the autocompletion should be dynamic (which is probably possible via readline.PcItemDynamic):

$ ls /
bin tmp sbin etc

Interactive startup / initialization

Hi,

I could not find this function when I scanned the code: is it possible to have a kind of interactive startup, where, e.g., the user is asked to provide some information right after starting the application when some condition is met? For example, if a configuration parameter (path) is missing, then the user is asked right after startup to input this information, without the need to enter a command.

Example:

$user: go run myapp.go
This is myApp
Seems like this is the first start of the app. Please enter the directory to save the data:
>>>

Ability to pass in extra arguments to commands is gone

In v1 you were able to do something like this:

shell := ishell.New()
myObj := somelib.New(arg arg arg)

shell.Register("blah", blahfunc(shell, myObj))

Then blahfunc could do all sorts of things with myObj.

Am I missing how you can do this with the v2 API?

Wrong output from shell.Println when receiving from a goroutine

I am trying to print some output from a channel to the shell. When receiving from a goroutine it prints without a newline and does not give the prompt back. Example:

package main

import (
    "time"
    "github.com/abiosoft/ishell"
)


func feed(c chan string) {
    for i := 0; i<3; i++ {
        c <- "Feedback"
        time.Sleep(time.Second)
    }
}

func main(){
    shell := ishell.New()
    c := make(chan string)
    
    // listen
    go func() {
        for msg := range(c) {
            shell.Println(msg)
        }
    }()
    
    // this does output correctly
    //feed(c)
    // this does not
    go feed(c)
    
    shell.Start()
}

go feed(c) outputs:

>>> Feedback
Feedback
Feedback

To get the prompt back you have to type a letter

feed(c) outputs correctly:

Feedback
Feedback
Feedback
>>>  

Print doesn't display text if string doesn't end with '\n'

fmt.Printf doesn't work when there is no new-line character at the end of the string.

// This works fine
shell.AddCmd(&ishell.Cmd{
    Name: "hello",
    Func: func(c *ishell.Context) {
        fmt.Printf("Hello\n")
    },
})

// This does not
shell.AddCmd(&ishell.Cmd{
    Name: "hello",
    Func: func(c *ishell.Context) {
        fmt.Printf("Hello")
    },
})

The example doesn't work.

file: 'file:///c%3A/Users/wiecbuk/go/src/stash.dts.fm.rbsgrp.net/ep/edt_command_client.git/spike.go'
severity: 'Error'
message: 'unknown field 'Aliases' in struct literal of type ishell.Cmd'
at: '44,3'
source: ''

file: 'file:///c%3A/Users/wiecbuk/go/src/stash.dts.fm.rbsgrp.net/ep/edt_command_client.git/spike.go'
severity: 'Error'
message: 'c.MultiChoice undefined (type *ishell.Context has no field or method MultiChoice)'
at: '72,4'
source: ''

file: 'file:///c%3A/Users/wiecbuk/go/src/stash.dts.fm.rbsgrp.net/ep/edt_command_client.git/spike.go'
severity: 'Error'
message: 'c.Checklist undefined (type *ishell.Context has no field or method Checklist)'
at: '92,4'
source: ''

file: 'file:///c%3A/Users/wiecbuk/go/src/stash.dts.fm.rbsgrp.net/ep/edt_command_client.git/spike.go'
severity: 'Error'
message: 'shell.Process undefined (type *ishell.Shell has no field or method Process)'
at: '193,3'
source: ''

file: 'file:///c%3A/Users/wiecbuk/go/src/stash.dts.fm.rbsgrp.net/ep/edt_command_client.git/spike.go'
severity: 'Error'
message: 'shell.Run undefined (type *ishell.Shell has no field or method Run)'
at: '196,3'
source: ''

file: 'file:///c%3A/Users/wiecbuk/go/src/stash.dts.fm.rbsgrp.net/ep/edt_command_client.git/spike.go'
severity: 'Error'
message: 'shell.Close undefined (type *ishell.Shell has no field or method Close)'
at: '198,3'
source: ''

Possibility to have one-off execution of commands

Hey Abiola,

first: awesome library! Really-really enjoying it. The amount of functionality I get from just including it is staggering. Autocomplete, shell history, password masking, process bars, multiline input, paged output... Wow. Wow. Wow. So useful. Especially in devops context. Thank you for this package!

What I was thinking: how hard would it be to also allow non-interactive use? Just parsing args, executing that one single command and then exit? It would be very useful in scripted environments, like CI and such.

What are your thoughts on this?

Best,
Roman

How to clear prompt on same line?

Hi all,

first of all great piece of software. really like it.

I would like to know if there is an option equivalent to ClearScreen() but one which only clears the actual line instead of the whole screen.

so for example:

>>> something written on this line

and when I hit CTRL + C (which I can catch with Interrupt()) I want the line to be empty on the same line:

>>> 

without moving into a new prompt line.

is this possible?

Feature request: make context values public available

hi,

it would be a benefit to have:

// Context is an ishell context. It embeds ishell.Actions.
type Context struct {
	values      map[string]interface{}

values exposed so one can iterate through the keys and values.

because right now when passing contexts from method to method with keys set by c.Set() the target method needs to know which key was meant so it can operate on it.

invalid memory address or nil pointer dereference

Hello guys,
tryed the main.go in the examples folder, seems like there is a problem with the readPassword() on go version go1.9.1 darwin/amd64 (mac)

`panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x20 pc=0x1206f61]

goroutine 1 [running]:
github.com/chzyer/readline.(*RuneBuffer).output(0xc42008c8c0, 0x0, 0xc420051838, 0x120817c)
/Users/xxxx/Go/src/github.com/chzyer/readline/runebuf.go:494 +0xd1
github.com/chzyer/readline.(*RuneBuffer).print(0xc42008c8c0)
/Users/xxxx/Go/src/github.com/chzyer/readline/runebuf.go:475 +0x2b
github.com/chzyer/readline.(*RuneBuffer).Refresh(0xc42008c8c0, 0x0)
/Users/xxxx/Go/src/github.com/chzyer/readline/runebuf.go:465 +0xb2
github.com/chzyer/readline.(*Operation).Runes(0xc4200fe000, 0x0, 0x0, 0x0, 0x0, 0x0)
/Users/xxxx/Go/src/github.com/chzyer/readline/operation.go:388 +0xf9
github.com/chzyer/readline.(*Operation).Slice(0xc4200fe000, 0x12c1710, 0xc420010b50, 0x0, 0x107be01, 0xc420166d80)
/Users/xxxx/Go/src/github.com/chzyer/readline/operation.go:429 +0x2f
github.com/chzyer/readline.(*Operation).PasswordWithConfig(0xc4200fe000, 0xc420166d80, 0x0, 0x0, 0x0, 0x0, 0x0)
/Users/xxxx/Go/src/github.com/chzyer/readline/operation.go:417 +0xb5
github.com/chzyer/readline.(*Operation).PasswordEx(0xc4200fe000, 0xc420160166, 0xa, 0x0, 0x0, 0x0, 0xc420051b48, 0xc42011c000, 0x16006c8, 0x0)
/Users/xxxx/Go/src/github.com/chzyer/readline/operation.go:405 +0x165
github.com/chzyer/readline.(*Operation).Password(0xc4200fe000, 0xc420160166, 0xa, 0x1045db9, 0xc420160166, 0xc42013e028, 0xa, 0xc420160166)
/Users/xxxx/Go/src/github.com/chzyer/readline/operation.go:421 +0x55
github.com/chzyer/readline.(*Instance).ReadPassword(0xc42012c000, 0xc420160166, 0xa, 0x40, 0xc420160166, 0xa, 0x20, 0xa)
/Users/xxxx/Go/src/github.com/chzyer/readline/readline.go:232 +0x43
github.com/abiosoft/ishell.(*shellReader).readPasswordErr(0xc420134060, 0x1210932, 0x13eb220, 0xc42000e018, 0xc42016a160)
/Users/xxxx/Go/src/github.com/abiosoft/ishell/reader.go:49 +0xd5
github.com/abiosoft/ishell.(*shellReader).readPassword(0xc420134060, 0x0, 0x0)
/Users/xxxx/Go/src/github.com/abiosoft/ishell/reader.go:54 +0x2b
github.com/abiosoft/ishell.(*shellActionsImpl).ReadPassword(0xc420140000, 0xc42016a160, 0x1)
/Users/xxxx/Go/src/github.com/abiosoft/ishell/actions.go:81 +0x32
main.main.func1(0xc42018a000)
/Volumes/Secondary/Boulot/Experiments/go/genious/gcreport/gcreport.go:63 +0x24f
github.com/abiosoft/ishell.(*Shell).handleCommand(0xc420132000, 0xc42016a0a0, 0x1, 0x1, 0x1213c96, 0xc420051de8, 0xc420051dd8)
/Users/xxxx/Go/src/github.com/abiosoft/ishell/ishell.go:248 +0x2fc
github.com/abiosoft/ishell.handleInput(0xc420132000, 0xc42016a0a0, 0x1, 0x1, 0xc420132000, 0xc420156060)
/Users/xxxx/Go/src/github.com/abiosoft/ishell/ishell.go:202 +0x4d
github.com/abiosoft/ishell.(*Shell).run(0xc420132000)
/Users/xxxx/Go/src/github.com/abiosoft/ishell/ishell.go:181 +0x245
github.com/abiosoft/ishell.(*Shell).Run(0xc420132000)
/Users/xxxx/Go/src/github.com/abiosoft/ishell/ishell.go:97 +0x39
main.main()
/Volumes/Secondary/Boulot/Experiments/go/genious/gcreport/gcreport.go:77 +0x1c0
exit status 2`

Easily configurable question prompt for Readline()

Sorry about opening bunch of issues, just trying to gather my thoughts around what a Inquirer.js clone in Go would look like.

Currently, to read input from the user without initializing a shell session, the code looks like this:

sh := ishell.New()
sh.SetPrompt("First name :")
firstName := sh.Readline()
sh.SetPrompt("Last name :")
lastName := sh.Readline()

A more preferable way to work with the library would be like this:

...
firstName := sh.Readline("First name")
lastName := sh.Readline("Last name")

Add graceful processing for non-latin symbols: Error: Unknown rune: 1087

Hello!

Thank you for your awesome library! I'm using it for CLI management.

I recently discovered that ishell fails when I enter some non-latin letters, for example "привет" accidentally.

And ishell stopping immediately:

root@cli> привет
Error: Unknown rune: 1087

<application stopped>

Could you add graceful processing for this case and just return error "incorrect rune" to CLL shell without stopping ishell application?

Thank you for your attention!

adding RawArgs on Context

Hello,

As I am using ishell in a mix environment where I need to process shell commands as well as non shell commands that need to be sent elsewhere, I would like to discuss the feasibility to add a way to access the unprocessed set of strings (RawArgs) as opposed to the shell processed ones (removal of quotes and escaped characters handling). This would be especially useful when dealing with NotFound commands in which case you could just delegate the parsing to another handler.

What do you think?

Please expose context values through Shell object

I want to expose some values to all my shell commands, without resorting to global values, so the context values map seems an obvious way to do so.

However, right now, I can only access these values through a Context object, while executing a command, not from the outside. Duplicating Get/Set/Delete/Keys from context onto Shell is probably sufficient for this? Perhaps renaming to GetContextValue() etc to make it more explicit?

Windows Multiplechoice doesn't work

Using master. When using Windows the multiplechoice throws an exception.

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.")
    }
},

This code will reproduce the problem

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.