Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Question] How to use the Expect.BufStr()? #7

Open
samuel-phan opened this issue Mar 18, 2021 · 4 comments
Open

[Question] How to use the Expect.BufStr()? #7

samuel-phan opened this issue Mar 18, 2021 · 4 comments

Comments

@samuel-phan
Copy link

Description

I don't understand how to use the Expect.BufStr().

Let's say I have this command that prints this:

Here are your choices:
1) Go to Smith valley
2) Go to Victoria street
3) Go home
Your choice:  <-- wait for input here

If I write this in my code:

exp, _ := expect.NewExpect(myCmd)
exp.Expect("Your choice: ")
// exp.BufStr() is already empty at this line because the exp.Expect() matched and reset the buffer
// I can't parse my choices then

Question

How can I read the choices after the exp.Expect() call?

Environment

  • OS: macOS Big Sur 11.2.3
  • Shell: zsh
@samuel-phan
Copy link
Author

@grrtrr I saw that you contributed quite a bit in your fork. Do you have an idea how this could be achieved?

@grrtrr
Copy link
Contributor

grrtrr commented Mar 19, 2021

Not immediately, this is some time ago. Here are some examples, hope they may be of help: grrtrr@7603f50

@leemcloughlin
Copy link
Owner

Hi

I think you should be looking for a choice line matching inputs like:

  1. Go to Smith valley
    and
    Your choice

Something like this should match a choice line:
\d).*\n

Do that in a loop till you get "Your choice"

@samuel-phan
Copy link
Author

Hi guys, and thanks for your quick reply. Got a busy week, I couldn't take a look sooner.

@leemcloughlin I see what you mean, and it's true that I can make it work this way. But I think it'd be simpler to have a buffer from the last matched expect.

Let's look through a more concrete example:

Choose your authentication:  ^
1) Send phone text message   | this part is asked only once per day
2) Send push                 |
Authentication choice: 2     v

Choose your credentials:
1) Account: foo Credentials: admin
2) Account: foo Credentials: readonly
3) Account: bar Credentials: storage
4) Account: bar Credentials: readonly
Credentials choice: 3

I could totally do this:

var pushChoice int
pushRE := regexp.MustCompile(`(\d+)\).*push$`)
credentialsMap = make(map[string][]string)
credentialRE := regexp.MustCompile(`(\d+)\) Acccount: (\w+) Credentials: (\w+)`)
for {
    index, buff, _ := exp.Expect("Authentication choice: ", pushRE, "Credentials choice: ", credentialsRE)
    switch index {
    case 0:
        break
    case 1:
        // Use pushRE regexp to extract choice number
        pushChoice := pushRE.FindStringSubmatch(string(buff))[1]
    case 2:
        break
    case 3:
        // Use credentialRE regexp to extract choice and infos
        matches := credentialRE.FindStringSubmatch(string(buf))
        credentialsMap[matches[2]] = append(credentialsMap[matches[2]], buff)  // store it for example
    }
}

but it sounds more natural to me to try to detect first the prompt and use a buffer for the past lines to extract the choices now that I know what I am being asked (which is what we do as human):

index, _, _ := exp.Expect("Authentication choice: ", "Credentials choice: ")
if index == 0 {
    // read the exp.Buffer to extract the authentiation choices
} else if index == 1 {
    // read the exp.Buffer to extract the credentials choices
} 

What do you think?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants